正在分析未知类型的数字字符串

Parsing numeric strings of unknown type?

本文关键字:数字 数字字符 字符串 类型 未知      更新时间:2023-10-16

当目标类型事先未知时,在C++中将std::string解析为某个数字类型的最佳方法是什么?

我已经看过lexical_cast,但它将目标类型作为模板参数。我可以编写包装器函数,通过捕获bad_lexical_cast并返回false来滥用这一点,但这看起来很难看。

我的输入值通常是intfloat,并且具有非常简单的格式,但灵活的东西会很棒!

您可以使用Boost Spirit Numerical Parsers或(ab)使用Boost Lexicalcast。

Boost Spirit允许您对接受的格式进行细粒度控制,例如参见

  • RealPolicies

这里有一个快速演示,还展示了如何检测几种可能的数字输入格式(渐进)并返回匹配的类型。当然,这可能有些过头了,但它应该展示如何进一步使用Spirit。

演示还展示了如何推进输入迭代器,以便您可以轻松地继续解析数字输入的结束位置。

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
enum numeric_types
{
    fmt_none,
    fmt_float,
    fmt_double,
    fmt_uint,
    fmt_int,
    // fmt_hex, etc. 
};
template <typename It>
    bool is_numeric(It& f, It l, numeric_types& detected)
{
    return qi::phrase_parse(f,l,
            qi::uint_   [ qi::_val = fmt_uint   ]
          | qi::int_    [ qi::_val = fmt_int    ]
          | qi::float_  [ qi::_val = fmt_float  ]
          | qi::double_ [ qi::_val = fmt_double ]
           ,qi::space, detected);
}
template <typename It>
    bool is_numeric(It& f, It l)
{
    numeric_types detected = fmt_none;
    return is_numeric(f, l, detected);
}
int main()
{
    const std::string input = "124, -25, 582";
    std::string::const_iterator it = input.begin();
    bool ok = is_numeric(it, input.end());
    if (ok)   
    {
        std::cout << "parse successn";
        if (it!=input.end()) 
            std::cerr << "trailing unparsed: '" << std::string(it,input.end()) << "'n";
    }
    else 
        std::cerr << "parse failed: '" << std::string(it,input.end()) << "'n";
    return ok? 0 : 255;
}

当您实际解析数据进行转换时,您需要知道将结果放入其中的类型;C++是一种静态类型语言,这是没有办法的。如果你有一个字符串,并且想知道它是什么类型的,使用正则表达式是一个简单的解决方案:

"\s*[+-]?(?:"
    "\d+\.\d*(?:[Ee][+-]?\d+)?"
    "|\.\d+(?:[Ee][+-]?\d+)?"
    "|\d+[Ee][+-]?\d+"
")"

应匹配任何可能的浮点值,并且:

"\s*[+-]?(?:"
    "[1-9][0-9]*"
    "|0[0-7]*"
    "|0x[0-9a-fA-F]+"
)"

匹配任意基数的整数。(假设Boost或C++11正则表达式的默认配置。)