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. Это происходит отсюда.