Reputation: 65
I have a struct that looks like this:
typedef struct dictionary_t{
char word[30];
int foo;
int bar;
} dictionary_t;
Which forms an ordered array:
dictionary_t dictionary[100];
I would like to search this array for a string using bsearch() and get a pointer to the struct. So far this has worked:
dictionary_t* result;
char target[30] = "target";
result = bsearch(&target, dictionary, dict_length, sizeof(dictionary_t), (int(*)(const void*,const void*)) strcmp);
However this is a bit of a hack and only works because the string happens to be the first member of the struct. What would be a better way to find a string within an array of structs and return a pointer to the struct?
Upvotes: 4
Views: 3615
Reputation: 114330
You should implement your own comparator function and pass it in. The most important (non-trivial) thing to keep in mind here is that according to the standard,
The implementation shall ensure that the first argument is always a pointer to the key.
This means that you can write a comparator that compares a string such as target
and a dictionary_t
object. Here is a simple function that compares your stucts to a string:
int compare_string_to_dict(const void *s, const void *d) {
return strncmp(s, ((const dictionary_t *)d)->word, sizeof(((dictionary_t *)0)->word));
}
You would then pass it by name as a normal function pointer to bsearch
:
result = bsearch(target, dictionary, dict_length, sizeof(dictionary_t), compare_string_to_dict);
Note that target
does not need to have its address passed in since it is no longer mocking a struct.
In case you are wondering, sizeof(((dictionary_t *)0)->word)
is an idiomatic way of getting the size of word
in dictionary_t
. You could also do sizeof(dictionary[0].word)
or define a constant equal to 30. It comes from here.
Upvotes: 5