error: control may reach end of non-void function - c

This error appeared to me when i was trying to compile a c file which contains a declaration of a linear search function
bool search(int value, int values[], int n)
{
// TODO: implement a searching algorithm
for(int d = 0;d<n;d++){
if(n<0){
return false;
}
else if(values[d]==value){
return true;
}
else{
return false;
}
}
}
What is wrong with my code? Please help.

Some problems with the code:
The method have a path that don't return anything, as commented, when parameter n = negative number or 0
The for-loop don't do anything, will only execute one time and exit for one of the conditions. It would only work correctly when the first element is the element searched, in any other case only check the first element and return (without correct info of present or not). Test with array int values[] = { 1, 2, 3, 4, 5 }; and search 3, your code would not found this value.
If you're searching for a specific value the code is:
bool search(int value, int values[], int n) {
for (int d = 0; d < n; d++) {
if (values[d] == value) {
return true;
}
}
return false;
}

The problem is the argument n passed to the function is n <= 0. The loop never executes and the function finishes without returning any value.
To fix it put the if(n <= 0) statement before the for loop.

If the 'for' loop doesn't get to do any iterations you won't be able to return anything from the function. Maybe add an edge case like
if(n <=0 )
return false;
before the loop.

d is incremented in the for loop until it equals the value of n. At that point, the code beyond the for loop is executed.
Being that there are no instructions beyond the for loop, the function returns to the caller. The error occurs due to there being no (boolean) value returned from the function in this case.
The error can be avoided by following Rule #1 of the Mahonri List Of Rules For Writing Maintainable C Code. Example:
bool search(int value, int values[], int n)
{
bool rCode=false;
// TODO: implement a searching algorithm
for(int d = 0;d<n;d++)
{
if(n<0)
{
goto CLEANUP;
}
else if(values[d]==value)
{
rCode=true;
goto CLEANUP;
}
else
{
goto CLEANUP;
}
}
CLEANUP:
return(rCode);
}

Related

why is this recursive function doesn't return 'counter' value?

