- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我必须处理文本格式的非常长的整数——长到无法放入 32 位整数。我需要将这样的文本解析成
boost::variant<int, double>.
因此,如果对于一个整数来说有一个长整数到大整数,它需要进入 double 。请参见下面的示例。它不解析名称值对
MUESR1 = 411100000000000.
如何解决这个问题?
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <iterator>
namespace qi = boost::spirit::qi;
namespace spirit = boost::spirit;
namespace ascii = boost::spirit::ascii;
typedef boost::variant<int, double> VALUE;
typedef std::pair<std::string, VALUE> PAIR;
typedef std::map<std::string, VALUE> PAIRS;
template<typename Iterator>
struct parameters:qi::grammar<Iterator, PAIRS(), ascii::space_type>
{
qi::rule<Iterator, std::string(), ascii::space_type> m_sName;
qi::rule<Iterator, VALUE(), ascii::space_type> m_sValue;
qi::rule<Iterator, PAIR(), ascii::space_type> m_sNameValue;
qi::rule<Iterator, PAIRS(), ascii::space_type> m_sRoot;
qi::real_parser<double, qi::strict_real_policies<double> > m_sReal;
parameters(void)
:parameters::base_type(m_sRoot)
{ m_sName %= qi::lexeme[qi::char_("a-zA-Z_") >> *qi::char_("a-zA-z_0-9")];
m_sValue %= m_sReal | spirit::int_;
m_sNameValue %= m_sName >> qi::lit('=') >> m_sValue >> -qi::lit('\n');
m_sRoot %= m_sNameValue >> *m_sNameValue;
}
};
int main(int, char**)
{
static const char s_ap[] = "\
MUEPH1 = 7.014158 MUEPHW= -0.3 MUEPWP = 0.23 MUEPHL= -0.72 MUEPLP = 3.4 MUEPHS = 2.976E-07 MUEPSP = 5 VTMP= -1.8463 WVTH0= -1.01558 MUESR0 = 0.01256478438899837 MUESR1 = 411100000000000\n\
MUEPHW2 = 0 MUEPWP2 = 1\n";
parameters<const char*> sGrammar;
const char *pIter = s_ap;
const char *const pEnd = s_ap + sizeof s_ap - 1;
PAIRS sValues;
if (phrase_parse(pIter, pEnd, sGrammar, boost::spirit::ascii::space, sValues) && pIter == pEnd)
{ std::cerr << "parsing successful!" << std::endl;
for (const auto &r : sValues)
std::cout << r.first << "=" << std::scientific << r.second << std::endl;
}
else
{ std::cerr << "parsing failed!" << std::endl;
std::cerr << pIter << std::endl;
}
}
最佳答案
是的,语法只要求解析严格的实数。如果您不想这样,则需要接受其他实数。 @llonesmiz 的评论是一种方法。
Alternatively, it seems like you could just parse doubles. Though binary real representation can be "lossy" that doesn't happen for the integral part of the mantissa until you exceed the 52/53 bits of significand (https://en.wikipedia.org/wiki/Double-precision_floating-point_format). By comparison, popular compilers have
int
at 32 bits.
//#define BOOST_SPIRIT_DEBUG
#include <boost/fusion/include/std_pair.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iterator>
#include <iomanip>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
typedef boost::variant<int, double> VALUE;
typedef std::pair<std::string, VALUE> PAIR;
typedef std::map<std::string, VALUE> PAIRS;
template <typename Iterator> struct parameters : qi::grammar<Iterator, PAIRS(), ascii::space_type> {
parameters(void) : parameters::base_type(m_sRoot) {
m_sName = qi::lexeme[qi::char_("a-zA-Z_") >> *qi::char_("a-zA-z_0-9")];
m_sValue = m_sReal | qi::int_ | qi::double_;
m_sNameValue = m_sName >> '=' >> m_sValue >> -qi::lit('\n');
m_sRoot = m_sNameValue >> *m_sNameValue;
BOOST_SPIRIT_DEBUG_NODES((m_sName)(m_sValue)(m_sNameValue)(m_sRoot))
}
private:
qi::rule<Iterator, std::string(), ascii::space_type> m_sName;
qi::rule<Iterator, VALUE(), ascii::space_type> m_sValue;
qi::rule<Iterator, PAIR(), ascii::space_type> m_sNameValue;
qi::rule<Iterator, PAIRS(), ascii::space_type> m_sRoot;
qi::real_parser<double, qi::strict_real_policies<double> > m_sReal;
};
int main(int, char **) {
static const char s_ap[] = R"(
MUEPH1 = 7.014158 MUEPHW= -0.3 MUEPWP = 0.23 MUEPHL= -0.72 MUEPLP = 3.4 MUEPHS = 2.976E-07 MUEPSP = 5 VTMP= -1.8463 WVTH0= -1.01558 MUESR0 = 0.01256478438899837 MUESR1 = 411100000000000
MUEPHW2 = 0 MUEPWP2 = 1
)";
parameters<const char*> sGrammar;
const char *pIter = std::begin(s_ap);
const char *const pEnd = std::end(s_ap) - 1;
PAIRS sValues;
if (phrase_parse(pIter, pEnd, sGrammar, boost::spirit::ascii::space, sValues) && pIter == pEnd) {
std::cerr << "parsing successful!" << std::endl;
for (const auto &r : sValues)
std::cout << r.first << "=" << std::scientific << std::setprecision(2) << r.second << std::endl;
} else {
std::cerr << "parsing failed!" << std::endl;
std::cerr << std::quoted(std::string(pIter, pEnd)) << std::endl;
}
}
另请注意常规改进,例如向您的规则添加调试。
关于c++ - boost::spirit 和 strict_real_policies 无法解析太长的整数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53400077/
我必须处理文本格式的非常长的整数——长到无法放入 32 位整数。我需要将这样的文本解析成 boost::variant. 因此,如果对于一个整数来说有一个长整数到大整数,它需要进入 double 。请
我是一名优秀的程序员,十分优秀!