You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Boost.Qi解析带符号int8_t转为double及扩展前缀支持?

解决Boost.Qi解析带符号int8_t及类型前缀的问题

编译错误修正

你的代码存在两处基础语法错误,导致编译失败:

  1. number = parse_number [ _val = _1 ] 语句末尾缺少分号,编译器无法正确识别语句边界。
  2. 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;
}

关键实现说明

  1. 溢出策略配置:针对(s8)前缀的解析器,通过set_overflow_policy(qi::overflow_policy::wrap)开启溢出环绕,使得255超出int8_t范围时自动转换为-1。
  2. 规则优先级:将带前缀的解析规则放在前面,确保"(s8)255"这类字符串不会被默认规则错误匹配。
  3. 类型转换:使用Phoenix库的static_cast_将解析得到的整数类型安全转换为double。

运行结果

编译运行后会输出:

255 : 255
(u8)255 : 255
(s8)255 : -1

内容的提问来源于stack exchange,提问作者Daniel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 04:09:54