假设我要解析以下字符串:
“1.2,2.0,3.9”
当我为它应用以下解析器时:
struct DataStruct
{
double n1, n2, n3;
};
BOOST_FUSION_ADAPT_STRUCT(DataStruct, (double, n1)(double, n2)(double, n3))
qi::rule<std::string::iterator, DataStruct()> data_ =
qi::double_ >> ','
>> qi::double_ >> ','
>> qi::double_;
auto str = "1.2, 2.0, 3.9";
auto it - str.begin();
if (qi::parse(it, str.end(), data_, res))
{
std::cout << "parse completed" << std::endl;
}
一切都还可以,但是当我想在我的字符串中不是一些double时,我可以得到“null”(即“1.2,null,3.9”)我想在DataStruct中将0值赋给适当的double值。有办法做到这一点吗?
答案 0 :(得分:3)
通常的诀窍是使用qi::attr
的替代方案:
rule_def = parser_expression | qi::attr(default_value);
在你的情况下,也许:
reader_ = qi::double_ | qi::lit("null") >> qi::attr(0);
<强> Live On Coliru 强>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
struct DataStruct { double n1, n2, n3; };
BOOST_FUSION_ADAPT_STRUCT(DataStruct, n1, n2, n3)
namespace qi = boost::spirit::qi;
int main() {
using Iterator = typename std::string::const_iterator;
qi::rule<Iterator, double()> reader_ = qi::double_ | qi::lit("null") >> qi::attr(0);
qi::rule<Iterator, DataStruct()> data_ = reader_ >> ',' >> reader_ >> ',' >> reader_;
DataStruct res;
auto const str = std::string("1.2,null,3.9");
Iterator start = str.begin(), end = str.end();
if (qi::parse(start, end, data_ >> qi::eoi, res)) {
std::cout << "parsed: " << boost::fusion::as_vector(res) << "\n";
}
else {
std::cout << "parse failed\n";
}
}
打印
parsed: (1.2 0 3.9)
请注意审核更改(不使用命名空间,请检查eoi
)。
答案 1 :(得分:1)
您可以使用以下代码:
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
struct DataStruct
{
double n1, n2, n3;
};
BOOST_FUSION_ADAPT_STRUCT(DataStruct, (double, n1)(double, n2)(double, n3))
int main() {
using namespace boost::spirit;
using Iterator = typename std::string::iterator;
qi::rule<Iterator, double()> reader_ = (qi::double_[_val = _1] | (lexeme["null"])[_val = 0.]);
qi::rule<Iterator, DataStruct()> data_ = reader_ >> ',' >> reader_ >> ',' >> reader_;
try {
DataStruct res;
auto str = std::string("1.2,null,3.9");
auto start = str.begin();
auto end = str.end();
bool ok = qi::parse(start, end, data_, res);
if (ok) {
std::cout << "parse completed" << std::endl;
}
else {
std::cout << "parse failed" << std::endl;
}
}
catch (const qi::expectation_failure<std::string::iterator>& except) {
std::cout << except.what();
}
std::cout << std::endl;
}