【发布时间】:2019-04-25 22:29:57
【问题描述】:
在 Boost.Spirit 中,只需执行以下操作即可从流中读取到 std::vector:
#include<vector>
#include<boost/spirit/include/qi.hpp>
namespace sqi = boost::spirit::qi;
int main(){
std::string const v_str = "AA BB CC";
std::vector<std::string> v;
auto it = begin(v_str);
bool r = sqi::phrase_parse(it, end(v_str),
(*sqi::lexeme[+sqi::char_("A-Z")]), sqi::space, v);
assert( v.size() == 3 and v[2] == "CC" );
}
但是,由于输入格式的原因,我提前知道了元素的数量,并且我应该能够在向量中保留空间。 例如输入字符串为“3 AA BB CC”,可以预先分配三个元素。
问题是如何将这些额外信息传递给向量并优化后面的push_back(例如避免重新分配)。
我尝试的是在开始时解析一个整数,将语义操作与执行reserve 的位置相关联。
std::string const v_str = "3 AA BB CC";
std::vector<std::string> v;
auto it = begin(v_str);
bool r = sqi::phrase_parse(it, end(v_str),
sqi::int_[([&](int i){v.reserve(i);})] >>
(*sqi::lexeme[+sqi::char_("A-Z")]), sqi::space, v);
问题是在语义操作之后整数没有被忽略,从我的测试中我可以看到它试图在保留后将结果(示例中的3)推送到向量中。
另一种解决方法是向 phrase_parse 函数添加另一个参数,但这似乎有点过头了。
那么,如何在 Boost.Spirit 中解析某些内容,只执行语义操作而不将结果发送到 sink 变量?
即使可以做到这一点,我也不确定这是否是正确的方法。
【问题讨论】:
-
我想你可以试试 qi::repeat() 来实现你所需要的。请参阅boost.org/doc/libs/1_70_0/libs/spirit/doc/html/spirit/qi/… 上的参考资料。
-
@drus,链接末尾的示例正是我正在寻找的,但出于某种原因,在我的情况下,第一个
char_[...]解析器也以str结束,而不是仅用于语义动作。也许这是因为我使用了 lambda 而不是 phoenix 表达式。
标签: c++ boost-spirit boost-spirit-qi semantic-actions