C++ 解析std::vector<;标准::向量<;双倍>;作为具有精神的结构属性

C++ 解析std::vector<;标准::向量<;双倍>;作为具有精神的结构属性,c++,parsing,vector,boost,boost-spirit,C++,Parsing,Vector,Boost,Boost Spirit,我有以下文字: [70000000:45] 4, 5, 6, 7 [60000000:60] 1, 2, 3, 4 [80000:90] 4, 5, 6, 7, 8, 9 方括号中的行包含频率和角度,其形式为[freq:angle],而后面的行是与这些参数相关的数字向量。我可以有不同的频率和角度,每个频率和角度都定义了一个向量 我有以下结构: struct Data { std::vector<int> frequencies; std::vector<int&g

我有以下文字:

[70000000:45]
4, 5, 6, 7

[60000000:60]
1, 2, 3, 4

[80000:90]
4, 5, 6, 7, 8, 9
方括号中的行包含频率和角度,其形式为
[freq:angle]
,而后面的行是与这些参数相关的数字向量。我可以有不同的频率和角度,每个频率和角度都定义了一个向量

我有以下结构:

struct Data {
  std::vector<int> frequencies;
  std::vector<int> elevations;
  std::vector<std::vector<double>> gains;
};
qi::rule<It, Data(), Skipper> start;
qi::rule<It, Ast::Data(), Skipper> section;
我需要解析文件以填充结构。我能够解析
频率
高程
,并将它们存储在向量中,但我无法存储增益数据。我需要从这些数据中创建一个向量

你可以在下面找到代码;解析后,
parsed
填充了频率和高程,我需要增益。我能做些什么来解析它们

#include <boost/optional/optional_io.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/posix_time/posix_time_io.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

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

const std::string file1 = R"xx(
[70000000:45]
4, 5, 6, 7

[60000000:60]
1, 2, 3, 4

[80000:90]
4, 5, 6, 7, 8, 9
)xx";


struct Data {
  std::vector<int> frequencies;
  std::vector<int> elevations;
  std::vector<std::vector<double>> gains;

};

BOOST_FUSION_ADAPT_STRUCT(
  Data,
  (std::vector<int>, frequencies)
  (std::vector<int>, elevations)
  (std::vector<std::vector<double>>, gains)
)

template <typename It, typename Skipper = qi::space_type>
struct grammar : qi::grammar<It, Data(), Skipper> {

  grammar() : grammar::base_type(start) {

    auto frequencyParser = qi::int_[px::push_back(px::at_c<0>(qi::_val), qi::_1)];
    auto elevationParser = qi::int_[px::push_back(px::at_c<1>(qi::_val), qi::_1)];
    auto frequencyElevationParser = qi::lit('[') >> frequencyParser >> qi::lit(':') >> elevationParser >> qi::lit(']');
    auto gainsParser = qi::double_ % qi::lit(','); // Problem here where I want to parse vector rows

    start = *(frequencyElevationParser >> gainsParser);
  }

private:

  qi::rule<It, Data(), Skipper> start;
};

int main() {
  using It = std::string::const_iterator;
  Data parsed;
  bool ok = qi::phrase_parse(file1.begin(), file1.end(), grammar<It>(), qi::space, parsed);
  return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
名称空间qi=boost::spirit::qi;
名称空间px=boost::phoenix;
常量std::字符串文件1=R“xx(
[70000000:45]
4, 5, 6, 7
[60000000:60]
1, 2, 3, 4
[80000:90]
4, 5, 6, 7, 8, 9
)xx”;
结构数据{
向量频率;
std::矢量高程;
矢量增益;
};
增强融合适应结构(
数据,
(标准:矢量,频率)
(标准::矢量,高程)
(标准::矢量,增益)
)
模板
结构语法:qi::grammar{
语法():语法::基本类型(开始){
自动频率PARSER=qi::int_u2;[px::推回(px::at_c(qi::val),qi:1)];
自动提升解析器=qi::int_ux::push_back(px::at_c(qi::_val),qi:_1)];
auto-frequencyElevationParser=qi::lit('[')>>frequencyParser>>qi::lit(':')>>elevationParser>>qi::lit(']');
auto-gainsParser=qi::double_%qi::lit(',');//这里的问题是我要在哪里解析向量行
开始=*(frequencyElevationParser>>GainParser);
}
私人:
qi::规则开始;
};
int main(){
使用它=std::string::const_迭代器;
解析数据;
bool ok=qi::phrase_parse(file1.begin()、file1.end()、grammar()、qi::space,已解析);
返回0;
}

