在结构中的字符串数组中使用 bsearch 搜索目标字符串

Search for a target string using bsearch in an array of string in a struct

您好,我正在使用 bsearch 在结构的字符串数组中搜索目标字符串,return 字符串的索引。但是,到目前为止它总是 returning NULL,而且我很确定我获取数组索引的方式也不正确:

#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);
}

所以我不确定我得到 NULL 的原因是否是因为字符串比较函数。于是写了myStrCmp看能不能看到数组的地址。但是我遇到了段错误:

Apple
Banana
Orange
Grape
Strawberry
Pineapple
Jackfruit
Lemon
Lime
Watermelon
Segmentation fault (core dumped)

我尝试了这些参数,但我仍然得到 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);

关于获取字符串的索引,我觉得下面的思路应该可行,但是我无法验证,因为我无法得到正确的搜索结果。有时我得到负值,这显然是错误的:

index = (result_element_add - start_add_of_the_array) / size_of_the_objects_in_the_array

我尝试了以下替代方法:

// Try 1:
int index = (buff - food_aisle->fruits[0].fruit_name) / sizeof(food_aisle->fruits[MAX_ITEM_SIZE]);

return编辑:

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);

return编辑:

Found key = (null) at index = -319396745.
key found
// Try 3:
int index = (buff - food_aisle->fruits[0].fruit_name) / sizeof(food_aisle->fruits[0]);

return编辑:

Found key = (null) at index = 233548559.
key found

这里的 bsearch() 用法可能有什么问题?

  1. 您正在将 strcmp 传递给 bsearchstrcmp 接受 const char* 个参数,bsearch 期待带有 const void* 的函数。
  2. 您正在将 strcmp 传递给 bsearch。它比较字符串,而不是 fruit_shelf_t.
  3. 的元素
  4. myStrCmp 仍然比较字符串,而不是 fruit_shelf_tkey
  5. 不要转换 bsearch 的结果。不要将函数指针转换为不同的类型。
  6. for(int i; i < 未初始化 i...
  7. if(!buff){ 检查是否未设置 buff。应该是 if(buff){.

  1. 我认为没有理由将指针传递给 char *,只需传递密钥本身即可。
  2. 来自 bsearch 的回调将键与数组中的元素进行比较。

int myCompareFruits(const void *s1, const void *s2) {
    const char *key = s1;
    const fruit_shelf_t *b = s2;
    printf("%s %s\n", key, b->fruit_name);
    return strcmp(key, b->fruit_name);
}

int binary_search(food_aisle_t* food_aisle, char *key){
    fruit_shelf_t *buff = bsearch(key, food_aisle->fruits,
        MAX_ITEM_SIZE, sizeof(fruit_shelf_t), myCompareFruits);
    if (buff) {