Boost Spirit语法用于识别从一行到向量的一系列数字?

时间:2014-07-08 07:29:31

标签: c++ boost vector boost-spirit

我有一个字符串,有这样的风格:

  SCALE FACTORS      16.      0.0     0.0     0.0     0.0      .

  SCALE FACTORS      30.       .       .       .       .       .

  SCALE FACTORS     256.      10.0     20.0     30.0    .

所以,几个数字的末尾有点,只有点和空格。这是一些历史数据格式,我有太多文件可以手动调整到更易读的形状。

线的起点始终是" SCALE FACTORS"可以"读"作为固定模板。

我需要一个boost精神表达式,帮助我在向量中识别这个字符串。 必须丢弃单独的点(或至少读为零)。数字必须存储在矢量中。行中有效数字的数量介于一个和几个之间(不固定)。

我的主要问题是,如何在向量中存储数字串。原则上,我可以在没有Boost Spirit帮助的情况下移除杂散点。

1 个答案:

答案 0 :(得分:3)

使用blank_type队长,您可以

    start = line % eol;
    line  = lit("SCALE") >> "FACTORS" >> *(double_|'.')

这导致'.'项的零:

Parsed 3 lines
[SCALE FACTORS] 16 0 0 0 0 0 
[SCALE FACTORS] 30 0 0 0 0 0 
[SCALE FACTORS] 256 10 20 30 0 
Remaining input: '
'

查看 Live On Coliru

#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/format.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <cstdint>

namespace qi  = boost::spirit::qi;
namespace phx = boost::phoenix;

typedef std::vector<double> line_t;
typedef std::vector<line_t> lines_t;

template <typename Iterator>
struct sfparser : public qi::grammar<Iterator, lines_t(), qi::blank_type>
{
    sfparser () : sfparser::base_type(start)
    {
        using namespace qi;

        start = line % eol;
        line  = lit("SCALE") >> "FACTORS" >> *(double_|'.');
    }

  private:
    qi::rule<Iterator, lines_t(), qi::blank_type> start;
    qi::rule<Iterator, line_t(), qi::blank_type > line;
};

int main()
{
    std::string const input = " SCALE FACTORS      16.      0.0     0.0     0.0     0.0      .\n"
        "SCALE FACTORS      30.       .       .       .       .       .\n"
        "  SCALE FACTORS     256.      10.0     20.0     30.0    .\n";

    std::string::const_iterator f = input.begin();
    std::string::const_iterator l = input.end();
    sfparser<std::string::const_iterator> grammar;

    lines_t data;
    if (qi::phrase_parse (f, l, grammar, qi::blank, data))
    {
        std::cout << "Parsed " << data.size() << " lines\n";
        for (auto& line : data)
        {
            std::cout << "[SCALE FACTORS] ";
            for (auto d : line)
                std::cout << d << " ";

            std::cout << "\n";
        }
    }
    else
    {
        std::cout << "Failed\n";
    }

    if (f!=l)
        std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
}