【问题标题】:C++: the easiest way to handle comma-delimited strings whose substrings have commas themselves? [closed]C ++:处理子字符串本身带有逗号的逗号分隔字符串的最简单方法? [关闭]
【发布时间】:2020-04-04 19:00:41
【问题描述】:

这是一个例子:

str1 = "a, b, \"c, d, e\", f"

如果我要解析这个字符串:

stringstream ss(str1);
while (getline(ss,str,',')){
    cout << str << endl;
}

输出如下:

a
 b
 "c
 d
 e"
 f

我在哪里寻找

a
 b
 c, d, e
 f

【问题讨论】:

  • 首先想到的是使用正则表达式来解析输入 en.cppreference.com/w/cpp/regex 这样您就可以定义什么是字符串。
  • the easiest way - 在 github 上找到一个库。使用那个库。
  • 这是标准的 csv 格式,所以是的,使用标准的 CSV 库

标签: c++ string parsing


【解决方案1】:

正如他们在评论中建议的那样,最简单的方法是使用解析器库。

C++ 中最好的解析器库之一是Boost.Spirit

这是一个如何使用 Boost.Spirit 解析格式的工作示例:

#include <iostream>

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/qi_parse.hpp>

#include <boost/variant.hpp>
#include <boost/variant/get.hpp>

using Element = boost::variant<
    std::string,
    std::vector<std::string>
    >;

std::ostream& operator<<(std::ostream& s, Element const& e) {
    switch(e.which()) {
    case 0:
        return s << boost::get<std::string>(e);
    case 1:
        for(auto const& a : boost::get<std::vector<std::string>>(e))
            s << a << ' ';
        return s;
    }
    throw;
}

std::vector<Element> parse(std::string const& input) {
    namespace qi = boost::spirit::qi;
    using namespace std;
    using I = decltype(input.begin());
    using S = qi::space_type;

    struct string2 : string {
        using string::string;
        string2(char c) : string(1, c) {} // Need this extra constructor for +qi::alnum.
    };

    // Grammar.
    qi::rule<I, S, string2>         element        = +qi::alnum;
    qi::rule<I, S>                  open           = qi::lit('"');
    qi::rule<I, S>                  close          = qi::lit('"');
    qi::rule<I, S, vector<string>>  nested_element = open >> (element % ',') >> close;
    qi::rule<I, S, Element>         element2       = element | nested_element;
    qi::rule<I, S, vector<Element>> parser         = element2 % ',';

    vector<Element> result;

    auto cur = input.begin();
    if(!phrase_parse(cur, input.end(), parser, qi::space, result) || cur != input.end())
        throw "Failed to parse.";

    return result;
}

int main() {
    auto elements = parse("a, b, \"c, d, e\", f");
    for(auto const& e : elements)
        std::cout << e << '\n';
}

输出:

a
b
c d e 
f

【讨论】:

  • @sehe 你知道如何避免必须指定qi::rule&lt;I, S, ...&gt;,使用auto 不起作用吗?
  • 我认为Element = boost::variant&lt; 可能有点矫枉过正,我怀疑这是一个 csv,所以你不必解析包裹在 "" 中的元素。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多