首页 > 解决方案 > 用于打开字符串的哈希函数

问题描述

我正在尝试在哈希的帮助下对 C++ 中的字符串进行切换。我和这段代码之间变得很私人,所以我不想放弃并使用枚举,即使我最终只有 8 个字符串可以放入 switch case。

结合我在其他主题上看到的内容,我写了这个非常简单且不太可靠的功能,但这对于我想做的事情来说已经足够了,因为它不专业。

我的功能:

constexpr long hashstr (const string &str, int h=0)
{
    return !str[h] ? 55 : ( hashstr(str, h+1) *33) + (unsigned char)str[h];
}

然后我在这个非常简单的 main 函数中调用它(现在),但它不会编译,告诉我大小写错误(不是常量)。我不明白这个问题,因为对我来说 arg 中的字符串是一个常量,加上函数返回一个常量表达式。

我的主要:

int main (void) {

    string teststr;
    cout << "test string :::>  ";
    cin >> teststr;
    int tt = hashstr(teststr);
    cout << "res -->  " << tt << endl;

    switch ( hashstr(teststr) )
    {
    case hashstr("rosathefloridaturtle") :
        cout << "ROSA OK" << endl;
        break;

    default:
        cout << "ERROR" << endl;
        break;
    }

    return EXIT_SUCCESS;
}

希望你们中的一些人能告诉我我做错了什么......

标签: c++hash

解决方案


除非您使用的是 c++20 std::string,否则constexpr不能在hashstr.

返回的值大于 中可表示的值long,因为有符号算术溢出是您的代码无法在中使用的未定义行为constexpr

修复这两个问题会给出工作代码:

constexpr unsigned long hashstr (const std::string_view &str, int h=0)
{
    return !str[h] ? 55 : ( hashstr(str, h+1) *33) + (unsigned char)(str[h]);
}

请注意,如果您查看编译器输出,它可能会告诉您为什么您的表达式 is not constexpr,例如 clang 打印:

error: case value is not a constant expression
    case hashstr("rosathefloridaturtle") :
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:22:18: note: non-literal type 'const std::string' (aka 'const basic_string<char>') cannot be used in a constant expression
    case hashstr("rosathefloridaturtle") :

更改为std::string_view打印:

error: case value is not a constant expression
    case hashstr("rosathefloridaturtle") :
         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:9:47: note: value 97009635813568987014 is outside the range of representable values of type 'long'
    return !str[h] ? 55 : ( hashstr(str, h+1) *33) + (unsigned char)str[h];
                                              ^
<source>:9:29: note: in call to 'hashstr("rosathefloridaturtle", 8)'
    return !str[h] ? 55 : ( hashstr(str, h+1) *33) + (unsigned char)str[h];

推荐阅读