gpt4 book ai didi

c++ - 如何使用 qi 解析和验证有序的整数列表

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:36:39 28 4
gpt4 key购买 nike

我正在解析一个文本文件,可能有几 GB 的大小,由以下几行组成:

11 0.1
14 0.78
532 -3.5

基本上,每行一个整数和一个 float 。整数应该是有序的并且是非负的。我想验证数据是否符合描述,并已将范围内的最小和最大整数返回给我。这是我想出的:

#include <iostream>
#include <string>

#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>

namespace px = boost::phoenix;
namespace qi = boost::spirit::qi;

namespace my_parsers
{
using namespace qi;
using px::at_c;
using px::val;
template <typename Iterator>
struct verify_data : grammar<Iterator, locals<int>, std::pair<int, int>()>
{
verify_data() : verify_data::base_type(section)
{
section
= line(val(0)) [ at_c<0>(_val) = _1]
>> +line(_a) [ _a = _1]
>> eps [ at_c<1>(_val) = _a]
;

line
%= (int_ >> other) [
if_(_r1 >= _1)
[
std::cout << _r1 << " and "
<< _1 << val(" out of order\n")
]
]
;

other
= omit[(lit(' ') | '\t') >> float_ >> eol];
}
rule<Iterator, locals<int>, std::pair<int, int>() > section;
rule<Iterator, int(int)> line;
rule<Iterator> other;
};
}

using namespace std;
int main(int argc, char** argv)
{
string input("11 0.1\n"
"14 0.78\n"
"532 -3.6\n");

my_parsers::verify_data<string::iterator> verifier;
pair<int, int> p;
std::string::iterator begin(input.begin()), end(input.end());
cout << "parse result: " << boolalpha
<< qi::parse(begin, end, verifier, p) << endl;
cout << "p.first: " << p.first << "\np.second: " << p.second << endl;
return 0;
}

我想知道的是:

  • 有更好的方法吗?我使用了继承和综合属性、局部变量和一点凤凰巫术。这很棒;学习这些工具很好,但我不禁想到可能有一种更简单的方法来实现同样的事情:/(在 PEG 解析器中......)
  • 例如没有局部变量怎么办?

更多信息:我同时解析了其他数据格式,因此我想将返回值保留为解析器属性。目前这是一个 std::pair,其他数据格式在解析时将公开它们自己的 std::pair,例如,我想将它们填充到 std::vector 中。

最佳答案

这至少已经短了很多:

  • 低至 28 LOC
  • 没有本地人了
  • 不再有 fusion 载体at<>魔法
  • 不再继承属性
  • 没有更多的语法课
  • 不再需要手动迭代
  • 使用期望点(参见 other)来 boost 解析错误报告
  • 这个解析器表达式巧妙地合成了一个 vector<int>如果您选择用 %= 分配它(但它会降低性能,除了可能分配一个较大的数组)

.

#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>

namespace px = boost::phoenix;
namespace qi = boost::spirit::qi;

typedef std::string::iterator It;

int main(int argc, char** argv)
{
std::string input("11 0.1\n"
"14 0.78\n"
"532 -3.6\n");

int min=-1, max=0;
{
using namespace qi;
using px::val;
using px::ref;

It begin(input.begin()), end(input.end());
rule<It> index = int_
[
if_(ref(max) < _1) [ ref(max) = _1 ] .else_ [ std::cout << _1 << val(" out of order\n") ],
if_(ref(min) < 0) [ ref(min) = _1 ]
] ;

rule<It> other = char_(" \t") > float_ > eol;

std::cout << "parse result: " << std::boolalpha
<< qi::parse(begin, end, index % other) << std::endl;
}
std::cout << "min: " << min << "\nmax: " << max << std::endl;
return 0;
}

奖金

我可能会建议从表达式中取出验证并使其成为一个独立的函数;当然,这会让事情变得更冗长(而且……更清晰),我的脑残样本使用了全局变量……——但我相信你知道如何使用 boost::bindpx::bind让它更真实

除此之外

  • 即使使用免费功能也可以降低到 27 LOC
  • 不再有 phoenix,不再有 phoenix 包含(是的编译时间)
  • 调试构建中不再有 phoenix 表达式类型膨胀二进制文件并减慢速度
  • 没有了 var , ref , if_ , .else_和可怜的operator, (由于过载未包含在 phoenix.hpp 中,因此存在重大错误风险(在某些时候)
  • (轻松移植到 c++0x lambda - 立即消除对全局变量的需要)

.

#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
namespace px = boost::phoenix;
namespace qi = boost::spirit::qi;
typedef std::string::iterator It;

int min=-1, max=0, linenumber=0;
void validate_index(int index)
{
linenumber++;
if (min < 0) min = index;
if (max < index) max = index;
else std::cout << index << " out of order at line " << linenumber << std::endl;
}

int main(int argc, char** argv)
{
std::string input("11 0.1\n"
"14 0.78\n"
"532 -3.6\n");
It begin(input.begin()), end(input.end());

{
using namespace qi;

rule<It> index = int_ [ validate_index ] ;
rule<It> other = char_(" \t") > float_ > eol;
std::cout << "parse result: " << std::boolalpha
<< qi::parse(begin, end, index % other) << std::endl;
}
std::cout << "min: " << min << "\nmax: " << max << std::endl;
return 0;
}

关于c++ - 如何使用 qi 解析和验证有序的整数列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6431404/

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