bsearch() - поиск строки в массиве структур

У меня есть структура, которая выглядит так:

typedef struct dictionary_t{
    char word[30];
    int foo;
    int bar;
} dictionary_t;

Который образует упорядоченный массив:

dictionary_t dictionary[100];

Я хотел бы найти в этом массиве строку с помощью bsearch() и получить указатель на структуру. Пока это сработало:

dictionary_t* result;
char target[30] = "target";
result = bsearch(&target, dictionary, dict_length, sizeof(dictionary_t), (int(*)(const void*,const void*)) strcmp);

Однако это немного хакерство и работает только потому, что строка оказывается первым членом структуры. Что может быть лучшим способом найти строку в массиве структур и вернуть указатель на структуру?

1 ответ

Решение

Вы должны реализовать свою собственную функцию компаратора и передать ее. Самая важная (нетривиальная) вещь, о которой следует помнить, это то, что согласно стандарту,

Реализация должна гарантировать, что первый аргумент всегда является указателем на ключ.

Это означает, что вы можете написать компаратор, который сравнивает строку, такую ​​как target и dictionary_t объект. Вот простая функция, которая сравнивает ваши структуры со строкой:

int compare_string_to_dict(const void *s, const void *d) {
    return strncmp(s, ((const dictionary_t *)d)->word, sizeof(((dictionary_t *)0)->word));
}

Затем вы должны передать его по имени как обычный указатель на функцию bsearch:

result = bsearch(target, dictionary, dict_length, sizeof(dictionary_t), compare_string_to_dict);

Обратите внимание, что target не нужно передавать его адрес, так как он больше не насмехается над структурой.

Если вам интересно, sizeof(((dictionary_t *)0)->word) это идиоматический способ получения размера word в dictionary_t, Вы могли бы также сделать sizeof(dictionary[0].word) или определите константу, равную 30. Это происходит отсюда.

Другие вопросы по тегам