Я не знаю о поддержке 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 и regex на работе при разборе числового формата для чисел с плавающей запятой (язык c ++ 0x 1 )
#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 feat:
- на основе диапазона для
- необработанные строковые литералы для спецификации регулярных выражений