当目标类型事先不知道时,将std::string
解析为C ++中的某些数字类型的最佳方法是什么?
我查看了lexical_cast,但是它将目标类型作为模板参数。我可以通过捕获bad_lexical_cast
并返回false
来编写滥用此功能的包装函数,但这看起来很难看。
我的输入值通常为int
或float
,格式非常简单,但灵活的内容会很棒!
答案 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正则表达式的默认配置。)