Reputation: 279
I'm trying to do a binary sorting function using recursion. It works well with the values that exist in the list[]
structure array. However, when I punch in a value that I know is not inside the array, instead of returning -1, it returns garbage value. I traced the code using debugger in MVS but there might be (in fact, definitely is) something that I just can't see.
Can somebody tell me why it doesn't return -1?
#include<stdio.h>
#include<string.h>
#define MAX 20
typedef struct
{
char name[MAX] = "";
char surname[MAX] = "";
int id;
}patient;
int binarySearch(patient list[], char *target, int top, int bottom, int *comparisons)
{
int center;
center = (top + bottom) / 2;
if (strcmp(list[center].surname, target) == 0)
return center;
(*comparisons)++;
if (top == center || bottom == center)
return -1;
if (strcmp(list[center].surname, target) == 1)
return binarySearch(list, target, center - 1, bottom, comparisons);
if (strcmp(list[center].surname, target) == -1)
return binarySearch(list, target, top, center + 1, comparisons);
}
int main(void)
{
FILE *fi = fopen("patients.txt", "r");
if (fi == NULL)
printf("Problem opening file!");
else
{
patient list[MAX];
int i = 0, comparisons = 0, index;
char target[MAX] = "";
while (fscanf(fi, "%s %s %d", &list[i].name, &list[i].surname, &list[i].id) != EOF)
i++;
printf("Enter the surname of the patient (END to exit): ");
scanf("%s", target);
index = binarySearch(list, target, i, 0, &comparisons);
printf("%-15s %-15s %-15d\n", list[index].name, list[index].surname, list[index].id);
printf("%d comparisons\n", comparisons);
}
}
Upvotes: 1
Views: 100
Reputation: 153468
How to save time: 1) ensure compiler warnings are fully enabled. 2) Use a good compiler.
I'd expect the below to to generate a warning like " warning: control reaches end of non-void function", providing you good and faster feedback than stack-overflow.
if (strcmp(list[center].surname, target) == -1)
return binarySearch(list, target, top, center + 1, comparisons);
}
Other good compiler feedback "error: expected ':', ',', ';', '}' or '__attribute__' before '='"
typedef struct {
char name[MAX] = ""; // not valid to initialize.
"traced the code using debugger in MVS" --> leads me to wonder if you are compiling your C code as C++ code.
Upvotes: 1
Reputation: 726579
You get a garbage value because your conditionals at the end are non-exhaustive.
When strcmp
indicates that the first value is after the second value, is not required to return 1
. The only requirement is that it returns a positive number. Same goes for less then and negative one -1
. Therefore, your function may end up reaching the end without hitting return
, which is undefined behavior.
You need to change your chain of if
s to compare return values with zero. As an optimization, you should store comparison result once, and reuse it throughout your conditionals:
int binarySearch(patient list[], char *target, int top, int bottom, int *comparisons)
{
int center = (top + bottom) / 2;
(*comparisons)++;
int cmp = strcmp(list[center].surname, target);
if (cmp == 0)
return center;
if (top == center || bottom == center)
return -1;
if (cmp > 0)
return binarySearch(list, target, center - 1, bottom, comparisons);
else // cmp < 0 here
return binarySearch(list, target, top, center + 1, comparisons);
}
Also note that in order to account for the number of comparisons in an accurate way, (*comparisons)++
should happen before strcmp
call.
Upvotes: 4