我自己找到了解决办法

我在语法中为
std::vector
添加了
qi::rule
,然后我用它解析向量,将结果像其他字段一样附加到结构中。下面是更正后的代码:

#include <boost/optional/optional_io.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/posix_time/posix_time_io.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

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

const std::string file1 = R"xx(
[70000000:45]
4, 5, 6, 7

[60000000:60]
1, 2, 3, 4

[80000:90]
4, 5, 6, 7, 8, 9
)xx";


struct Data {
  std::vector<int> frequencies;
  std::vector<int> elevations;
  std::vector<std::vector<double>> gains;
};

BOOST_FUSION_ADAPT_STRUCT(
  Data,
  (std::vector<int>, frequencies)
  (std::vector<int>, elevations)
  (std::vector<std::vector<double>>, gains)
)

template <typename It, typename Skipper = qi::space_type>
struct grammar : qi::grammar<It, Data(), Skipper> {

  grammar() : grammar::base_type(start) {

    auto frequencyParser = qi::int_[px::push_back(px::at_c<0>(qi::_val), qi::_1)];
    auto elevationParser = qi::int_[px::push_back(px::at_c<1>(qi::_val), qi::_1)];
    auto frequencyElevationParser = qi::lit('[') >> frequencyParser >> qi::lit(':') >> elevationParser >> qi::lit(']');
    vectorParser = qi::double_ % qi::lit(',');
    auto gainsParser = vectorParser[px::push_back(px::at_c<2>(qi::_val), qi::_1)];

    start = *(frequencyElevationParser >> gainsParser);
  }

private:

  qi::rule<It, Data(), Skipper> start;
  qi::rule<It, std::vector<double>(), Skipper> vectorParser;
};

int main() {
  using It = std::string::const_iterator;
  Data parsed;
  bool ok = qi::phrase_parse(file1.begin(), file1.end(), grammar<It>(), qi::space, parsed);
  return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
名称空间qi=boost::spirit::qi;
名称空间px=boost::phoenix;
常量std::字符串文件1=R“xx(
[70000000:45]
4, 5, 6, 7
[60000000:60]
1, 2, 3, 4
[80000:90]
4, 5, 6, 7, 8, 9
)xx”;
结构数据{
向量频率;
std::矢量高程;
矢量增益;
};
增强融合适应结构(
数据,
(标准:矢量,频率)
(标准::矢量,高程)
(标准::矢量,增益)
)
模板
结构语法:qi::grammar{
语法():语法::基本类型(开始){
自动频率PARSER=qi::int_u2;[px::推回(px::at_c(qi::val),qi:1)];
自动提升解析器=qi::int_ux::push_back(px::at_c(qi::_val),qi:_1)];
auto-frequencyElevationParser=qi::lit('[')>>frequencyParser>>qi::lit(':')>>elevationParser>>qi::lit(']');
vectorParser=qi::double_%qi::lit(',');
auto-gainsParser=vectorParser[px::push_back(px::at_c(qi::_val),qi::_1)];
开始=*(frequencyElevationParser>>GainParser);
}
私人:
qi::规则开始;
qi::规则向量解析器;
};
int main(){
使用它=std::string::const_迭代器;
解析数据;
bool ok=qi::phrase_parse(file1.begin()、file1.end()、grammar()、qi::space,已解析);
返回0;
}

本着我经常重复的咒语的精神,我会使用一个特征,并将每个部分解析为Ast结构:

