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