我不知道 iostreams 是否支持严格的输入格式。
但是,您可以使用 Boost Spirit:
带有 RealPolicy 的标准真实解析器
见http://www.boost.org/doc/libs/1_47_0/libs/spirit/doc/html/spirit/qi/reference/numeric/real.html
这将允许您明确定义指数、符号和任何(数千个)分隔符所接受的格式。这也是一种相当复杂的方法,但它非常快速且非常灵活(也适用于非标准数值类型,IIRC)。
两阶段解析
您可以使用任一 Spirit Qi 规则来指定确切的格式,并且仅当 raw[] 输入序列符合您的要求时才将其传递给标准数字解析器。
涉及更多但也是更优化的方法是使用 Spirit Lexer 对输入进行标记 - 有效地执行相同但更有效的方法。
中间立场
这里的中间立场是使用普通的 (Posix|Perl|C++11|Boost) 正则表达式来验证输入格式并将其传递给任何合适的转换(如 Boost Lexical cast,或者只是std::stringstream >> double 等)
一个示例展示了 Spirit Qi 和正则表达式在工作中的预匹配,同时解析浮点数的格式 (语言是 c++0x1):
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/regex.hpp>
namespace qi=boost::spirit::qi;
namespace phx=boost::phoenix;
bool is_ok(const std::vector<char>& raw)
{
static const boost::regex rx(R"(-?(\d*\.\d+|\d+\.\d*))");
return boost::regex_match(raw.begin(), raw.end(), rx);
}
template <typename Input>
void test(const Input& input)
{
auto f(std::begin(input)), l(std::end(input));
double parsed = 0;
bool ok = qi::phrase_parse(f, l,
// this is the parser expression
&(+qi::char_)[ qi::_pass = phx::bind(is_ok, qi::_1) ]
>> qi::double_,
// end parser expression
qi::space, parsed);
std::cout << "DEBUG: '" << input << "'\t" << std::boolalpha << ok << "\t" << parsed << std::endl;
}
int main()
{
const std::string good[] = { ".300", "300.", "-.4", "-4." };
const std::string wrong[] = { "", ".", "1", "-1", "-1111", "3..", "+1", "+.1", "+1.", "+1.0", "+-2.", "-+2." };
for (auto& input : good)
test(input);
for (auto& input : wrong)
test(input);
}
1 使用 c++11 功能: