Должен ли поток строк анализировать «INFINITY»? как бесконечное значение?

Глядя на документацию для strtod:

Linux:

Бесконечность — это либо «INF», либо «INFINITY», независимо от регистра.

OS X:

Если часть строки следует за дополнительным плюсом
или знак минус начинается с «INFINITY» … это
интерпретируется как бесконечность

Я использую stringstream преобразовать string к doubleи (ошибочно) предположил, что strtod использовался за кулисами. Ни clang ++ 3.4, ни g ++ 4.8 не преобразуют «INFINITY» в inf, Только clang ++, кажется, конвертирует «INF» inf,

Я предполагаю слишком много о работе stringstream«s operator>>? Или, может быть, я не могу проверить важное состояние ошибки? Мой тестовый код ниже (g++ -std=c++11 -Wall -Wextra inf.cpp -o inf).

Тестовый код

#include <cmath>
#include <cstdlib>
#include <iomanip>
#include <iostream>
#include <sstream>

void
doTest(
const std::string &str)
{
double val1 = std::strtod(str.c_str(), nullptr);
std::cout << str << " - std::isinf from strtod: " << std::boolalpha <<
std::isinf(val1) << '\n';

std::stringstream sstream(str);
double val2;
sstream >> val2;
std::cout << str << " - std::isinf from stringstream: " <<
std::boolalpha << std::isinf(val2) << '\n';

std::cout << val1 << " vs " << val2 << '\n';

std::cout << std::endl;
}

int
main()
{
doTest("INFINITY");
doTest("+INF");

return (0);
}

Выход

clang ++ 3.4 (OS X 10.9.2):

INFINITY - std::isinf from strtod: true
INFINITY - std::isinf from stringstream: false
inf vs 0

+INF - std::isinf from strtod: true
+INF - std::isinf from stringstream: true
inf vs inf

g ++ 4.8:

INFINITY - std::isinf from strtod: true
INFINITY - std::isinf from stringstream: false
inf vs 0

+INF - std::isinf from strtod: true
+INF - std::isinf from stringstream: false
inf vs 0

3

Решение

Я прошел через стандарт, и оператор потока должен быть определен в терминах функции C strtod, но только после фильтрации чего-либо, что может стать не-числом или бесконечностью на этапе 2.

После следа документа:

27.7.2.2.2 Арифметические экстракторы

Как и в случае со вставками, эти экстракторы зависят от num_get локали<> (22.4.2.1) объект
выполнить синтаксический анализ данных входного потока. Эти экстракторы ведут себя как отформатированные функции ввода (как
описано в 27.7.2.2.1). После того, как часовой объект построен, преобразование происходит так, как если бы оно выполнялось
следующий фрагмент кода:

typedef num_get< charT,istreambuf_iterator<charT,traits> > numget;
iostate err = iostate::goodbit;
use_facet< numget >(loc).get(*this, 0, *this, err, val);
setstate(err);

22.4.2.1.2 виртуальные функции num_get

Этап 2: Если in==end затем этап 2 заканчивается. В противном случае charT берется из in и локальных переменных.
инициализируются как будто

char_type ct = *in;
char c = src[find(atoms, atoms + sizeof(src) - 1, ct) - atoms];
if (ct == use_facet<numpunct<charT> >(loc).decimal_point())
c = ’.’;
bool discard = ct == use_facet<numpunct<charT> >(loc).thousands_sep()
&& use_facet<numpunct<charT> >(loc).grouping().length() != 0

где значения src и атомов определены как если бы:

static const char src[] = "0123456789abcdefxABCDEFX+-";
char_type atoms[sizeof(src)];
use_facet<ctype<charT> >(loc).widen(src, src + sizeof(src), atoms);

для этого значения loc.

2

Другие решения


По вопросам рекламы [email protected]