解析未知类型的数字字符串?

时间:2012-02-20 08:29:32

标签: c++ string parsing numbers

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

我查看了lexical_cast,但是它将目标类型作为模板参数。我可以通过捕获bad_lexical_cast并返回false来编写滥用此功能的包装函数,但这看起来很难看。

我的输入值通常为intfloat,格式非常简单,但灵活的内容会很棒!

2 个答案:

答案 0 :(得分:3)

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

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

这是一个快速演示,它还展示了如何检测几种可能的数字输入格式(逐步)并返回匹配的类型。当然这可能是矫枉过正,但它应该展示如何进一步使用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 success\n";
        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;
}

答案 1 :(得分:1)

当您实际解析数据以进行转换时,您需要知道 输入结果的类型; 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正则表达式的默认配置。)