struct Data {
  std::vector<int> frequencies;
  std::vector<int> elevations;
  std::vector<std::vector<double>> gains;
};
qi::rule<It, Data(), Skipper> start;
qi::rule<It, Ast::Data(), Skipper> section;
魔法: 让我们创建一个Ast结构,并仅对其进行调整,而不是使用给定的不切实际的数据类型:

namespace Ast {
    struct Data {
        int frequency;
        int elevation;
        std::vector<double> gains;
    };
}

BOOST_FUSION_ADAPT_STRUCT(Ast::Data, frequency, elevation, gains)
这要简单得多

演示

#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>

namespace qi = boost::spirit::qi;

const std::string file1 = R"xx(
[70000000:45]
4, 5, 6, 7

[60000000:60]
1, 2, 3, 4

[80000:90]
4, 5, 6, 7, 8, 9
)xx";

namespace MyLib {
    struct Data {
        std::vector<int> frequencies;
        std::vector<int> elevations;
        std::vector<std::vector<double> > gains;
    };
}

namespace Ast {
    struct Data {
        int frequency;
        int elevation;
        std::vector<double> gains;
    };
}

namespace boost { namespace spirit { namespace traits {
    template <> struct container_value<MyLib::Data> { using type = Ast::Data; };

    template<> struct push_back_container<MyLib::Data, Ast::Data> {
        static bool call(MyLib::Data& c, Ast::Data const& val) {
            c.frequencies.push_back(val.frequency);
            c.elevations.push_back(val.elevation);
            c.gains.push_back(val.gains);
            return true;
        }
    };
} } }

BOOST_FUSION_ADAPT_STRUCT(Ast::Data, frequency, elevation, gains)

namespace MyLib {
    template <typename It, typename Skipper = qi::space_type>
    struct grammar : qi::grammar<It, Data(), Skipper> {

        grammar() : grammar::base_type(start) {
            using namespace qi;

            section = '[' >> int_ >> ':' >> int_ >> ']' >> double_ % ',';
            start = *section;
        }

      private:
        qi::rule<It, Data(), Skipper> start;
        qi::rule<It, Ast::Data(), Skipper> section;
    };
}

int main() {
    using It = std::string::const_iterator;
    MyLib::Data parsed;
    bool ok = qi::phrase_parse(file1.begin(), file1.end(), MyLib::grammar<It>(), qi::space, parsed);
}
#包括
#包括
名称空间qi=boost::spirit::qi;
常量std::字符串文件1=R“xx(
[70000000:45]
4, 5, 6, 7
[60000000:60]
1, 2, 3, 4
[80000:90]
4, 5, 6, 7, 8, 9
)xx”;
名称空间MyLib{
结构数据{
向量频率;
std::矢量高程;
矢量增益;
};
}
名称空间Ast{
结构数据{
整数频率;
内立面图;
矢量增益;
};
}
名称空间提升{名称空间精神{名称空间特征{
模板结构容器_值{using type=Ast::Data;};
模板结构推回容器{
静态bool调用(MyLib::Data&c,Ast::Data const&val){
c、 频率。推回(值频率);
c、 标高。推回(val.标高);
c、 增益。推回(值增益);
返回true;
}
};
} } }
增强融合自适应结构(Ast::数据、频率、高程、增益)
名称空间MyLib{
模板
结构语法:qi::grammar{
语法():语法::基本类型(开始){
使用名称空间qi;
section='['>>int\>':'>>int\>']'>>double\%',';
开始=*节;
}
私人:
qi::规则开始;
qi::规则部分;
};
}
int main(){
使用它=std::string::const_迭代器;
MyLib::解析的数据;
bool ok=qi::phrase_parse(file1.begin()、file1.end()、MyLib::grammar()、qi::space,已解析);
}

使用X3,这将变得更加简单:

#include <boost/spirit/home/x3.hpp>
#include <iostream>

namespace x3 = boost::spirit::x3;

const std::string file1 = R"xx(
[70000000:45]
4, 5, 6, 7

[60000000:60]
1, 2, 3, 4

[80000:90]
4, 5, 6, 7, 8, 9
)xx";


struct Data {
  std::vector<int> frequencies;
  std::vector<int> elevations;
  std::vector<std::vector<double>> gains;
};

