如何用Boost.Qi解析带符号int8_t转为double及扩展前缀支持?
解决Boost.Qi解析带符号int8_t及类型前缀的问题
编译错误修正
你的代码存在两处基础语法错误,导致编译失败:
number = parse_number [ _val = _1 ]语句末尾缺少分号,编译器无法正确识别语句边界。- struct定义结束后未添加分号,这是C++结构体定义的强制语法要求。
此外,默认的qi::int_parser<int8_t>会检查数值范围,输入255会因超出int8_t的合法范围(-128~127)导致解析失败,而非自动溢出为-1,需要显式设置溢出策略。
正确实现代码
以下是满足你需求的完整实现,支持无前缀、(u8)前缀、(s8)前缀的解析逻辑:
#include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix.hpp> #include <cstdint> #include <vector> #include <string> #include <iostream> namespace qi = boost::spirit::qi; namespace phoenix = boost::phoenix; template <typename Iterator> struct number_grammar : qi::grammar<Iterator, double()> { number_grammar() : number_grammar::base_type(start) { // 配置解析器:(s8)前缀需要允许溢出wrap qi::int_parser<int8_t, 10, 1, 3> s8_parser; s8_parser.set_overflow_policy(qi::overflow_policy::wrap); qi::uint_parser<uint8_t, 10, 1, 3> u8_parser; qi::uint_parser<uintmax_t, 10> default_parser; // 定义各类型解析规则 s8_rule = "(s8)" >> s8_parser[qi::_val = phoenix::static_cast_<double>(qi::_1)]; u8_rule = "(u8)" >> u8_parser[qi::_val = phoenix::static_cast_<double>(qi::_1)]; default_rule = default_parser[qi::_val = phoenix::static_cast_<double>(qi::_1)]; // 规则优先级:前缀规则优先匹配,避免被默认规则截断 number = s8_rule | u8_rule | default_rule; start = qi::skip(qi::space)[number]; } private: qi::rule<Iterator, double()> start; qi::rule<Iterator, double()> number; qi::rule<Iterator, double()> s8_rule; qi::rule<Iterator, double()> u8_rule; qi::rule<Iterator, double()> default_rule; }; int main() { number_grammar<std::string::const_iterator> grammar; std::vector<std::string> test_cases = {"255", "(u8)255", "(s8)255"}; for (const auto& str : test_cases) { std::string::const_iterator iter = str.begin(); std::string::const_iterator end = str.end(); double result; bool success = qi::parse(iter, end, grammar, result); if (success && iter == end) { std::cout << str << " : " << result << std::endl; } else { std::cout << str << " : 解析失败" << std::endl; } } return 0; }
关键实现说明
- 溢出策略配置:针对(s8)前缀的解析器,通过
set_overflow_policy(qi::overflow_policy::wrap)开启溢出环绕,使得255超出int8_t范围时自动转换为-1。 - 规则优先级:将带前缀的解析规则放在前面,确保"(s8)255"这类字符串不会被默认规则错误匹配。
- 类型转换:使用Phoenix库的
static_cast_将解析得到的整数类型安全转换为double。
运行结果
编译运行后会输出:
255 : 255 (u8)255 : 255 (s8)255 : -1
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