int rec(int k)
{
static int temp = 0, counter = 0;
if(!k) return counter;
if(k%2 == 0){
counter++;
temp = rec(k/2);
}
if(k%2){
counter++;
temp = rec(k-1);
}
}
This function is supposed to get a number k and check how many operations are needed to get k to 0 only by multiplying by 2 or by adding 1.
this function works fine but returns zero instead of the last value in the counter. I tried to debug it, and I saw the counter value increasing, but after getting to the value it is supposed to return, the function goes back to complete all the calls, and returns 0.
I fixed it by making counter global and returning nothing, but my questions are:
Is there a way to fix it as it is with the counter inside the function?
Why is this function returning zero at the end?
Here's a nice recursive function that doesn't declare any variables at all, it's purely recursive!
int get_steps_to_zero(int n)
{
// Deal with negative values
if (n < 0) n *= -1;
if (n == 0) {
// Base case: we have reached zero
return 0;
} else if (n % 2 == 0) {
// Recursive case 1: we can divide by 2
return 1 + get_steps_to_zero(n / 2);
} else {
// Recursive case 2: we can subtract by 1
return 1 + get_steps_to_zero(n - 1);
}
}
get_steps_to_zero(457);
> 13
Others have addressed the general recursion issue, yet there remains a ...
Corner case
"this function works fine" --> Not quite.
The algorithm is an infinite loop for rec(-1) as it attempts -1 --> -2 --> -1 --> -2 ...
A better approach would sometimes add 1.
if(k%2) {
counter++;
// temp = rec(k-1);
temp = rec(k + (k < 0 ? 1 : -1));
}
This also well handles non-2's complement issue.
I will try to show a new side to this discussion,
Recursion is like a chain,
This means that any function can receive a value from its child and return a value to its parent.
In your program you are trying to return a value from the last child to the first parent,
So your program must have all links in the chain receive and send value in order.
But in your code you return a value only in the last call, and all other calls do not return this value back.
Your stop condition is here:
if(!k) return counter;
Only the last call enters this scope, but other calls do not reach any return statement.
they get to here:
if(k%2 == 0){
counter++;
temp = rec(k/2);
}
if(k%2){
counter++;
temp = rec(k-1);
here there is no return statement.
your compiler will warning you like this:
"warning: control reaches end of non-void function".
but your program will compile so it return zero like all non-void functions without return.
So if you want this program to work make it like Randomblock1, or like this:
int rec(int k)
{
static int counter = 0;
if(!k){
return counter;
}
else if(k%2 == 0){
counter ++;
counter += rec(k/2);
}
else{
counter++;
counter += rec(k-1);
}
return counter;
}
But this program also do not work well, what is the reason?
The reason is because you used by static variable.
It's a little hard to explain, but you can't use this recursion with a static variable, so add a patch to this line:
static int counter = 0;
like this
int counter = 0;
I hope what I wrote will be understandable

Is there a better way to exit all recursive functions at once, rather than one by one?

Is there a better way to exit all of the recursive iterations immediately after the if(a == b) condition is met, instead of having to include lines 7 and 8 in their current form? Without lines 7 and 8 as they currently are, it seems to exit merely the last iteration.
bool recursive(int a, int b) {
if(a == b)
return true;
for(int i = 0; i < count; i++)
if(locked[b][i] == true)
if(recursive(a, i) == true)
return true;
return false;
}
It's not really critical, but I'd like to spare lines whenever possible. Any ideas?
I would probably write this like so:
bool recursive(int a, int b) {
bool result = (a == b);
for (int i = 0; i < count && !result; i++) {
result = (locked[b][i] && recursive(a, i));
}
return result;
}
Introduction of a variable to hold the working result of the function allows for testing that result as part of the condition for performing a loop iteration. That way you can terminate the loop as soon as the result flips from false to true, yet you don't need any code to distinguish after the fact between the two possible reasons for loop termination.
Yes. You could use a bit obscure functionality of C named longjmp.
It allows to jump back a stack over multiple function calls. A bit similar to throw in C++.
Firstly, return environment is created with setjmp().
It returns 0 if to was a first call to setjmp().
Otherwise it returns a value set by longjmp() called deeper in the recursive call.
#include <stdio.h>
#include <setjmp.h>
void slowrec(int n) {
if (n == 0) {
puts("done");
} else {
puts("go down");
slowrec(n - 1);
puts("go up");
}
}
jmp_buf env;
void fastrec(int n) {
if (n == 0) {
puts("done");
longjmp(env, 1);
} else {
puts("go down");
fastrec(n - 1);
puts("go up");
}
}
int main() {
puts("-- slow recursion --");
slowrec(5);
puts("-- longjmp recursion --");
if (setjmp(env) == 0) {
fastrec(5);
}
return 0;
}
produces:
-- slow recursion --
go down
go down
go down
go down
go down
done
go up
go up
go up
go up
go up
-- longjmp recursion --
go down
go down
go down
go down
go down
done
For original problem the code may look like this:
jmp_buf env;
void recursive_internal(int a, int b) {
if (a == b) longjmp(env, 1); // true
for(int i = 0; i < count; i++)
if(locked[b][i])
recursive_internal(a, i);
}
bool recursive(int a, int b) {
if (setjmp(env) == 0) {
recursive_internal(a, b);
// left without triggering long jump
return false;
}
// returned with longjmp
return true;
}
Note that there is no return value in recursive_internal because either a==b condition is met and longjmp was taken as it was the only way true could be returned. Otherwise, condition was never met and the algorithm exited via return false.

CS50 Pset 3 Finding the Needle

I realised that when I included the "else return false" in my bool search, it will never be able to "find the needle". Conversely, if I were to remove that part, the program works fine. It is able to find 2008 and not find 2013. Any idea why is this so?
/**
* helpers.c
*
* Computer Science 50
* Problem Set 3
*
* Helper functions for Problem Set 3.
*/
#include <cs50.h>
#include "helpers.h"
/**
* Returns true if value is in array of n values, else false.
*/
//value = needle , values[] = haystack, n = size
bool search(int value, int values[], int n)
{
// TODO: implement a searching algorithm
if(n<0)
return false;
for(int i=0;i<n;i++)
{
if(value == values[i])
{
return true;
}
else
{
return false;
}
}
return false;
}
/**
* Sorts array of n values.
*/
void sort(int values[], int n)
{
// TODO: implement an O(n^2) sorting algorithm
return;
}
Look at the code carefully:
for(int i=0;i<n;i++)
{
if(value == values[i])
{
return true;
}
else
{
return false;
}
}
The loop body always returns from the function - thus it will only run once (assuming n > 0). This is the same as testing whether value is in the first position of the haystack.
If you take out the else branch, the code in the loop body only returns when the value is found. If it's not found, it will check the next element, and the next, etc., until either you find it or you run out of elements.
I think you should implement sort function first . the search will not work without sort . if you try the above code with needle say 1 and you but 1 in the beginning if haystack it will return true . but if you put 1 in the second of the haystack it will return false even you are looking for 1 .

Can't return the correct int in C

i'm using this function (quicksort algorithm) and im
trying to get the total relocations also. In order to collect as much statitics i can i have to execute the function many times using a for loop, so after the end of the algorithm i must make the static variable equal to zero after copying it to a non-static variable and return it. Instead i always get a 0 return.
Please help me to not get a 0 grade too :P Thanks
int quicksort(int left, int right, int *p)
{
static int staticrelocations=0;
int i,j,mid,x,temp,relocations;
if(left<right)
{
i=left;
j=right;
mid=(left+right)/2;
x=p[mid];
while(i<j)
{
while(p[i]<x)
i++;
while(p[j]>x)
j--;
if(i<j)
{
if(p[i]==p[j])
{
if(i<mid)
i++;
if(j>mid)
j--;
}
else
{
temp=p[i];
p[i]=p[j];
p[j]=temp;
staticrelocations++;
}
}
}
quicksort(left,j-1,p);
quicksort(j+1,right,p);
}
relocations=staticrelocations;
staticrelocations=0;
return relocations;
}
You recurse into quicksort(), and in the innermost invocation you set staticrelocations = 0 before returning its former value. However, in the outer quicksort(), you ignore the return value of the inner quicksort. The outer quicksort returns the zeroed staticrelocations. Instead, you should go like this:
int quicksort()
{
int relocs = 0;
/* function logic */
if (/*did a new relocation*/)
relocs++;
relocs += quicksort(); //inner quicksort recursively
return relocs;
}

Collatz chain recursive function C

I am trying to create some code that when given a starting number attempts to find the length of the corresponding collatz chain.
I was hoping to do this recursively and this is what I have so far :
#include stdio.h
int collatz(int number, int count)
{
if(number == 1)
{
return count;
}
if(number%2==0)
{
number = number/2;
collatz(number, count+1);
}
else
{
number = number*3+1;
collatz(number,count+1);
}
return 0;
}
int main(void)
{
int stored=0;
int temp;
for(int i = 1;i<10;i++)
{
temp = collatz(i,1);
if(temp>stored)
{
stored = temp;
}
}
printf("%i\n",stored);
}
The problem is of course that the function eventually reaches its endpoint, but then gets returned as the length of the chain and this becomes the new number..
How can I structure this program so that when the count reaches its endpoint I can take this value as the output of the very first call?
You need to return the result of the recursive call. Right now you're ignoring the value of the recursive call and returning 0. Each recursive call should look like this:
return collatz(number, count+1);

Resources