如何将字符串解析为std :: map并验证其格式? [英] How to parse a string into std::map and validate its format?

查看:92
本文介绍了如何将字符串解析为std :: map并验证其格式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将像"{{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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