提高精神固定点作为整数解析器

时间:2019-01-08 13:21:32

标签: c++ boost-spirit

我有以下解析器,

    #define PRICE_MULT 10000
    qi::uint_parser<uint32_t, 10, 1, 6> int_part;
    qi::uint_parser<uint32_t, 10, 1, 6> dec_part;

    qi::rule<Iterator, uint64_t()> fixed_point =
         (int_part >> "." >> dec_part )[qi::_val = qi::_1 * PRICE_MULT + qi::_2];


    m_wire_msg = ( qi::as_string[*qi::alpha] >> "," // symbol
                >> qi::ulong_long >> ","        // symbol seq num
                >> qi::ulong_long >> ","        // order id
                >> (fixed_point | qi::ulong_) >> ","
                >> qi::uint_ >> ","                   // volume
                >> qi::char_ >> ","                   // side
                >> +qi::space >> ","                  // firm id
                >> qi::ushort_                        // parity split

但是它无法解析

"AAPL,1192544,16044086616349464,157.47,100,S,     ,0"

具体来说,157.47有时可以是整数,例如。 157本身,这就是为什么我使用“(fixed_point | qi :: ulong _)”。

但是解析失败,我不太了解。理想情况下,还应该正确解析以下内容,

"AAPL,1192544,16044086616349464,157,100,S,     ,0"

非常感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

如果没有小数部分,请使用可选的解析器使之不会失败。

您也有PRICE_MULT带有4个零,但是dec_part允许最多6位数字。

#define PRICE_MULT 10000
qi::uint_parser<std::uint32_t, 10, 1, 6> int_part;
qi::uint_parser<std::uint32_t, 10, 1, 4> dec_part;

qi::rule<Iterator, std::uint64_t()> fixed_point =
      int_part[qi::_val = qi::_1 * PRICE_MULT]
    >> -('.' >> dec_part[qi::_val += qi::_1]);

https://wandbox.org/permlink/H46ujDgJ57gyE69I

正确的定点解析器如下所示:

constexpr std::uint64_t lut[] = { 1, 10, 100, 1000, 10000, 100000, 1000000 };
constexpr int frac_digits = 6;
qi::uint_parser<std::uint32_t, 10, 1, 6> const int_part;
qi::uint_parser<std::uint32_t, 10, 1, frac_digits> const dec_part;
qi::rule<Iterator, std::uint64_t()> fixed_point
    = int_part[qi::_val = qi::_1 * lut[frac_digits]]           // parse integer part and save multiplied by lut[frac_digits]
   >> ( !qi::lit('.')                                          // do not fail on missing fractional part
      | ('.' >>  qir::iter_pos >> dec_part >> qir::iter_pos)[  // parse fraction and save/syntesize iterators before and after
                    qi::_val += qi::_2 * phx::ref(lut)[        // multiple fraction by lookuped pow10 value
                                            frac_digits - (qi::_3 - qi::_1)]]
        >> *qi::digit);                                        // consume unparsed digits

https://wandbox.org/permlink/mtdMDPzB2RjPxQlD

input          result
=====          ======
123            123000000 
123.0          123000000
123.4          123400000
123.45         123450000
123.456        123456000
123.4567       123456700
123.45678      123456780
123.456789     123456789
123.456789123  123456789
123.           fail
.123           fail

答案 1 :(得分:0)

如果我想乘以10000来使157.47等于1574700,以下方法是最好的方法吗?

m_fixed_point = m_int_part[qi::_val = qi::_1 * PRICE_MULT] >>
-("." >> -(m_digit[qi::_val += qi::_1 * 1000])
>> -(m_digit[qi::_val += qi::_1 * 100])
>> -(m_digit[qi::_val += qi::_1 * 10])
>> -(m_digit[qi::_val += qi::_1 ])
);