int main() {
  Data parsed;

  auto appender = [](auto& ctx)
  {
      Data& data = x3::_val(ctx);
      auto& entry = x3::_attr(ctx);
      data.frequencies.push_back(boost::fusion::at_c<0>(entry));
      data.elevations.push_back(boost::fusion::at_c<1>(entry));
      data.gains.emplace_back(std::move(boost::fusion::at_c<2>(entry)));
  };

  auto block = x3::rule<struct r_block, Data>{}  =
      (('[' >> x3::int_ >> ':' >> x3::int_ >> ']') >> (x3::double_ % ','))[appender];

  auto it = file1.begin();
  while (x3::phrase_parse(it, file1.end(), block, x3::space, parsed))
    ;

  if (it != file1.end()) {
      std::cout << "Not all input parsed" << std::endl;
  }

  assert(parsed.elevations.size() == parsed.frequencies.size()
      && parsed.frequencies.size() == parsed.gains.size());

  for (int i = 0; i < parsed.frequencies.size(); ++i) {
      std::cout << "frequency: " << parsed.frequencies[i] << std::endl;
      std::cout << "elevations: " << parsed.elevations[i] << std::endl;
      std::cout << "gains: ";
      std::copy(parsed.gains[i].begin(), parsed.gains[i].end(), std::ostream_iterator<double>(std::cout, ","));
      std::cout << std::endl;
  }

  return 0;
}
#包括
#包括
名称空间x3=boost::spirit::x3;
常量std::字符串文件1=R“xx(
[70000000:45]
4, 5, 6, 7
[60000000:60]
1, 2, 3, 4
[80000:90]
4, 5, 6, 7, 8, 9
)xx”;
结构数据{
向量频率;
std::矢量高程;
矢量增益;
};
int main(){
解析数据;
自动追加器=[](自动和ctx)
{
数据和数据=x3::_val(ctx);
自动输入(&entry=x3::_attr(ctx);
数据。频率。推回(boost::fusion::at_c(条目));
数据。高程。推回(boost::fusion::at_c(条目));
数据.gains.emplace_back(std::move(boost::fusion::at_c(entry));
};
自动块=x3::规则{}=
((“[”>>x3::int\u>>”:“>>x3::int\u>>
#include <boost/spirit/home/x3.hpp>
#include <iostream>

namespace x3 = boost::spirit::x3;

const std::string file1 = R"xx(
[70000000:45]
4, 5, 6, 7

[60000000:60]
1, 2, 3, 4

[80000:90]
4, 5, 6, 7, 8, 9
)xx";


struct Data {
  std::vector<int> frequencies;
  std::vector<int> elevations;
  std::vector<std::vector<double>> gains;
};

int main() {
  Data parsed;

  auto appender = [](auto& ctx)
  {
      Data& data = x3::_val(ctx);
      auto& entry = x3::_attr(ctx);
      data.frequencies.push_back(boost::fusion::at_c<0>(entry));
      data.elevations.push_back(boost::fusion::at_c<1>(entry));
      data.gains.emplace_back(std::move(boost::fusion::at_c<2>(entry)));
  };

  auto block = x3::rule<struct r_block, Data>{}  =
      (('[' >> x3::int_ >> ':' >> x3::int_ >> ']') >> (x3::double_ % ','))[appender];

  auto it = file1.begin();
  while (x3::phrase_parse(it, file1.end(), block, x3::space, parsed))
    ;

  if (it != file1.end()) {
      std::cout << "Not all input parsed" << std::endl;
  }

  assert(parsed.elevations.size() == parsed.frequencies.size()
      && parsed.frequencies.size() == parsed.gains.size());

  for (int i = 0; i < parsed.frequencies.size(); ++i) {
      std::cout << "frequency: " << parsed.frequencies[i] << std::endl;
      std::cout << "elevations: " << parsed.elevations[i] << std::endl;
      std::cout << "gains: ";
      std::copy(parsed.gains[i].begin(), parsed.gains[i].end(), std::ostream_iterator<double>(std::cout, ","));
      std::cout << std::endl;
  }

  return 0;
}