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

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


person Myrmidon    schedule 09.05.2017    source источник


Ответы (1)


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

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

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

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. Это взято из здесь.

person Mad Physicist    schedule 09.05.2017
comment
Спасибо за быстрый и информативный ответ. Теперь это имеет гораздо больше смысла. :) - person Myrmidon; 09.05.2017
comment
@ Дженс. Фиксированный. Вместо этого я использовал sizeof(((dictionary_t *)0)->word). - person Mad Physicist; 09.05.2017
comment
Не надо сюда бросать: strncmp((const char *)s ... - person alk; 09.05.2017
comment
@говорить. Ты прав. Изначально я сравнивал две структуры, и это пережиток. Также сделал диктовку const, пока я был на ней. - person Mad Physicist; 09.05.2017