gpt4 book ai didi

boost - 如何使用 boost::xpressive 在语义操作中使用结构填充向量

转载 作者:行者123 更新时间:2023-12-01 13:23:30 29 4
gpt4 key购买 nike

每次检测到匹配项时,我都试图将数据结构插入到向量中,但我什至在编译时都失败了。接下来是代码:

#include <string>
#include <boost/xpressive/xpressive.hpp>
#include <boost/xpressive/regex_actions.hpp>

using namespace boost::xpressive;

struct Data
{
int integer;
double real;
std::string str;

Data(const int _integer, const double _real, const std::string& _str) : integer(_integer), real(_real), str(_str) { }
};

int main()
{
std::vector<Data> container;

std::string input = "Int: 0 - Real: 18.8 - Str: ABC-1005\nInt: 0 - Real: 21.3 - Str: BCD-1006\n";

sregex parser = ("Int: " >> (s1 = _d) >> " - Real: " >> (s2 = (repeat<1,2>(_d) >> '.' >> _d)) >> " - Str: " >> (s3 = +set[alnum | '-']) >> _n)
[::ref(container)->*push_back(Data(as<int>(s1), as<double>(s2), s3))];

sregex_iterator cur(input.begin(), input.end(), parser);
sregex_iterator end;

for(; cur != end; ++cur)
smatch const &what = *cur;

return 0;
}

编译“push_back”语义 Action 失败,因为我在内部使用了一个数据对象,它不能懒惰地使用它(我想,我不太确定)。

拜托,有人可以帮我解决这个问题吗?

注意 - 不幸的是,我使用的是 MS VS 2010(不完全符合 c++11),所以请不要使用可变参数模板和 emplace_back 解决方案。谢谢。

最佳答案

使用 Xpressive

你应该让这个 Action 成为一个懒惰的 Actor 。您的 Data 构造函数调用不是。

Live On Coliru

#include <string>
#include <boost/xpressive/xpressive.hpp>
#include <boost/xpressive/regex_actions.hpp>

namespace bex = boost::xpressive;

struct Data {
int integer;
double real;
std::string str;

Data(int integer, double real, std::string str) : integer(integer), real(real), str(str) { }
};

#include <iostream>

int main() {
std::vector<Data> container;

std::string const& input = "Int: 0 - Real: 18.8 - Str: ABC-1005\nInt: 0 - Real: 21.3 - Str: BCD-1006\n";

using namespace bex;
bex::sregex const parser = ("Int: " >> (s1 = _d) >> " - Real: " >> (s2 = (repeat<1,2>(_d) >> '.' >> _d)) >> " - Str: " >> (s3 = +set[alnum | '-']) >> _n)
[bex::ref(container)->*bex::push_back(bex::construct<Data>(as<int>(s1), as<double>(s2), s3))];

bex::sregex_iterator cur(input.begin(), input.end(), parser), end;

for (auto const& what : boost::make_iterator_range(cur, end)) {
std::cout << what.str() << "\n";
}

for(auto& r : container) {
std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
}
}

打印

Int: 0 - Real: 18.8 - Str: ABC-1005

Int: 0 - Real: 21.3 - Str: BCD-1006

[ 0; 18.8; ABC-1005 ]
[ 0; 21.3; BCD-1006 ]

使用 spirit

我会为此使用 spirit 。 Spirit 具有直接解析为底层数据类型的原语,这样更不易出错且效率更高。

灵气(V2)

使用 Phoenix,它非常相似: Live On Coliru

使用 Fusion 适配,它变得更有趣,也更简单:

Live On Coliru

现在想象一下:

  • 您想匹配不区分大小写的关键字
  • 你想让空格变得无关紧要
  • 您想接受空行,但不想接受中间的随机数据

你会如何在 Xpressive 中做到这一点?这就是你如何使用 Spirit 来做到这一点。请注意,附加约束本质上是如何不改变语法的。将其与基于正则表达式的解析器进行对比。

Live On Coliru

#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/struct.hpp>
namespace qi = boost::spirit::qi;

struct Data {
int integer;
double real;
std::string str;
};

BOOST_FUSION_ADAPT_STRUCT(Data, integer, real, str);

#include <iostream>

int main() {
std::vector<Data> container;
using It = std::string::const_iterator;

std::string const& input = "iNT: 0 - Real: 18.8 - Str: ABC-1005\n\nInt: 1-Real:21.3 -sTR:BCD-1006\n\n";

qi::rule<It, Data(), qi::blank_type> parser = qi::no_case[
qi::lit("int") >> ':' >> qi::auto_ >> '-'
>> "real" >> ':' >> qi::auto_ >> '-'
>> "str" >> ':' >> +(qi::alnum|qi::char_('-')) >> +qi::eol
];

It f = input.begin(), l = input.end();
if (parse(f, l, qi::skip(qi::blank)[*parser], container)) {
std::cout << "Parsed:\n";
for(auto& r : container) {
std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
}
} else {
std::cout << "Parse failed\n";
}

if (f != l) {
std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
}
}

静态打印

Parsed:
[ 0; 18.8; ABC-1005 ]
[ 1; 21.3; BCD-1006 ]

进一步思考:你会怎样

  • 解析科学记数法?负数?
  • 正确解析十进制数(假设您真的要解析财务金额,您可能不希望使用不精确的浮点表示法)

灵X3

如果你可以使用 c++14,Spirit X3 会比 Spirit Qi 或 Xpressive 方法更高效,编译快很多:

Live On Coliru

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

struct Data {
int integer;
double real;
std::string str;
};

BOOST_FUSION_ADAPT_STRUCT(Data, integer, real, str);

namespace Parsers {
using namespace boost::spirit::x3;

static auto const data
= rule<struct Data_, ::Data> {}
= no_case[
lit("int") >> ':' >> int_ >> '-'
>> "real" >> ':' >> double_ >> '-'
>> "str" >> ':' >> +(alnum|char_('-')) >> +eol
];

static auto const datas = skip(blank)[*data];
}

#include <iostream>

int main() {
std::vector<Data> container;

std::string const& input = "iNT: 0 - Real: 18.8 - Str: ABC-1005\n\nInt: 1-Real:21.3 -sTR:BCD-1006\n\n";

auto f = input.begin(), l = input.end();
if (parse(f, l, Parsers::datas, container)) {
std::cout << "Parsed:\n";
for(auto& r : container) {
std::cout << "[ " << r.integer << "; " << r.real << "; " << r.str << " ]\n";
}
} else {
std::cout << "Parse failed\n";
}

if (f != l) {
std::cout << "Remaining input: '" << std::string(f,l) << "'\n";
}
}

打印(越来越无聊):

Parsed:
[ 0; 18.8; ABC-1005 ]
[ 1; 21.3; BCD-1006 ]

关于boost - 如何使用 boost::xpressive 在语义操作中使用结构填充向量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48918172/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com