c – 如何使用boost :: spirit解析csv

前端之家收集整理的这篇文章主要介绍了c – 如何使用boost :: spirit解析csv前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有这个csv线
std::string s = R"(1997,Ford,E350,"ac,abs,moon","some "rusty" parts",3000.00)";

我可以使用boost :: tokenizer解析它:

typedef boost::tokenizer< boost::escaped_list_separator<char>,std::string::const_iterator,std::string> Tokenizer;
boost::escaped_list_separator<char> seps('\\',','\"');
Tokenizer tok(s,seps);
for (auto i : tok)
{
    std::cout << i << std::endl;
}

它是正确的,除了令牌“生锈”应该有双引号被剥离.

这是我尝试使用boost :: spirit

boost::spirit::classic::rule<> list_csv_item = !(boost::spirit::classic::confix_p('\"',*boost::spirit::classic::c_escape_ch_p,'\"') | boost::spirit::classic::longest_d[boost::spirit::classic::real_p | boost::spirit::classic::int_p]);
std::vector<std::string> vec_item;
std::vector<std::string>  vec_list;
boost::spirit::classic::rule<> list_csv = boost::spirit::classic::list_p(list_csv_item[boost::spirit::classic::push_back_a(vec_item)],')[boost::spirit::classic::push_back_a(vec_list)];
boost::spirit::classic::parse_info<> result = parse(s.c_str(),list_csv);
if (result.hit)
{
  for (auto i : vec_item)
  {
    cout << i << endl;
   }
}

问题:

>不起作用,仅打印第一个令牌
>为什么提升::精神::经典?找不到使用Spirit V2的例子
>设置很残酷..但我可以忍受这个

**我真的想使用boost :: spirit,因为它往往非常快

预期产量:

1997
Ford
E350
ac,moon
some "rusty" parts

3000.00

解决方法

Sehe的帖子看起来比我的更干净,但是我把它放在一起有点,所以这里无论如何:
#include <boost/tokenizer.hpp>
#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;

int main() {
    const std::string s = R"(1997,""rusty"",3000.00)";

    // Tokenizer
    typedef boost::tokenizer< boost::escaped_list_separator<char>,std::string> Tokenizer;
    boost::escaped_list_separator<char> seps('\\','\"');
    Tokenizer tok(s,seps);
    for (auto i : tok)
        std::cout << i << "\n";
    std::cout << "\n";

    // Boost Spirit Qi
    qi::rule<std::string::const_iterator,std::string()> quoted_string = '"' >> *(qi::char_ - '"') >> '"';
    qi::rule<std::string::const_iterator,std::string()> valid_characters = qi::char_ - '"' - ',';
    qi::rule<std::string::const_iterator,std::string()> item = *(quoted_string | valid_characters );
    qi::rule<std::string::const_iterator,std::vector<std::string>()> csv_parser = item % ',';

    std::string::const_iterator s_begin = s.begin();
    std::string::const_iterator s_end = s.end();
    std::vector<std::string> result;

    bool r = boost::spirit::qi::parse(s_begin,s_end,csv_parser,result);
    assert(r == true);
    assert(s_begin == s_end);

    for (auto i : result)
        std::cout << i << std::endl;
    std::cout << "\n";
}

这个输出

1997
Ford
E350
ac,moon
rusty
3000.00

1997
Ford
E350
ac,moon
rusty
3000.00

值得注意的事情:这不会实现完整的CSV解析器.您还需要查看转义字符或实现所需的任何其他内容.

另外:如果你正在查看文档,那么你知道,在Qi中,’a’相当于boost :: spirit :: qi :: lit(‘a’)和“abc”相当于boost ::精神::齐::亮( “ABC”).

关于双引号:所以,正如Sehe在上面的评论中指出的那样,并不直接清楚输入文本中围绕“”的规则意味着什么.如果您希望所有不在引用字符串中的“”实例转换为“,那么以下内容将起作用.

qi::rule<std::string::const_iterator,std::string()> double_quote_char = "\"\"" >> qi::attr('"');
qi::rule<std::string::const_iterator,std::string()> item = *(double_quote_char | quoted_string | valid_characters );

猜你在找的C&C++相关文章