Most efficient way to match (a few) strings in C?
c, embedded, match, string
Solution
The problem with hashing is that an arbitrary string entered by the user may generate the same hash as one of your matches and you'll execute the wrong stuff. For a search set as small as 10 I'd just stick to the `if-else` approach. Or use a string array and function pointer array (assuming all functions have the same signature) to select the function to execute.
char const *matches[10] = {"first", "second", ..., "tenth"};
void (*fn[10])(void) = {&do_first, &do_second, ..., &do_tenth};
for( i = 0; i < 10; ++i ) {
if( strcmp( str, matches[i] ) == 0 ) {
(*fn[i])();
}
}
Problem
Our system needs to accept user input from a terminal and match against a few known keyword strings (maybe 10). We don't have the space/computrons to do regexp etc., code needs to be tiny & quick. Now, the nasty way to do this is: ``` // str is null-terminated, assume we know it's safe/sane here if(!strncmp(str,"hello",5) { do_hello(); } else if(!strncmp(str,"world",5) { do_world(); } else { meh(); // Wasn't a match } ``` So, after a bit of googling & reading I'm being convinced that a nicer way is to pre-compute the hash of the various matches as an int, and then just use a case statement: ``` // Assume hash() stops at NULL switch(hash(str)) { case HASH_OF_HELLO: do_hello(); break; case HASH_OF_WORLD: do_world(); break; default: meh(); break; } ``` We can compute the *HASH_OF_match* at compile time. This seems potentially a faster / more elegant way to pick a string from a relatively small set. So - does this seem reasonable? / Is there a glaring problem with doing this? / Anyone got a more elegant way of doing it? As a footnote, this is the nicest looking hash algorithm I've seen this afternoon ;), credited to dan bernstein, it looks up to the job at hand. ``` unsigned int get_hash(const char* s) { unsigned int hash = 0; int c; while((c = *s++)) { // hash = hash * 33 ^ c hash = ((hash << 5) + hash) ^ c; } return hash; } ```