Hi I'm using bsearch to search for a target string in an array of string in a struct and return the index of the string. However, so far it is always returning NULL, and I'm pretty sure the way I'm getting the array index is also not right:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_ITEM_SIZE 10
#define MAX_NAME_LEN 20
typedef struct fruit_shelf_s {
char fruit_name[MAX_NAME_LEN + 1]; // +1 for null
int max_shelf_size;
int current_shelf_occupied;
} fruit_shelf_t;
typedef struct food_aisle_s {
fruit_shelf_t fruits[MAX_ITEM_SIZE];
} food_aisle_t;
void load_fruit_shelf(food_aisle_t *food_aisle, char sample[MAX_ITEM_SIZE][MAX_NAME_LEN]) {
for(int i; i < MAX_ITEM_SIZE; i++){
// buffer siE large enough so it does not over flow
strncpy(food_aisle->fruits[i].fruit_name, sample[i], strlen(sample[i])+1);
}
for (int j = 0; j < MAX_ITEM_SIZE; j++) {
printf("%s\n", food_aisle->fruits[j].fruit_name);
}
}
int myStrCmp(const void *s1, const void *s2) {
printf("myStrCmp: s1(%p): %s, s2(%p): %s\n", s1, *(char **)s1, s2, *(char**)s2);
return strcmp(*(char **) s1, *(char **) s2);
}
int binary_search(food_aisle_t* food_aisle, char *key){
char *buff = (char*)bsearch(&key, food_aisle->fruits, MAX_ITEM_SIZE, sizeof(food_aisle_t), (int(*)(const void*,const void*)) strcmp);
if(!buff){
int index = (buff - food_aisle->fruits[0].fruit_name) / sizeof(food_aisle->fruits[0]);
printf("Found key = %s at index = %d.\n", buff, index);
return 0;
} else {
printf("Did not find key = %s\n", key);
return -1;
}
}
char sample[MAX_ITEM_SIZE][MAX_NAME_LEN] = {"Apple", "Banana", "Orange", "Grape", "Strawberry", "Pineapple", "Jackfruit", "Lemon", "Lime", "Watermelon"};
int main () {
food_aisle_t food_aisle;
// Empty the array;
for (int i = 0; i < MAX_ITEM_SIZE; i++) {
memset(food_aisle.fruits[0].fruit_name, 0, sizeof(food_aisle.fruits[i].fruit_name));
}
// load the array
load_fruit_shelf(&food_aisle, sample);
char *key = "Orange";
int num = binary_search(&food_aisle, key);
if(num == 0){
printf("key found");
} else {
printf("key not found");
}
return(0);
}
So I'm not sure if the reason I'm getting NULL is because the string comparison function. So I wrote myStrCmp
to see if I can see the address of the array. But I got an Segfault:
Apple
Banana
Orange
Grape
Strawberry
Pineapple
Jackfruit
Lemon
Lime
Watermelon
Segmentation fault (core dumped)
I experimented with the arguments but I still get NULL:
// change to double pointer to reference to the array of string
char **buff = (char**)bsearch(&key, food_aisle->fruits, MAX_ITEM_SIZE, sizeof(food_aisle_t*), (int(*)(const void*,const void*)) strcmp);
// change the size type the searching element to sizeof(fruit_shelf_t*)
char *buff = (char*)bsearch(&key, food_aisle->fruits, MAX_ITEM_SIZE, sizeof(fruit_shelf_t*), (int(*)(const void*,const void*)) strcmp);
// change the size type the searching element to sizeof(char*)
char *buff = (char*)bsearch(&key, food_aisle->fruits, MAX_ITEM_SIZE, sizeof(char*), (int(*)(const void*,const void*)) strcmp);
As for getting the index of the string, I think the following idea should work, but I can't verify it since I can't get the correct search result. And sometimes I got negative values which is defiantly wrong:
index = (result_element_add - start_add_of_the_array) / size_of_the_objects_in_the_array
I tried the following alternatives:
// Try 1:
int index = (buff - food_aisle->fruits[0].fruit_name) / sizeof(food_aisle->fruits[MAX_ITEM_SIZE]);
returned:
Found key = (null) at index = 333807782.
key found
// Try 2:
int index = (buff - food_aisle->fruits[0].fruit_name) / sizeof(food_aisle->fruits[MAX_ITEM_SIZE].fruit_name);
returned:
Found key = (null) at index = -319396745.
key found
// Try 3:
int index = (buff - food_aisle->fruits[0].fruit_name) / sizeof(food_aisle->fruits[0]);
returned:
Found key = (null) at index = 233548559.
key found
What might be the issue for the bsearch()
usage here?