Sii*_*las 5 c++ boost boost-spirit
是否有可能(使用Boost :: Spirit :: QI)从逗号分隔的字符串中解析数字,以便获得每个已解析数字的索引?
假设我有一个字符串"23,123,65,1",我想将这些数字中的每一个插入到给定位置(0,1,2,3)的矩阵中.一种方法是将数字解析为std :: vector,然后将它们复制到矩阵行,但速度并不是特别快.
目前我正在使用矢量变体:
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++;
});
}
Run Code Online (Sandbox Code Playgroud)
如果解析器有一个成功的回调,它需要一个lambda函数或类似的功能,那就太棒了.
seh*_*ehe 12
有很多方法.
我通常建议的是使用经过深思熟虑的repeat(n)表达式直接暴露容器属性(如vector<vector<double> >).
你似乎在寻找的是与国家的语义行为.(这是来自lex/yacc的常见做法).
我在下面的三个完整演示中处理这些方法(1.,2.和3.)
Matrix类型视为容器属性,并使用它来覆盖它的插入逻辑spirit::traits.对于这种方法,我引用这个答案:在boost精神中将属性传递给子规则.这是一个相对简单的方法:
直接解析成vector<vector<double> >(在线完整代码)
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_(" \t,")) [ repeat(_r1) [ double_ ] ];
matrix %= eps // [ std::cout << phx::val("debug: ") << _r1 << ", " << _r2 << "\n" ]
>> repeat(_r1) [ row(_r2) >> (eol|eoi) ];
Run Code Online (Sandbox Code Playgroud)
用法:
if (qi::phrase_parse(f,l,parser(10, 4),qi::blank, m))
std::cout << "Wokay\n";
else
std::cerr << "Uhoh\n";
Run Code Online (Sandbox Code Playgroud)同样,但适应Matrix结构(完整代码在这里生活)
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))
Run Code Online (Sandbox Code Playgroud)
用法
Matrix m(10, 4);
if (qi::phrase_parse(f,l,parser(m.rows(),m.columns()),qi::blank, m))
std::cout << "Wokay\n";
else
std::cerr << "Uhoh\n";
Run Code Online (Sandbox Code Playgroud)3.这是更多的工作,但可能更灵活.您将定义一个多态可调用类型以在给定单元格中插入值:
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)
Run Code Online (Sandbox Code Playgroud)
最后一行使它成为一个phoenix惰性函数,因此您可以在语义操作中使用它而不需要奇怪的绑定语法:
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*/])
;
Run Code Online (Sandbox Code Playgroud)
完整代码再次在liveworkspace.org上发布
| 归档时间: |
|
| 查看次数: |
845 次 |
| 最近记录: |