将解析结果自动连接到向量中
auto concatenation of parse results into vectors
我已经编写了一些规则,将浮点解析为两个std::vector的浮点,然后将其存储在struct:中
数据输入:
#
# object name01
#
v -1.5701 33.8087 0.3592
v -24.0119 0.0050 21.7439
# a comment
vn 0.0000 0.5346 0.8451
vn 0.8331 0.5531 -0.0000
# another comment
结构:
struct ObjParseData
{
ObjParseData() : verts(), norms() {}
std::vector<float> verts;
std::vector<float> norms;
};
以及相关解析代码:
struct objGram : qi::grammar<std::string::const_iterator, ObjParseData(), iso8859::space_type>
{
objGram() : objGram::base_type(start)
{
vertex = 'v' >> qi::double_ >> qi::double_ >> qi::double_;
normal = "vn" >> qi::double_ >> qi::double_ >> qi::double_;
comment = '#' >> qi::skip(qi::blank)[ *(qi::print) ];
vertexList = *(vertex | comment);
normalList = *(normal | comment);
start = vertexList >> normalList;
}
qi::rule<std::string::const_iterator, ObjParseData(), iso8859::space_type> start;
qi::rule<std::string::const_iterator, std::vector<float>(), iso8859::space_type> vertexList;
qi::rule<std::string::const_iterator, std::vector<float>(), iso8859::space_type> normalList;
qi::rule<std::string::const_iterator, std::vector<float>(), iso8859::space_type> vertex;
qi::rule<std::string::const_iterator, std::vector<float>(), iso8859::space_type> normal;
qi::rule<std::string::const_iterator, iso8859::space_type> comment;
} objGrammar;
ObjParseData resultData;
std::string::const_iterator f = data.cbegin();
bool res = qi::phrase_parse( f, data.cend(), objGrammar, iso8859::space, resultData );
这是有效的。它将所有以"v"开头的浮点数解析为结构的verts向量,并将所有以"vn"开头的浮数解析为范数。这很好,但我真的不知道为什么这样有效。
现在,如果我正确理解了这一点,下面定义的规则会将其所有结果放入一个std::向量的float中。
qi::rule<std::string::const_iterator, std::vector<float>(), iso8859::space_type> vertex;
所以,看看上面显示的解析代码,知道像vertex这样的规则会解析成一个std::vector of float,显然像vertex List这样的规则(上面显示的那个)会将来自vertex的结果连接成一个std::vector的float?所以看到这种行为,你会认为你可以把这两个规则(顶点和顶点列表)写为一个,但不幸的是,这不起作用:
vertex = *('v' >> qi::double_ >> qi::double_ >> qi::double_) | comment;
normal = *("vn" >> qi::double_ >> qi::double_ >> qi::double_) | comment;
comment = '#' >> qi::skip(qi::blank)[ *(qi::print) ];
start = vertex >> normal;
代码确实进行了编译,qi::phrase_parse确实返回了一个成功的解析,但结构中的std::vector不再被填充。。我在这里错过了什么?
您错放了分组括号:展开
vertexList = *(vertex | comment);
normalList = *(normal | comment);
通过消除导致的子规则
vertex = *(('v' >> qi::double_ >> qi::double_ >> qi::double_) | comment);
normal = *(("vn" >> qi::double_ >> qi::double_ >> qi::double_) | comment);
或者,我更喜欢:
完整的工作样本(请下次让您的代码样本SSCCE?https://meta.stackexchange.com/questions/22754/sscce-how-to-provide-examples-for-programming-questions):
#include <iterator>
#include <fstream>
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace karma = boost::spirit::karma;
namespace phx = boost::phoenix;
struct ObjParseData
{
ObjParseData() : verts(), norms() {}
std::vector<float> verts;
std::vector<float> norms;
};
BOOST_FUSION_ADAPT_STRUCT(ObjParseData, (std::vector<float>, verts)(std::vector<float>, norms))
template <typename It, typename Skipper = qi::space_type>
struct parser : qi::grammar<It, ObjParseData(), Skipper>
{
parser() : parser::base_type(start)
{
using namespace qi;
vertex = 'v' >> qi::double_ >> qi::double_ >> qi::double_;
normal = "vn" >> qi::double_ >> qi::double_ >> qi::double_;
comment = '#' >> qi::skip(qi::blank)[ *(qi::print) ];
#if 0
vertexList = *(vertex | comment);
normalList = *(normal | comment);
start = vertexList >> normalList;
#else
vertex = *(comment | ('v' >> qi::double_ >> qi::double_ >> qi::double_));
normal = *(comment | ("vn" >> qi::double_ >> qi::double_ >> qi::double_));
start = vertex >> normal;
#endif
BOOST_SPIRIT_DEBUG_NODE(start);
}
private:
qi::rule<std::string::const_iterator, ObjParseData(), qi::space_type> start;
qi::rule<std::string::const_iterator, std::vector<float>(), qi::space_type> vertexList;
qi::rule<std::string::const_iterator, std::vector<float>(), qi::space_type> normalList;
qi::rule<std::string::const_iterator, std::vector<float>(), qi::space_type> vertex;
qi::rule<std::string::const_iterator, std::vector<float>(), qi::space_type> normal;
qi::rule<std::string::const_iterator, qi::space_type> comment;
};
bool doParse(const std::string& input)
{
typedef std::string::const_iterator It;
auto f(begin(input)), l(end(input));
parser<It, qi::space_type> p;
ObjParseData data;
try
{
bool ok = qi::phrase_parse(f,l,p,qi::space,data);
if (ok)
{
std::cout << "parse successn";
std::cout << "data: " << karma::format_delimited(
"v: " << karma::auto_ << karma::eol <<
"n: " << karma::auto_ << karma::eol, ' ', data);
}
else std::cerr << "parse failed: '" << std::string(f,l) << "'n";
if (f!=l) std::cerr << "trailing unparsed: '" << std::string(f,l) << "'n";
return ok;
} catch(const qi::expectation_failure<It>& e)
{
std::string frag(e.first, e.last);
std::cerr << e.what() << "'" << frag << "'n";
}
return false;
}
int main()
{
std::ifstream ifs("input.txt", std::ios::binary);
ifs.unsetf(std::ios::skipws);
std::istreambuf_iterator<char> f(ifs), l;
bool ok = doParse({ f, l });
}
输出:
parse success
data: v: -1.57 33.809 0.359 -24.012 0.005 21.744
n: 0.0 0.535 0.845 0.833 0.553 0.0
相关文章:
- 用于连接向量的 Constexpr 函数
- C++将两个不同类型的向量的属性连接到新的向量中
- 以零字节作为定界符/终端的字节加入(连接)字符串向量
- 交叉连接 2 个向量的元素以产生第三个
- C++线程的向量在连接时随机崩溃
- 将两个向量与另一个向量连接起来
- 有没有办法像python:np.concatenate([x,y,z],axis=1)中那样沿着列连接三个二维向量C++
- Swig - 结构的 c++ 向量以及如何连接它们
- <T> 在使用运算符+ 连接两个向量之前从类型向量中删除索引
- 有没有办法简单地连接多个向量
- 尝试保存到成员向量的连接-一次只保存一个
- 如何连接/合并向量
- 如何使用 boost 连接 c++ 中的字符串向量
- std::bad_alloc连接两个向量时
- 如何连接向量的两个元素
- 对百万或十亿个 STL 向量进行排序和连接的最快方法
- 在转换一个向量的元素时,连接两个向量的最佳方式是什么
- 获取"子"向量和"连接"向量
- 如何在Eigen中连接向量
- 在opencv中连接向量Rect