如何用Boost Spirit Qi解析带大小写不敏感公制前缀的数值并返回转换后的值?
实现带公制前缀的数值解析(Boost Spirit Qi)
要实现将带公制前缀的字符串转换为对应数值,核心是通过语义动作将匹配到的后缀映射为乘数,再与前面的数值相乘得到最终结果。以下是修改后的完整代码:
#include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix.hpp> namespace qi = boost::spirit::qi; namespace phoenix = boost::phoenix; using iter = std::string::const_iterator; class MyGrammar : public qi::grammar<iter, double()> { public: MyGrammar() : MyGrammar::base_type(start) { // 定义后缀与乘数的映射,支持大小写不敏感 suffix = qi::no_case[ qi::char_('k')[qi::_val = 1000.0] ]; // 主规则:数值 * 乘数(无后缀时乘数为1.0) start = (qi::double_ >> suffix)[qi::_val = qi::_1 * qi::_2] | qi::double_[qi::_val = qi::_1]; } qi::rule<iter, double()> suffix; qi::rule<iter, double()> start; }; // 测试示例 #include <iostream> #include <string> int main() { MyGrammar grammar; std::string input1 = "10k"; std::string input2 = "15.5K"; std::string input3 = "200"; double result; iter begin, end; begin = input1.begin(); end = input1.end(); if (qi::parse(begin, end, grammar, result)) { std::cout << input1 << " → " << result << std::endl; // 输出10000 } begin = input2.begin(); end = input2.end(); if (qi::parse(begin, end, grammar, result)) { std::cout << input2 << " → " << result << std::endl; // 输出15500 } begin = input3.begin(); end = input3.end(); if (qi::parse(begin, end, grammar, result)) { std::cout << input3 << " → " << result << std::endl; // 输出200 } return 0; }
关键修改说明:
- 调整模板参数:将
qi::grammar<iter>改为qi::grammar<iter, double()>,表示整个语法解析后返回double类型;规则suffix和start也对应改为qi::rule<iter, double()>,用于返回乘数和最终结果。 - 语义动作映射乘数:通过
qi::_val设置规则的返回值,比如匹配到k或K时,suffix规则返回1000.0。使用qi::no_case简化大小写不敏感匹配,无需分别写'k'和'K'。 - 计算最终结果:主规则
start中,用qi::_1获取前面的数值,qi::_2获取后缀的乘数,两者相乘后赋值给qi::_val作为最终结果;无后缀的分支直接返回原始数值。 - 依赖Phoenix库:语义动作需要Boost Phoenix支持,因此要包含
<boost/spirit/include/phoenix.hpp>,qi::_1、qi::_2、qi::_val都是Phoenix的占位符。
如果需要扩展更多公制前缀(如m对应0.001,M对应1e6等),只需在suffix规则中添加更多分支即可,例如:
suffix = qi::no_case[ qi::char_('k')[qi::_val = 1000.0] | qi::char_('m')[qi::_val = 0.001] | qi::char_('M')[qi::_val = 1e6] ];
内容的提问来源于stack exchange,提问作者user3814483
相关产品推荐
相关产品推荐

