<bdo id='l0Vcx'></bdo><ul id='l0Vcx'></ul>
<tfoot id='l0Vcx'></tfoot>

    1. <legend id='l0Vcx'><style id='l0Vcx'><dir id='l0Vcx'><q id='l0Vcx'></q></dir></style></legend>
      <i id='l0Vcx'><tr id='l0Vcx'><dt id='l0Vcx'><q id='l0Vcx'><span id='l0Vcx'><b id='l0Vcx'><form id='l0Vcx'><ins id='l0Vcx'></ins><ul id='l0Vcx'></ul><sub id='l0Vcx'></sub></form><legend id='l0Vcx'></legend><bdo id='l0Vcx'><pre id='l0Vcx'><center id='l0Vcx'></center></pre></bdo></b><th id='l0Vcx'></th></span></q></dt></tr></i><div id='l0Vcx'><tfoot id='l0Vcx'></tfoot><dl id='l0Vcx'><fieldset id='l0Vcx'></fieldset></dl></div>

      <small id='l0Vcx'></small><noframes id='l0Vcx'>

      1. Boost::Spirit::QI 解析器:解析元素的索引

        时间:2023-07-20
      2. <small id='uHPCw'></small><noframes id='uHPCw'>

      3. <tfoot id='uHPCw'></tfoot>

          1. <legend id='uHPCw'><style id='uHPCw'><dir id='uHPCw'><q id='uHPCw'></q></dir></style></legend>

              <tbody id='uHPCw'></tbody>

          2. <i id='uHPCw'><tr id='uHPCw'><dt id='uHPCw'><q id='uHPCw'><span id='uHPCw'><b id='uHPCw'><form id='uHPCw'><ins id='uHPCw'></ins><ul id='uHPCw'></ul><sub id='uHPCw'></sub></form><legend id='uHPCw'></legend><bdo id='uHPCw'><pre id='uHPCw'><center id='uHPCw'></center></pre></bdo></b><th id='uHPCw'></th></span></q></dt></tr></i><div id='uHPCw'><tfoot id='uHPCw'></tfoot><dl id='uHPCw'><fieldset id='uHPCw'></fieldset></dl></div>
              <bdo id='uHPCw'></bdo><ul id='uHPCw'></ul>
                  本文介绍了Boost::Spirit::QI 解析器:解析元素的索引的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

                  问题描述

                  是否可以(使用 Boost::Spirit::QI)从逗号分隔的字符串中解析数字,以便获得每个解析数字的索引?

                  假设我有一个字符串 "23,123,65,1" 并且我想将这些数字中的每一个插入到给定位置 (0, 1, 2, 3) 的矩阵中.一种方法是将数字解析为 std::vector,然后将它们复制到矩阵行,但速度不是特别快.

                  目前我正在使用矢量变体:

                  矩阵数据(10, 4);整数行 = 0;int col = 0;std::string str = "23,123,65,1";std::vector资源;if (qi::parse(str.begin(), str.end(), qi::double_ % ',', res)){std::for_each(res.begin(), res.end(), [&col, &data, &row](double elem) {数据(行,列)= elem;颜色++;});}

                  如果解析器有一个采用 lambda 函数或类似功能的成功回调,那就太棒了.

                  解决方案

                  有很多方法.

                  • 我通常推荐的做法是使用经过深思熟虑的repeat(n) 表达式,并直接暴露容器属性(如vector<;向量 >).

                  • 似乎要寻找的是带有状态的语义动作.(这是来自 lex/yacc 的常见做法).

                  我在下面的三个完整演示中介绍了这些方法(1.、2. 和 3.)

                  • 一种高级技术是使用自定义点让 Spirit 直接将您的 Matrix 类型视为容器属性,并使用 spirit 覆盖它的插入逻辑::traits.对于这种方法,我参考了这个答案:pass attribute to孩子统治提振精神.

                  使用 继承属性

                  这是一个相对简单的方法:

                  1. 直接解析成vector;>(完整代码在线直播)

                    qi::rule排;qi::rule矩阵;行 %= skip(char_(" 	,")) [ repeat(_r1) [ double_ ] ];矩阵 %= eps//[ std::cout <<phx::val("调试:") <<_r1<<", " <<_r2<<"
                    " ]>>重复(_r1)[行(_r2)>>(eol|eoi) ];

                    用法:

                    if (qi::phrase_parse(f,l,parser(10, 4),qi::blank, m))std::cout <<"哇哦
                    ";别的std::cerr <<"呃
                    ";

                  2. 类似,但采用 Matrix 结构(完整代码住在这里)

                    struct 矩阵{矩阵(size_t 行,size_t cols):_cells(),_rows(行),_cols(cols){}双&数据(size_t col, size_t row) { return _cells.at(row).at(col);}const double &数据(size_t col, size_t row) const { return _cells.at(row).at(col);}size_t 列()const { 返回 _cols;}size_t 行()const { 返回 _rows;}std::vector>_细胞;size_t _rows, _cols;};BOOST_FUSION_ADAPT_STRUCT(矩阵,(std::vector >,_cells))

                    用法

                    矩阵 m(10, 4);如果 (qi::phrase_parse(f,l,parser(m.rows(),m.columns()),qi::blank, m))std::cout <<"哇哦
                    ";别的std::cerr <<"呃
                    ";

                  使用语义动作/qi::locals

                  3.这是更多的工作,但可能更灵活.您将定义一个多态可调用类型以在给定单元格中插入一个值:

                  struct MatrixInsert{模板<类型名,类型名,类型名,类型名>结构结果 { typedef bool 类型;};模板 <typename Matrix, typename Row, typename Col, typename Value>bool operator()(Matrix &m, Row& r, Col& c, Value v) const{if (r 

                  最后一行使它成为一个 phoenix 惰性函数,因此您可以在语义操作中使用它而无需奇怪的绑定语法:

                  qi::rule>矩阵;矩阵 = eps [ _a = 0/*当前行*/]>>(eps [ _b = 0/*当前列*/]>>double_ [ _pass = matrix_insert(_val, _a, _b, _1) ] % ',') % (eol [ ++_a/*下一行*/]);

                  完整代码再次liveworkspace.org

                  Is it possible (using Boost::Spirit::QI) to parse numbers from a comma separated string so that I get the index of each parsed number?

                  Suppose I have a string "23,123,65,1" and I want to insert each of these numbers into a matrix at given locations (0, 1, 2, 3). One way to do it would to parse the numbers into an std::vector and then copy them to the matrix row, but it isn't particularly fast.

                  Currently I'm using the vector variant:

                  Matrix data(10, 4);
                  int row = 0;
                  int col = 0;
                  std::string str = "23,123,65,1";
                  std::vector<double> res;
                  if (qi::parse(str.begin(), str.end(), qi::double_ % ',', res))
                  {
                    std::for_each(res.begin(), res.end(), [&col, &data, &row](double elem) {
                  
                        data(row, col) = elem;
                        col++;
                  });
                  }
                  

                  It'd be awesome if the parser had a success callback that takes a lambda function or a similar feature.

                  解决方案

                  There are a number of approaches.

                  • What I'd usually recommend instead, is using well thought out repeat(n) expressions with directly exposed container attributes (like vector<vector<double> >).

                  • What you seem to be looking for is semantic actions with state. (This is common practice coming from lex/yacc).

                  I treat these approaches in three full demos below (1., 2. and 3.)

                  • An advanced technique is using customization points to allow Spirit to directly treat your Matrix type as a container attribute and override the insertion logic for it using spirit::traits. For this approach I refer to this answer: pass attribute to child rule in boost spirit.

                  Using inherited attributes

                  Here is a relatively straightforward approach:

                  1. parsing directly into a vector<vector<double> > (full code live online)

                    qi::rule<It, Matrix::value_type(size_t cols), qi::blank_type> row;
                    qi::rule<It, Matrix(size_t rows,size_t cols), qi::blank_type> matrix;
                    
                    row    %= skip(char_(" 	,")) [ repeat(_r1) [ double_ ] ];
                    matrix %= eps // [ std::cout << phx::val("debug: ") << _r1 << ", " << _r2 << "
                    " ]
                           >> repeat(_r1) [ row(_r2) >> (eol|eoi) ];
                    

                    Usage:

                    if (qi::phrase_parse(f,l,parser(10, 4),qi::blank, m))
                        std::cout << "Wokay
                    ";
                    else
                        std::cerr << "Uhoh
                    ";
                    

                  2. Similarly, but adapting a Matrix struct (full code live here)

                    struct Matrix
                    {
                        Matrix(size_t rows, size_t cols) : _cells(), _rows(rows), _cols(cols) { }
                    
                        double       & data(size_t col, size_t row)       { return _cells.at(row).at(col); } 
                        const double & data(size_t col, size_t row) const { return _cells.at(row).at(col); } 
                    
                        size_t columns() const { return _cols; }
                        size_t rows()    const { return _rows; }
                    
                        std::vector<std::vector<double> > _cells;
                        size_t _rows, _cols;
                    };
                    
                    BOOST_FUSION_ADAPT_STRUCT(Matrix, (std::vector<std::vector<double> >,_cells))
                    

                    Usage

                    Matrix m(10, 4);
                    
                    if (qi::phrase_parse(f,l,parser(m.rows(),m.columns()),qi::blank, m))
                        std::cout << "Wokay
                    ";
                    else
                        std::cerr << "Uhoh
                    ";
                    

                  Using semantic actions/qi::locals

                  3. This is more work, but potentially more flexible. You'd define a polymorphic callable type to insert a value at a given cell:

                  struct MatrixInsert
                  {
                      template <typename, typename, typename, typename> struct result { typedef bool type; };
                      template <typename Matrix, typename Row, typename Col, typename Value>
                          bool operator()(Matrix &m, Row& r, Col& c, Value v) const
                          {
                              if (r < m.rows() && c < m.columns())
                              {
                                  m.data(r, c++) = v;
                                  return true; // parse continues
                              }
                              return false;    // fail the parse
                          }
                  };
                  
                  BOOST_PHOENIX_ADAPT_CALLABLE(matrix_insert, MatrixInsert, 4)
                  

                  The last line makes this a phoenix lazy function, so you can use it without weird bind syntax in your semantic actions:

                  qi::rule<It, Matrix(), qi::blank_type, qi::locals<size_t /*_a: row*/, size_t/*_b: col*/> > matrix;
                  matrix = eps    [ _a = 0 /*current row*/ ]
                       >> (
                              eps     [ _b = 0 /*current col*/ ] 
                           >> double_ [ _pass = matrix_insert(_val, _a, _b, _1) ] % ','
                          ) % (eol    [ ++_a /*next row*/])
                       ;
                  

                  Full code is, again live on liveworkspace.org

                  这篇关于Boost::Spirit::QI 解析器:解析元素的索引的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

                  <tfoot id='MxDgc'></tfoot>
                  • <i id='MxDgc'><tr id='MxDgc'><dt id='MxDgc'><q id='MxDgc'><span id='MxDgc'><b id='MxDgc'><form id='MxDgc'><ins id='MxDgc'></ins><ul id='MxDgc'></ul><sub id='MxDgc'></sub></form><legend id='MxDgc'></legend><bdo id='MxDgc'><pre id='MxDgc'><center id='MxDgc'></center></pre></bdo></b><th id='MxDgc'></th></span></q></dt></tr></i><div id='MxDgc'><tfoot id='MxDgc'></tfoot><dl id='MxDgc'><fieldset id='MxDgc'></fieldset></dl></div>
                      <tbody id='MxDgc'></tbody>

                      <bdo id='MxDgc'></bdo><ul id='MxDgc'></ul>

                        <legend id='MxDgc'><style id='MxDgc'><dir id='MxDgc'><q id='MxDgc'></q></dir></style></legend>

                        <small id='MxDgc'></small><noframes id='MxDgc'>