Recursive Linear Search in C debug - c

Problem:1
In this code if I search a number which is not in array it should display Value not found but I don't know it's not displaying that message instead everytime it's showing Found value in element -5I don't have any clue why it's happening.
#include<stdio.h>
#define SIZE 100
size_t linearSearch(const int array[], int key, size_t size);
int main(void)
{
int a[SIZE];
size_t x;
int searchKey;
size_t element;
for(x=0; x<SIZE; ++x){
a[x] = 2*x;
}
for(x=0; x<SIZE; ++x){
if(x%10 == 0){
puts("");
}
printf("%5d", a[x]);
}
puts("\n\nEnter integer search key:");
scanf("%d", &searchKey);
// attempt to locate searchKey in array a
element = linearSearch(a, searchKey, SIZE);
// display results
if(element != -1){
printf("Found value in element %d", element);
}
else{
puts("Value not found");
}
}
size_t linearSearch(const int array[], int key, size_t size)
{
if(size<0){
return -1;
}
if(key == array[size-1]){
return size-1;
}
return linearSearch(array, key, size-1);
}
Problem:2
I can't understood how
size_t linearSearch(const int array[], int key, size_t size)
function working specially these line
if(key == array[size-1]){
return size-1;
return linearSearch(array, key, size-1);

As everyone said that you have a little mistake that is, you should write if(size==0) not if(size<0).
let me explain what's going on recursively in linearSearch() function
size_t linearSearch(const int array[], int key, size_t size)
{
if(size == 0){
return -1;
}
else
if(key == array[size-1]){
return size-1;
}
else{
return linearSearch(array, key, size-1);
}
}
Suppose you gave an input 198 as searchkey.
When you calling linearSearch() function by the statement
element = linearSearch(a, searchKey, SIZE);
you are passing reference to array[], searchKey 198, and Size 100 as argument.
In linearSearch function first if statement if(size==0) checks if the size is equal to zero if not then else if statement runs.
in else if statement If(198 == array[100-1]) condition is checked.
and we see 198 is present in array[99] so the else if condition is true thus linearSearch function return the 99 as result.
Now lets see what happend if you input 55 which is not in the array list.
if(size==0) is not true so program will skip it and will go to the next statement.
if(55 == array[100-1] will be checked as its not true then linearSearch(array, 55, 100-1) will be called. again if(55==array[99-1]) will be checked.
at some point size will become 0. and the first if(size==0) statement will execute.

1) The main problem is if(size<0){. Conditional expression will always be false. because size_t is unsigned integer. So, it returns a random position with the values found(It's undefined behavior) by chance become a large numbers(e.g. -5 is 4294967291 as unsigned) without end(not found).
if(size<0){ should be if(size==0){
2) If key match the last element, returns its position. If not, repeat with a shorter one size. key not found if size is zero.

Just change the if statement from if(size<0) to if(size==0)your code will work.

Related

Why is my code for binary search not working? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 14 days ago.
Improve this question
The code doesn't print the position of elements at the far left or right positions. I've looked at it for hours please help me find out whats wrong.
type here
#include<stdio.h>
#define max 50
void binarysearch(int l,int r,int key,int num[])
{
int mid=(l+r)/2;
if(num[mid]==key)
{
printf("Element found at location %d",mid+1);return;
}
else if(num[mid]<key)
{
return binarysearch(l,mid-1,key,num);
}
else
{
return binarysearch(mid+1,r,key,num);
}
printf("Element not found ");return;
}
int main()
{
int i,key,size,num[max];
printf("Enter size of array : ");scanf("%d",&size);
for(i=0;i<size;i++)
{
printf("Enter the element : ");scanf("%d",&num[i]);fflush(stdin);
}
printf("Enter key to search : ");scanf("%d",&key);
binarysearch(0,size-1,key,num);
return 0;
}
I'm gonna go insane. Send help
For starters you need to check within the function whether r is not less than l. Without this check the function can invoke undefined behavior.
These if statements are incorrect
else if(num[mid]<key)
{
return binarysearch(l,mid-1,key,num);
}
else
{
return binarysearch(mid+1,r,key,num);
}
For example if num[mid] is less than key then you need to call the function recursively like
return binarysearch(mid+1, r, key,num);
otherwise like
return binarysearch(1, mid-1,key,num);
Pay attention to that the function should not output any message. It should returns to the caller either the index of the found element or for example -1 if the searched value is not found in the array. It is the caller of the function that will decide whether to output a message.
It would be much better to declare the function at least like
int binarysearch( const int num[], int size, int key );
or like
int * binarysearch( const int num[], size_t size, int key );
For the last declaration the function returns a pointer to the found element or NULL.
Here is a demonstration program that shows the function implemengtation.
#include <stdio.h>
int * binarysearch( const int a[], size_t n, int key )
{
if (n == 0)
{
return NULL;
}
else if (a[n / 2] < key)
{
return ( int * )binarysearch( a + n / 2 + 1, n - n / 2 - 1, key );
}
else if ( key < a[n / 2] )
{
return ( int * )binarysearch( a, n / 2, key );
}
else
{
return ( int * )a + n / 2;
}
}
int main( void )
{
int a[] = { 1, 3, 5 };
const size_t N = sizeof( a ) / sizeof( *a );
for (int key = 0; key < a[N - 1] + 2; ++key)
{
int *p = binarysearch( a, N, key );
if (p != NULL)
{
printf( "The value %d is found at position %td.\n", key, p - a );
}
else
{
printf( "The value %d is not found.\n", key );
}
}
}
The program output is
The value 0 is not found.
The value 1 is found at position 0.
The value 2 is not found.
The value 3 is found at position 1.
The value 4 is not found.
The value 5 is found at position 2.
The value 6 is not found.
Pay also attention to that this call in your program
fflush(stdin);
has undefined behavior.
You've simply wrote the code in opposite places.
The right code would be:
#include<stdio.h>
#define max 50
void binarysearch(int l,int r,int key,int num[])
{
int mid=(l+r)/2;
if(num[mid]==key)
{
printf("Element found at location %d",mid+1);return;
}
else if(num[mid]<key)
{
// Wrong Code
// you've done the opposite operation
//return binarysearch(l,mid-1,key,num);
// Correct Code
return binarysearch(mid+1,r,key,num);
}
else
{
// Wrong Code
// same problem as before.. you've done opposite operation
//return binarysearch(mid+1,r,key,num);
// Correct Code
return binarysearch(l,mid-1,key,num);
}
printf("Element not found ");return;
}
int main()
{
int i,key,size,num[max];
printf("Enter size of array : ");scanf("%d",&size);
for(i=0;i<size;i++)
{
printf("Enter the element : ");scanf("%d",&num[i]);fflush(stdin);
}
printf("Enter key to search : ");scanf("%d",&key);
binarysearch(0,size-1,key,num);
return 0;
}
Hope this would help.
There are two problems:
1- Your arguments about the recursive called functions are wrong.
2- The recursive call is infinite.
You should change your binarysearch function to this:
void binarysearch(int l, int r, int key, int num[])
{
int mid=(l+r)/2;
if(l > r)
{
printf("Element not found");
return;
}
if(num[mid] == key)
{
printf("Element found at location %d", mid+1);
return;
}
if(num[mid] < key)
{
return binarysearch(mid+1, r, key, num);
}
return binarysearch(l, mid-1, key, num);
}

last number in a function array

I want to write a function where I have a given array and number N. The last occurrence of this number I want to return address. If said number cannot be found I want to use a NULL-pointer
Start of the code I've made:
int main(void) {
int n = 3;
int ary[6] = { 1,3,7,8,3,9 };
for (int i = 0; i <= 6; i++) {
if (ary[i] == 3) {
printf("%u\n", ary[i]);
}
}
return 0;
}
result in command prompt:
3
3
The biggest trouble I'm having is:
it prints all occurrences, but not the last occurrence as I want
I haven't used pointers much, so I don't understand how to use the NULL-pointer
I see many minor problems in your program:
If you want to make a function, make a function so your parameters and return types are explicit, instead of coding directly in the main.
C arrays, like in most languages, start the indexing at 0 so if there are N element the first has index 0, then the second has 1, etc... So the very last element (the Nth) has index N-1, so in your for loops, always have condition "i < size", not "i <= size" or ( "i <= size-1" if y'r a weirdo)
If you want to act only on the last occurence of something, don't act on every. Just save every new occurence to the same variable and then, when you're sure it was the last, act on it.
A final version of the function you describe would be:
int* lastOccurence(int n, int* arr, int size){
int* pos = NULL;
for(int i = 0; i < size; i++){
if(arr[i] == n){
pos = &arr[i]; //Should be equal to arr + i*sizeof(int)
}
}
return pos;
}
int main(void){
int n = 3;
int ary[6] = { 1,3,7,8,3,9 };
printf("%p\n", lastOccurence(3, ary, 6);
return 0;
}
Then I'll add that the NULL pointer is just 0, I mean there is literally the line "#define NULL 0" inside the runtime headers. It is just a convention that the memory address 0 doesn't exist and we use NULL instead of 0 for clarity, but it's exactly the same.
Bugs:
i <= 6 accesses the array out of bounds, change to i < 6.
printf("%u\n", ary[i]); prints the value, not the index.
You don't actually compare the value against n but against a hard-coded 3.
I think that you are looking for something like this:
#include <stdio.h>
int main(void)
{
int n = 3;
int ary[6] = { 1,3,7,8,3,9 };
int* last_index = NULL;
for (int i = 0; i < 6; i++) {
if (ary[i] == n) {
last_index = &ary[i];
}
}
if(last_index == NULL) {
printf("Number not found\n");
}
else {
printf("Last index: %d\n", (int)(last_index - ary));
}
return 0;
}
The pointer last_index points at the last found item, if any. By subtracting the array's base address last_index - ary we do pointer arithmetic and get the array item.
The cast to int is necessary to avoid a quirk where subtracting pointers in C actually gives the result in a large integer type called ptrdiff_t - beginners need not worry about that one, so just cast.
First of all, you will read from out of array range, since your array last element is 5, and you read up to 6, which can lead in segmentation faults. #Ludin is right saying that you should change
for (int i = 0; i <= 6; i++) // reads from 0 to 6 range! It is roughly equal to for (int i = 0; i == 6; i++)
to:
for (int i = 0; i < 6; i++) // reads from 0 to 5
The last occurrence of this number I want to return as address.
You are printing only value of 3, not address. To do so, you need to use & operator.
If said number cannot be found I want to use a NULL-pointer
I don't understand, where do you want to return nullpointer? Main function can't return nullpointer, it is contradictory to its definition. To do so, you need to place it in separate function, and then return NULL.
If you want to return last occurence, then I would iterate from the end of this array:
for (int i = 5; i > -1; i--) {
if (ary[i] == 3) {
printf("place in array: %u\n", i); // to print iterator
printf("place in memory: %p\n", &(ary[i])); // to print pointer
break; // if you want to print only last occurence in array and don't read ruther
}
else if (i == 0) {
printf("None occurences found");
}
}
If you want to return an address you need yo use a function instead of writing code in main
As you want to return the address of the last occurence, you should iterate the array from last element towards the first element instead of iterating from first towards last elements.
Below are 2 different implementations of such a function.
#include <stdio.h>
#include <assert.h>
int* f(int n, size_t sz, int a[])
{
assert(sz > 0 && a != NULL);
// Iterate the array from last element towards first element
int* p = a + sz;
do
{
--p;
if (*p == n) return p;
} while(p != a);
return NULL;
}
int* g(int n, size_t sz, int a[])
{
assert(sz > 0 && a != NULL);
// Iterate the array from last element towards first element
size_t i = sz;
do
{
--i;
if (a[i] == n) return &a[i];
} while (i > 0);
return NULL;
}
int main(void)
{
int n = 3;
int ary[] = { 1,3,7,8,3,9 };
size_t elements = sizeof ary / sizeof ary[0];
int* p;
p = g(n, elements, ary); // or p = f(n, elements, ary);
if (p != NULL)
{
printf("Found at address %p - value %d\n", (void*)p, *p);
}
else
{
printf("Not found. The function returned %p\n", (void*)p);
}
return 0;
}
Working on the specified requirements in your question (i.e. a function that searches for the number and returns the address of its last occurrence, or NULL), the code below gives one way of fulfilling those. The comments included are intended to be self-explanatory.
#include <stdio.h>
// Note that an array, passed as an argument, is converted to a pointer (to the
// first element). We can change this in our function, because that pointer is
// passed BY VALUE (i.e. it's a copy), so it won't change the original
int* FindLast(int* arr, size_t length, int find)
{
int* answer = NULL; // The result pointer: set to NULL to start off with
for (size_t i = 0; i < length; ++i) { // Note the use of < rather than <=
if (*arr == find) {
answer = arr; // Found, so set our pointer to the ADDRESS of this element
// Note that, if multiple occurrences exist, the LAST one will be the answer
}
++arr; // Move on to the next element's address
}
return answer;
}
int main(void)
{
int num = 3; // Number to find
int ary[6] = { 1,3,7,8,3,9 }; // array to search
size_t arrlen = sizeof(ary) / sizeof(ary[0]); // Classic way to get length of an array
int* result = FindLast(ary, arrlen, num); // Call the function!
if (result == NULL) { // No match was found ...
printf("No match was found in the array!\n");
}
else {
printf("The address of the last match found is %p.\n", (void*)result); // Show the address
printf("The element at that address is: %d\n", *result); // Just for a verification/check!
}
return 0;
}
Lots of answers so far. All very good answers, too, so I won't repeat the same commentary about array bounds, etc.
I will, however, take a different approach and state, "I want to use a NULL-pointer" is a silly prerequisite for this task serving only to muddle and complicate a very simple problem. "I want to use ..." is chopping off your nose to spite your face.
The KISS principle is to "Keep It Simple, St....!!" Those who will read/modify your code will appreciate your efforts far more than admiring you for making wrong decisions that makes their day worse.
Arrays are easy to conceive of in terms of indexing to reach each element. If you want to train in the use of pointers and NULL pointers, I suggest you explore "linked lists" and/or "binary trees". Those data structures are founded on the utility of pointers.
int main( void ) {
const int n = 3, ary[] = { 1, 3, 7, 8, 3, 9 };
size_t sz = sizeof ary/sizeof ary[0];
// search for the LAST match by starting at the end, not the beginning.
while( sz-- )
if( ary[ sz ] == n ) {
printf( "ary[ %sz ] = %d\n", sz, n );
return 0;
}
puts( "not found" );
return 1; // failed to find it.
}
Consider that the array to be searched is many megabytes. To find the LAST match, it makes sense to start at the tail, not the head of the array.
Simple...

Infinite recursion: binary search & asserts

I'm writing an implementation of binary search in C and I'm getting infinite recursion for no apparent (to me) reason. Heres my code:
/*Orchestrate program*/
int main(int argc, char* argv){
int array[] = {1,2,3,3,3,6,7,8,9,9,20,21,22};
int length = 13;
int key = 23;
binary_search(key, array, 0, length - 1);
return 0;
}
int binary_search(int key, int array[], int first_index, int last_index){
int middle;
middle = (first_index + last_index)/2;
if (first_index == last_index){
if (array[middle] == key){
printf("%d has been found at position %d\n", key, middle+1);
}
printf("item not found");
}
else if (key > array[middle]){
binary_search(key, array, middle, last_index);
}
else if (key < array[middle]){
binary_search(key, array, first_index, middle);
}
}
Based on the value of my key in main, I guess the problem lies in the first else if, but I'm not sure why. If I were to remove the first_index == last_index line, the algorithm works fine but only when the item is in the array. If the item isn't in the array, I naturally get infinite recursion.
Also, I tried to fix this problem by removing the first_index == last_index line and placing a return -1; at the end of the function, but I get the same problem that I am getting now.
EDIT:
Putting together pieces of advice I received from a few different users, I came to the following solution (fixed off by one errors and un-nested decisions):
void binary_search(int key, int array[], int first_index, int last_index){
int middle;
middle = (first_index + last_index)/2;
if (array[middle] == key){
printf("%d has been found at position %d\n", key, middle+1);
}
if (first_index == last_index){
printf("item not found");
}
else if (key > array[middle]){
binary_search(key, array, middle + 1, last_index);
}
else if (key < array[middle]){
binary_search(key, array, first_index, middle - 1);
}
}
I have a follow-up question: Could there have been a way to use asserts to assist me in finding this solution myself? (I'm just learning about asserts so I'm wondering where I can apply them)
You search ever smaller ranges of a sorted array. The bounadries of your array are inclusive.
The base case of your recursion is: If the range is empty, the key is not found. Or, in code:
if (first_index > last_index){
printf("Not found\n");
}
You should calculate and compare the middle element of your range only after you have established that the range is not empty. In that case, you have three outcomes:
The middle element is the key: bingo!
The middle element is smaller than the key: Search the right half of the array and exclude the middle element, which we have already checked.
The middle element is larger than the key: Ditto, but with the left half.
Putting this all together:
void binary_search(int key, int array[], int first_index, int last_index)
{
if (first_index > last_index){
printf("Not found\n");
} else {
int middle = (first_index + last_index) / 2;
if (array[middle] == key) printf("%d at index %d\n", key, middle);
if (key > array[middle]){
binary_search(key, array, middle + 1, last_index);
} else {
binary_search(key, array, first_index, middle - 1);
}
}
}
This function still has two things that nag me:
A function that prints the index is of little practical use. The printing should be done by the client code, i.e. by the code that calls the function. Return the found index or a special value for "not found" instead.
The range has inclusive bounds. That's not very C-like. In C, a range is usually described by an inclusive lower and an exclusive upper bound. That's how array indices and for loops work. Following this convention means that your client code doesn't have to do the awkward length - 1 calculation.
So here's a variant that returns the index or -1 if the key is not in the array:
int binary_search1(int key, int array[], int first_index, int last_index)
{
if (first_index < last_index){
int middle = (first_index + last_index) / 2;
if (array[middle] == key) return middle;
if (key > array[middle]){
return binary_search1(key, array, middle + 1, last_index);
} else {
return binary_search1(key, array, first_index, middle);
}
}
return -1;
}
and test it with:
int main()
{
int arr[6] = {3, 4, 6, 8, 12, 13};
int i;
for (i = 0; i < 20; i++) {
int ix = binary_search(i, arr, 0, 6);
if (ix < 0) {
printf("%d not found.\n", i);
} else {
printf("%d at index %d.\n", i, ix);
}
}
return 0;
}
Note that your original array has duplicate entries. This is okay, but you will get the index of any of the duplicate values, not necessarily the first one.
Your function should look like this:
void binary_search(int key, int array[], int first_index, int last_index){
int middle;
middle = (first_index + last_index)/2;
if (array[middle] == key){
printf("%d has been found at position %d\n", key, middle+1);
}
else if (first_index == last_index) {
printf("item not found");
}
else if (key > array[middle]){
binary_search(key, array, middle + 1, last_index);
}
else {
//assert (key < array[middle]); // feel free to uncomment this one and include the assert library if you want
binary_search(key, array, first_index, middle - 1);
}
}
In other words, increment or decrement middle appropriately in the recursive call.
This is important, because, for example, when you reduce to size 2 for your search and middle is your first element, then effectively you are not changing the dimension of the array in the recursive calls.
I also changed your function to void since you are not returning anything.

Function in C not returning proper value

I'm trying to check whether an array is sorted without using a loop. It's working properly, i,e. if I have an array with elements that are in ascending order, the printf executes, since I get "Sorted." But
printf("Array 1 returns: %d \n\n", sortCheck(arr1, SORTED1));
returns 0? Why is this?
Thanks. Here's the entire code.
#include<stdio.h>
const int SORTED1 = 5;
int sortCheck (int arr[], int arrSize);
int indexCounter = 0;
int main()
{
int arr1[] = {1,2,3,4,5};
printf("Array 1: \n");
printf("Array 1 returns: %d \n\n", sortCheck(arr1, SORTED1));
indexCounter = 0;
return 0;
}
int sortCheck(int arr[], int arrSize)
{
if ( (arr[indexCounter]==arr[arrSize-1]) && (indexCounter==arrSize-1) )
{
printf("Sorted. \n");
return 1;
}
if ( arr[indexCounter] <= arr[indexCounter+1] )
{
indexCounter++;
sortCheck(arr, arrSize);
}
else
{
printf("Not sorted.");
return 0;
}
}
You are seeing undefined behavior due to a missing return statement.
if ( arr[indexCounter] <= arr[indexCounter+1] )
{
indexCounter++;
// Problem. Missing return.
sortCheck(arr, arrSize);
}
Change the offending line to:
return sortCheck(arr, arrSize);
Following changes should print value 1
int sortCheck(int arr[], int arrSize)
{
int val = 0;
if ( (arr[indexCounter]==arr[arrSize-1]) && (indexCounter==arrSize-1) )
{
printf("Sorted. \n");
return 1;
}
if ( arr[indexCounter] <= arr[indexCounter+1] )
{
indexCounter++;
val = sortCheck(arr, arrSize);
return val;
}
else
{
printf("Not sorted.");
return 0;
}
}
the sortCheck() function does not check if the array is sorted.
there are two reasons for this.
1) when the recursive call was invoked, the returned value is being ignored, so the information about a particular byte pair is lost.
2) the index (arrSize) is always passed, rather than the offset to the current byte index
I.E. the whole sortCheck() function needs to be re-designed.
Using a debugger (or a printf( of the parameters) in the path that calls the recursive sortCheck() would have revealed that fact.

Write the definition of a function, isReverse

Write the definition of a function, isReverse , whose first two parameters are arrays of integers of equal size, and whose third parameter is an integer indicating the size of each array. The function returns true if and only if one array is the reverse of the other. ("Reverse" here means same elements but in reverse order.)
int isReverse(int array1[], int array2[], int size)
{
int i;
for (i=0;i<size;i++)
{
if(array1[i] == array2[size-1])
return 0;
else
return 1;
}
}
i keep getting an error. whats wrong with it.
When you return from within any block in the function the function execution ends there, so in your case you are returning from function even when the first elements of the arrays are matching which is not correct, you should check whole array and then return from the function in the end, check the code below:
int isReverse(int array1[], int array2[], int size)
{
int i,status=1;
for (i=0;i<size;i++) //Size is the length of the array? if yes than you need -1 from it.
{
if(array1[i] == array2[size])
{
status=0;
--size;
}
else
return 1;
}
return status;
}
Moreover, size-1 does not change the value of the variable size itself hence size will remain same throughout the loop, use --size this will decrement the value of actual variable hence decrementing it by one every time.
The variable "size" never changes, so you're always checking elements of array1 against the last element of array2.
Since this sounds like a homework problem, I'll let you see if you can go from there.
This is how I did it.
int isReverse(int array1[], int array2[], int SIZE)
{
for( int counter = 0; counter <= SIZE/2; counter++ )
if(array1[counter] != array2[SIZE-counter] || array2[counter] != array1[SIZE-counter])
return 1;
return 0;
}
You are just comparing the value at index i with a constant SIZE-1. Instead you want to compare the value at i with the comparison array's size-i. So each time the counter increments it compares with the opposite array's size-i. And you only have to do this for half of the array.
The return value is wrong because you are checking only 1 value from each array, not all of them. What you want to do is something like this.
for (i=0;i<size;i++)
{
if(!(array1[i] == array2[size-i-1]))
return 0;
}
return 1;
Basically you go through the array one by one, if any of the values are not the same as the appropriate value on the other array, it is not a reverse, so we return 0. If we get out of the for loop without going through the if, it means they are reverses so we return 1.
int isReverse(int array1[], int array2[], int size)
{
int flag = 0;
for (int i=0;i<size;i++)
{
if(array1[i] != array2[size-1]){
flag = 1;
break;
}
return flag;
}
}
In the code you have kept the return statement inside the loop... keep the return statement outside the loop and try
int isReverse(int a[], int b[], int n)
{
int i = 0;
while (i<n)
{
if (a[i] != b[n-i-1]) {return 0; break;}
else i++;
}
return 1;
}
anw this was the correct answer.
bool isReverse(int array1[], int array2[],int size)
{
int i=0;
for (int k=0;k<size;k++){
if (array1[k]==array2[size-k-1]){
i++;
}
}
if (i==size){
return true;
}else{
return false;
}
}

Resources