在 C 中匹配(一些)字符串的最有效方法?

2024-02-29

我们的系统需要接受来自终端的用户输入,并与一些已知的关键字字符串(可能是 10 个)进行匹配。

我们没有空间/计算机来执行正则表达式等,代码需要小而快。

现在,最糟糕的方法是:

   // 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
   }

因此,经过一番谷歌搜索和阅读后,我确信更好的方法是将各种匹配的哈希值预先计算为 int,然后只使用 case 语句:

// 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;
}

我们可以在编译时计算*HASH_OF_match*。这似乎是一种从相对较小的集合中挑选字符串的更快/更优雅的方法。

那么——这看起来合理吗? /这样做有明显的问题吗? / 有人有更优雅的方法吗?

作为脚注,这是我今天下午见过的最漂亮的哈希算法;),归功于 dan bernstein,它看起来很适合手头的工作。

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

散列的问题在于,用户输入的任意字符串可能会生成与您的字符串之一相同的散列。matches你会执行错误的事情。对于小至 10 的搜索集,我会坚持使用if-else方法。或者使用字符串数组和函数指针数组(假设所有函数具有相同的签名)来选择要执行的函数。

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])();
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 C 中匹配(一些)字符串的最有效方法? 的相关文章

随机推荐