如何使用boost::spirit将文本解析为结构
How to parse text into a struct using boost::spirit?
我正在学习boost::spirit
,我正在尝试将一些文本读取并解析为结构。
例如,"2: 4.6"
在下面的TestStruct
中被解析为 int 2
和双4.6
:
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/support_istream_iterator.hpp>
#include <boost/fusion/include/std_pair.hpp>
namespace qi = boost::spirit::qi;
struct TestStruct {
int myint;
double mydouble;
TestStruct() {}
TestStruct(std::pair<int,double> p) : myint(p.first), mydouble(p.second) {}
};
template <typename Iterator, typename Skipper>
struct MyGrammar : qi::grammar<Iterator, TestStruct(), Skipper> {
MyGrammar() : MyGrammar::base_type(mystruct) {
mystruct0 = qi::int_ >> ":" >> qi::double_;
mystruct = mystruct0;
}
qi::rule<Iterator, std::pair<int,double>(), Skipper> mystruct0;
qi::rule<Iterator, TestStruct(), Skipper> mystruct;
};
int main() {
typedef boost::spirit::istream_iterator It;
std::cin.unsetf(std::ios::skipws);
It it(std::cin), end; // input example: "2: 3.4"
MyGrammar<It, qi::space_type> gr;
TestStruct ts;
if (qi::phrase_parse(it, end, gr, qi::space, ts) && it == end)
std::cout << ts.myint << ", " << ts.mydouble << std::endl;
return 0;
}
它工作得很好,但我想知道如何简化这段代码?
例如,我想摆脱mystruct0
语法规则,该规则仅用于标记类型std::pair<int,double>
,然后用于从mystruct
规则自动构造TestStruct
对象。
如果可能的话,我还希望能够从std::pair
中删除TestStruct
构造函数。
那么,下面的代码可以以某种方式编译吗?这将是一个更好的解决方案:
struct TestStruct {
int myint;
double mydouble;
TestStruct() {}
TestStruct(int i, double d) : myint(i), mydouble(d) {}
};
template <typename Iterator, typename Skipper>
struct MyGrammar : qi::grammar<Iterator, TestStruct(), Skipper> {
MyGrammar() : MyGrammar::base_type(mystruct) {
mystruct = qi::int_ >> ":" >> qi::double_;
}
qi::rule<Iterator, TestStruct(), Skipper> mystruct;
};
int main() {
typedef boost::spirit::istream_iterator It;
std::cin.unsetf(std::ios::skipws);
It it(std::cin), end; // input example: "2: 3.4"
MyGrammar<It, qi::space_type> gr;
TestStruct ts;
if (qi::phrase_parse(it, end, gr, qi::space, ts) && it == end)
std::cout << ts.myint << ", " << ts.mydouble << std::endl;
return 0;
}
不幸的是,编译器说:
boost_1_49_0/include/boost/spirit/home/qi/detail/assign_to.hpp:123:
error: no matching function for call to ‘TestStruct::TestStruct(const int&)’
为了能够将值"按顺序"解析为结构,您需要将其转换为fusion
元组,如此处所述。
在您的情况下,这意味着您需要
-
包括必要的标头
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
-
使用融合适应结构宏。最好把它放在
TestStruct
声明之后:BOOST_FUSION_ADAPT_STRUCT( TestStruct, (int,myint) (double,mydouble) )
通过这两项更改,简化版本将编译并生成所需的结果。不确定它现在是否真的简单得多 - 但如果您打算向结构中添加更多成员,这是一个很好的起点,因为它可能有助于简化将来的事情。
我没有看到您可以进行任何其他重大更改以使程序更简单。
是的,代码可以编译。事实上,你可以不用构造函数:默认的(编译器生成的)构造函数很好。
您需要做的就是将结构调整为融合序列。(作为奖励,这也适用于业力。
这正是最初使std::pair
起作用的魔力。
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/struct.hpp>
namespace qi = boost::spirit::qi;
struct TestStruct {
int myint;
double mydouble;
};
BOOST_FUSION_ADAPT_STRUCT(TestStruct, (int, myint)(double, mydouble));
template <typename Iterator, typename Skipper>
struct MyGrammar : qi::grammar<Iterator, TestStruct(), Skipper> {
MyGrammar() : MyGrammar::base_type(mystruct) {
mystruct = qi::int_ >> ":" >> qi::double_;
}
qi::rule<Iterator, TestStruct(), Skipper> mystruct;
};
int main() {
typedef std::string::const_iterator It;
const std::string input("2: 3.4");
It it(input.begin()), end(input.end());
MyGrammar<It, qi::space_type> gr;
TestStruct ts;
if (qi::phrase_parse(it, end, gr, qi::space, ts) && it == end)
std::cout << ts.myint << ", " << ts.mydouble << std::endl;
return 0;
}
相关文章:
- C++将文本文件中的数据读取到结构数组中
- 将文本文件解析为树状数据结构
- 调用 cout 时如何在结构中输出常量文本?
- 从文本文件中读取并输入到数组结构中,然后显示读取的数据C++
- 将文本文件读取到数组结构中
- 使用结构数组计算文本文件中单词的出现次数C++
- 具有引用数据成员的结构不是文本类型吗?
- 如何将 C# 文本框输入与 C 结构和导入一起使用
- 用 C++ 将结构写入文本文件
- 将数据从文本文件读取到C++结构中
- 如何将来自文本文件的数据读取到结构的int阵列中
- 如何创建名称作为文本文件第一行的结构?
- 非常简单的C 文本冒险的代码结构
- 如何将文本文件保存到C 中的字符串结构
- 尝试使用文本文件初始化多个结构变量
- 尝试将文本文件读入 C++ 中的结构数组
- 结构数组写入文本文件
- 最佳数据结构存储文本文件中的数字集
- 将Boost序列化文本存档转换为结构化格式
- C++ 从文本文件数据类型读取为结构,并将数据存储在列表的向量中