实现字符串到整数查找的快速且可维护的方法 table

Fast and maintainable way of implementing string to integer lookup table

我可以找到许多关于如何将整数映射到字符串常量的问题,以及明显的解决方案

char const* strings[] = {"Foo", "Bar", ...};

现在,假设我想要反转:我有字符串 "Bar",并且想要 1。我的字符串最多 4 个字符,ascii null 不是有效值。有 64 个整数可以将值映射到。我是否必须编写一个带有字符串比较的长 if-else 结构,还是有更好的方法。

为了澄清,我更喜欢不需要运行时初始化的解决方案,从 C++17 开始,这使得 ti 无法使用 std::mapstd::unordered_map

你应该使用 std::map 除非你需要 better/custom。

std::map<std::string, int> stringToPos;

stringToPos["Foo"] = stringToPos.size(); // there's other ways to init the map, but you can fill it up this way too
stringToPos["Bar"] = stringToPos.size();
stringToPos["Bleh"] = stringToPos.size();

std::cout << stringToPos["Bleh"] << std::endl;

填充地图的另一个选项是:

for(auto s:{"foo","bar","bleh"})
{
    stringToPos[s] = stringToPos.size();
}

如果您可以使用 c++17,我会使用带有 string_viewunordered_map。像

#include <iostream>
#include <string_view>
#include <unordered_map>

int main(){

    std::array<char const*,2> strings = { "Foo", "Bar" };
    std::unordered_map<std::string_view,int> map;
    for( int i = 0 ; i != strings.size(); ++i  )
        map[strings[i]] = i;

    std::cout << map["Foo"];
}

查看工作版本 here:

My strings are up to 4 characters and ascii null is not a valid value.

在此条件下,您可以将字符串转换为整数,并使用您最喜欢的编译时整数到整数映射。

例如,switch:

#include <cstddef>
#include <cstdint>

namespace detail {
    constexpr std::uint64_t string_as_int(const char* string) noexcept {
        std::uint64_t result = 0;
        std::uint64_t i = 0;
        for (; i < 4 && *string; ++string, ++i) {
            result |= static_cast<std::uint64_t>(static_cast<unsigned char>(*string)) << (i * 8u);
        }
        return result;
    }

    constexpr std::uint64_t operator ""_h(const char* string, std::size_t) noexcept {
        return string_as_int(string);
    }
}

constexpr int lookup(const char* string) {
    using detail::operator ""_h;
    switch (detail::string_as_int(string)) {
        case "Foo"_h: return 1;
        case "Bar"_h: return 2;
        default: return 0;
    }
}