从 C++ 中的字符串中解析键/值对

Parsing key/value pairs from a string in C++

本文关键字:值对 字符串 C++      更新时间:2023-10-16

我在 C++11 工作,没有 Boost。我有一个函数,它将包含一系列键值对的 std::string 作为输入,用分号分隔,并返回从输入构造的对象。所有密钥都是必需的,但可以按任意顺序排列。

下面是一个示例输入字符串:

顶部=0;底部=6;名称=福;

这是另一个:

名称=条形图;底部=20;顶部=10;

有相应的混凝土结构:

struct S 
{
    const uint8_t top;
    const uint8_t bottom;
    const string name; 
}

我已经通过在输入字符串上重复运行正则表达式来实现该函数,每个 S 成员一次,并将每个成员捕获的组分配给 S 的相关成员,但这闻起来很错误。处理这种解析的最佳方法是什么?

对于易于阅读的解决方案,例如,您可以使用std::regex_token_iterator和排序容器来区分属性值对(或者使用未排序的容器和std::sort)。

std::regex r{R"([^;]+;)"};
std::set<std::string> tokens{std::sregex_token_iterator{std::begin(s), std::end(s), r}, std::sregex_token_iterator{}};

现在属性值字符串在集合tokens中按字典顺序排序,即第一个是Bottom,然后是Name,最后一个是Top

最后,使用简单的std::string::findstd::string::substr来提取字符串的所需部分。

现场示例

你关心性能还是可读性?如果可读性足够好,那么从这个问题中选择你最喜欢的split版本,然后我们开始:

std::map<std::string, std::string> tag_map;
for (const std::string& tag : split(input, ';')) {
    auto key_val = split(input, '=');
    tag_map.insert(std::make_pair(key_val[0], key_val[1]));
}

S s{std::stoi(tag_map["top"]),
    std::stoi(tag_map["bottom"]),
    tag_map["name"]};