如何将字符串解析为std :: map并验证其格式? [英] How to parse a string into std::map and validate its format?
问题描述
我想将像"{{0, 1}, {2, 3}}"
这样的字符串解析为std::map
.我可以使用<regex>
库编写一个用于解析字符串的小函数,但是我不知道如何检查给定的字符串是否为有效格式.如何验证字符串的格式?
I'd like to parse a string like "{{0, 1}, {2, 3}}"
into a std::map
. I can write a small function for parsing a string using <regex>
library, but I have no idea how to check whether a given string is in a valid format. How can I validate the format of a string?
#include <list>
#include <map>
#include <regex>
#include <iostream>
void f(const std::string& s) {
std::map<int, int> m;
std::regex p {"[\\[\\{\\(](\\d+),\\s*(\\d+)[\\)\\}\\]]"};
auto begin = std::sregex_iterator(s.begin(), s.end(), p);
auto end = std::sregex_iterator();
for (auto x = begin; x != end; ++x) {
std::cout << x->str() << '\n';
m[std::stoi(x->str(1))] = std::stoi(x->str(2));
}
std::cout << m.size() << '\n';
}
int main() {
std::list<std::string> l {
"{{0, 1}, (2, 3)}",
"{{4, 5, {6, 7}}" // Ill-formed, so need to throw an excpetion.
};
for (auto x : l) {
f(x);
}
}
注意:我不认为必须使用regex
来解决此问题.任何形式的解决方案,包括通过减去子字符串立即进行验证和插入的某些方式,都是值得的.
NOTE: I don't feel obliged to use regex
to solve this problem. Any kind of solutions, including some ways validating and inserting at once by subtracting substrings, will be appreciated.
推荐答案
在我看来,基于Spirit的解析器始终更加健壮和易读.与Spirit :-)一起解析也更加有趣.因此,除了@ Aleph0的答案,我还要提供一个基于Spirit-X3的紧凑型解决方案:
In my opinion, Spirit-based parser is always much more robust and readable. It is also much more fun to parse with Spirit :-). So, in addition to @Aleph0 's answer, I'd like to provide a compact solution based on Spirit-X3:
#include <string>
#include <map>
#include <iostream>
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/spirit/home/x3.hpp>
int main() {
std::string input ="{{0, 1}, {2, 3}}";
using namespace boost::spirit::x3;
const auto pair = '{' > int_ > ',' > int_ > '}';
const auto pairs = '{' > (pair % ',') > '}';
std::map<int, int> output;
// ignore spaces, tabs, newlines
phrase_parse(input.begin(), input.end(), pairs, space, output);
for (const auto [key, value] : output) {
std::cout << key << ":" << value << std::endl;
}
}
请注意,我使用的运算符>
表示期望".因此,如果输入与预期不符,Spirit会引发异常.如果您喜欢静默故障,请改用运算符>>
.
Note that I used operator >
, which means "expect". So, if the input does not match the expectation, Spirit throws an exception. If you prefer a silent failure, use operator >>
instead.
这篇关于如何将字符串解析为std :: map并验证其格式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!