使用boost spirit解析中间有非数字的整数
Parse an integer with non-digits in between using boost spirit
我正在尝试从中间带有非数字的字符串中解析数值。有没有可能用boost spirit来做?例如,
std::string s = "AB1234xyz5678C9";
int x = 0;
boost::spirit::qi::parse(s.begin(), s.end(), /* Magic Input */, x);
// x will be equal 123456789
一点技巧:
weird_num = as_string[ skip(alpha) [+digit] ] [_val = stol_(_1) ];
这需要您调整 std::stol
以便在语义操作中使用:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
BOOST_PHOENIX_ADAPT_FUNCTION(long, stol_, std::stol, 1);
namespace qi = boost::spirit::qi;
int main()
{
std::string const s = "AB1234xyz5678C9";
qi::rule<std::string::const_iterator, long()> weird_num;
{
using namespace qi;
weird_num = as_string[ skip(alpha) [+digit] ] [_val = stol_(_1) ];
}
long x = 0;
if (boost::spirit::qi::parse(s.begin(), s.end(), weird_num, x))
std::cout << "Got it: " << x << "\n";
}
版画
Got it: 123456789
我认为这很容易完成,但是,这是使用 boost::spirit
的工作变体。
#include <string>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/spirit/include/qi.hpp>
struct integer_collector
{
public:
void collect(int v) const
{
stream << v;
}
int get() const
{
int result = 0;
stream >> result;
return result;
}
private:
mutable std::stringstream stream;
};
int main()
{
using namespace boost::spirit::qi;
std::string s = "AB1234xyz5678C9";
integer_collector collector;
int x = 0;
boost::spirit::qi::parse(s.begin(), s.end(),
*(omit[*alpha] >> int_ >> omit[*alpha])
[boost::bind(&integer_collector::collect, boost::ref(collector),
boost::placeholders::_1)]);
x = collector.get();
std::cout << x << std::endl;
}
这是一种方法:
namespace qi = boost::spirit::qi;
std::string s = "AB1234xyz5678C9";
int x = 0;
auto f = [&x](char c){ if (::isdigit(c)) x = x * 10 + (c - '0'); };
qi::parse(s.begin(), s.end(), +(qi::char_[f]));
[编辑]
或者,没有 isdigit:
auto f = [&x](char c){ x = x * 10 + (c - '0'); };
qi::parse(s.begin(), s.end(), +(qi::char_("0-9")[f] | qi::char_));
[编辑 2]
或者,没有 lambda:
#include "boost\phoenix.hpp"
...
namespace phx=boost::phoenix;
qi::parse(s.begin(), s.end(),+(qi::char_("0-9")
[phx::ref(x) = phx::ref(x) * 10 + qi::_1 - '0'] | qi::char_));
[编辑 3]
或者,使用递归规则:
qi::rule<std::string::iterator, int(int)> skipInt =
(qi::char_("0-9")[qi::_val = qi::_r1 * 10 + (qi::_1 - '0')]
| qi::char_[qi::_val = qi::_r1])
>> -skipInt(qi::_val)[qi::_val = qi::_1];
qi::parse(s.begin(), s.end(), skipInt(0), x);
我正在尝试从中间带有非数字的字符串中解析数值。有没有可能用boost spirit来做?例如,
std::string s = "AB1234xyz5678C9";
int x = 0;
boost::spirit::qi::parse(s.begin(), s.end(), /* Magic Input */, x);
// x will be equal 123456789
一点技巧:
weird_num = as_string[ skip(alpha) [+digit] ] [_val = stol_(_1) ];
这需要您调整 std::stol
以便在语义操作中使用:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
BOOST_PHOENIX_ADAPT_FUNCTION(long, stol_, std::stol, 1);
namespace qi = boost::spirit::qi;
int main()
{
std::string const s = "AB1234xyz5678C9";
qi::rule<std::string::const_iterator, long()> weird_num;
{
using namespace qi;
weird_num = as_string[ skip(alpha) [+digit] ] [_val = stol_(_1) ];
}
long x = 0;
if (boost::spirit::qi::parse(s.begin(), s.end(), weird_num, x))
std::cout << "Got it: " << x << "\n";
}
版画
Got it: 123456789
我认为这很容易完成,但是,这是使用 boost::spirit
的工作变体。
#include <string>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/spirit/include/qi.hpp>
struct integer_collector
{
public:
void collect(int v) const
{
stream << v;
}
int get() const
{
int result = 0;
stream >> result;
return result;
}
private:
mutable std::stringstream stream;
};
int main()
{
using namespace boost::spirit::qi;
std::string s = "AB1234xyz5678C9";
integer_collector collector;
int x = 0;
boost::spirit::qi::parse(s.begin(), s.end(),
*(omit[*alpha] >> int_ >> omit[*alpha])
[boost::bind(&integer_collector::collect, boost::ref(collector),
boost::placeholders::_1)]);
x = collector.get();
std::cout << x << std::endl;
}
这是一种方法:
namespace qi = boost::spirit::qi;
std::string s = "AB1234xyz5678C9";
int x = 0;
auto f = [&x](char c){ if (::isdigit(c)) x = x * 10 + (c - '0'); };
qi::parse(s.begin(), s.end(), +(qi::char_[f]));
[编辑] 或者,没有 isdigit:
auto f = [&x](char c){ x = x * 10 + (c - '0'); };
qi::parse(s.begin(), s.end(), +(qi::char_("0-9")[f] | qi::char_));
[编辑 2] 或者,没有 lambda:
#include "boost\phoenix.hpp"
...
namespace phx=boost::phoenix;
qi::parse(s.begin(), s.end(),+(qi::char_("0-9")
[phx::ref(x) = phx::ref(x) * 10 + qi::_1 - '0'] | qi::char_));
[编辑 3] 或者,使用递归规则:
qi::rule<std::string::iterator, int(int)> skipInt =
(qi::char_("0-9")[qi::_val = qi::_r1 * 10 + (qi::_1 - '0')]
| qi::char_[qi::_val = qi::_r1])
>> -skipInt(qi::_val)[qi::_val = qi::_1];
qi::parse(s.begin(), s.end(), skipInt(0), x);