C++ 从C++;

C++ 从C++;,c++,regex,parsing,c++11,C++,Regex,Parsing,C++11,我在C++11中工作,没有Boost。我有一个函数,它接受一个std::string作为输入,该字符串包含一系列用分号分隔的键值对,并返回一个由输入构造的对象。所有钥匙都是必需的,但可以是任意顺序 下面是一个输入字符串示例: Top=0;底部=6;Name=Foo 还有一个: 名称=条;底部=20;Top=10 有一个对应的混凝土结构: struct S { const uint8_t top; const uint8_t bottom; const string na

我在C++11中工作,没有Boost。我有一个函数,它接受一个std::string作为输入,该字符串包含一系列用分号分隔的键值对,并返回一个由输入构造的对象。所有钥匙都是必需的,但可以是任意顺序

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

Top=0;底部=6;Name=Foo

还有一个:

名称=条;底部=20;Top=10

有一个对应的混凝土结构:

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

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

您关心性能还是可读性?如果可读性足够好,那么从以下位置选择您最喜欢的
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"]};
std::map tag\u map;
for(const std::string&tag:split(输入“;”)){
自动键=分割(输入“=”);
tag_map.insert(std::make_pair(key_val[0],key_val[1]);
}
S{std::stoi(标记映射[“顶部]),
标准::stoi(标签地图[“底部]),
标记映射[“名称”]};

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

std::regex r{r'([^;]+;)”;
std::set tokens{std::sregex_token_迭代器{std::begin(s),std::end(s),r},std::sregex_token_迭代器{};
现在属性值字符串在集合
标记
中按字典顺序排序,即第一个是
底部
,然后是
名称
,最后一个是
顶部

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


什么是正则表达式?为什么你觉得它不对?在
上标记化
,然后在
=
上标记,我的第一个想法可能是使用find_first_of,但我也不认为使用正则表达式有什么好笑的。正则表达式是按照“Top=([0-9]+)”等的思路进行的。它似乎可能是错误的,因为我重复匹配同一个字符串,这似乎是浪费。或者也许它只是好的!我想我认为这类问题是经常遇到的,并且有一个规范的解决方案。我觉得答案可能是“不要使用正则表达式”。问题中似乎暗示您需要正则表达式解决方案。
std::regex r{R"([^;]+;)"};
std::set<std::string> tokens{std::sregex_token_iterator{std::begin(s), std::end(s), r}, std::sregex_token_iterator{}};