我已经检查了使用
gperf
将所有月份设置为 "January"、"Jan"、"JANUARY"、"JAN"、"january"、"jan" 等等时会发生什么。
struct months {
char *name;
int number;
};
#define TOTAL_KEYWORDS 69
#define MIN_WORD_LENGTH 3
#define MAX_WORD_LENGTH 9
#define MIN_HASH_VALUE 3
#define MAX_HASH_VALUE 218
/* maximum key range = 216, duplicates = 0 */
#ifdef __GNUC__
__inline
#else
#ifdef __cplusplus
inline
#endif
#endif
static unsigned int
hash (register const char *str, register size_t len)
{
static unsigned char asso_values[] =
{
219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 10, 80, 75, 95, 5,
125, 95, 219, 219, 5, 219, 95, 55, 45, 60,
60, 219, 85, 95, 50, 90, 25, 219, 219, 12,
219, 219, 219, 219, 219, 219, 219, 0, 40, 35,
35, 35, 40, 25, 219, 219, 0, 219, 10, 50,
0, 25, 15, 219, 15, 35, 30, 10, 25, 219,
219, 25, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219, 219, 219, 219, 219,
219, 219, 219, 219, 219, 219
};
return len + asso_values[(unsigned char)str[2]] + asso_values[(unsigned char)str[1]] + asso_values[(unsigned char)str[0]];
}
struct months *
in_word_set (register const char *str, register size_t len)
{
static struct months wordlist[] =
{
{""}, {""}, {""},
{"jan",1},
{""}, {""}, {""},
{"january",1},
{"Jan",1},
{""}, {""}, {""},
{"January",1},
{"jun",6},
{"june",6},
{""}, {""}, {""},
{"Jun",6},
{"June",6},
{""}, {""}, {""},
{"jul",7},
{"july",7},
{""}, {""}, {""},
{"Jul",7},
{"July",7},
{""}, {""}, {""},
{"apr",4},
{""},
{"april",4},
{""}, {""},
{"aug",8},
{""}, {""},
{"august",8},
{""},
{"Apr",4},
{""},
{"April",4},
{""}, {""},
{"Aug",8},
{""}, {""},
{"August",8},
{""},
{"nov",11},
{""}, {""}, {""}, {""},
{"november",11},
{""}, {""}, {""}, {""},
{"JAN",1},
{""}, {""}, {""},
{"JANUARY",1},
{"mar",3},
{""},
{"march",3},
{""}, {""},
{"Mar",3},
{""},
{"March",3},
{""}, {""},
{"may",5},
{""},
{"MAY",5},
{""}, {""},
{"May",5},
{""}, {""}, {""}, {""},
{"sep",9},
{""}, {""}, {""}, {""},
{"oct",10},
{"september",9},
{""}, {""},
{"october",10},
{"Nov",11},
{""}, {""}, {""}, {""},
{"November",11},
{""}, {""}, {""}, {""},
{"dec",12},
{""}, {""}, {""}, {""},
{"december",12},
{""}, {""}, {""}, {""},
{"feb",2},
{""}, {""}, {""}, {""},
{"february",2},
{""}, {""}, {""}, {""},
{"Oct",10},
{""}, {""}, {""},
{"October",10},
{"NOV",11},
{""}, {""}, {""}, {""},
{"NOVEMBER",11},
{""}, {""}, {""}, {""},
{"JUN",6},
{"JUNE",6},
{""}, {""}, {""},
{"Sep",9},
{""}, {""}, {""}, {""},
{"MAR",3},
{"September",9},
{"MARCH",3},
{""}, {""},
{"APR",4},
{""},
{"APRIL",4},
{""}, {""},
{"SEP",9},
{""}, {""}, {""}, {""},
{"Dec",12},
{"SEPTEMBER",9},
{""}, {""}, {""},
{"December",12},
{""}, {""}, {""}, {""},
{"DEC",12},
{""}, {""}, {""}, {""},
{"DECEMBER",12},
{""}, {""}, {""}, {""},
{"OCT",10},
{""}, {""}, {""},
{"OCTOBER",10},
{"JUL",7},
{"JULY",7},
{""}, {""}, {""},
{"AUG",8},
{""}, {""},
{"AUGUST",8},
{""},
{"Feb",2},
{""}, {""}, {""}, {""},
{"February",2},
{""}, {""}, {""}, {""},
{"FEB",2},
{""}, {""}, {""}, {""},
{"FEBRUARY",2}
};
if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
{
register unsigned int key = hash (str, len);
if (key <= MAX_HASH_VALUE)
{
register const char *s = wordlist[key].name;
if (*str == *s && !strcmp (str + 1, s + 1))
return &wordlist[key];
}
}
return 0;
}
我猜这很快,每个字符串只需要一个strcmp
。这正是GCC用于关键字检查的方法。
有一个非常好的gperf
介绍可以在这里找到。
gperf
以提前生成键的完美哈希。 - Shawngperf
看起来很有趣,但比下面回答中发现和发布的快速(且特定)哈希函数要大。我发表这篇文章是因为有人可能在某个时候、某个地方会觉得它有用。干杯!... - Fe2O3