std — C ++: atof () ведет себя неправильно

Я использую библиотеку для загрузки файлов Wavefront .obj в свое приложение OpenGL (tinyobjloader). Я заметил, что при загрузке объектов возникает ошибка. Когда я загружаю объект с координатой, например. 0.9999999, это установлено в 0. Отладкой я обнаружил, что следующий метод производит это поведение:

static inline float parseFloat(const char*& token)
{
token += strspn(token, " \t");
float f = (float)atof(token);
token += strcspn(token, " \t\r");
return f;
}

Так что atof () возвращает int, а не float. Я читал, что некоторые компиляторы не выдают предупреждение при использовании atof () без включения «stdlib.h», и в результате atof () возвращает целое число.

Любопытно, что даже если я включу «stdlib.h», ошибка останется. Я не могу понять, что вызывает такое поведение.

Любая идея?

0

Решение

Стандарт говорит atof:

За исключением поведения при ошибке, это эквивалентно
strtod (НПТР (символ **) NULL)

так что ваш возврат ‘0’ не имеет ничего общего с тем, что float не может представлять его или что-то подобное.

Если бы вы использовали вместо этого strtod (что, вероятно, следует делать, когда поток строк не является опцией, просто чтобы иметь возможность сообщать об ошибках), то вы, вероятно, заметите, что он прекращает синтаксический анализ в .,

Это сильный признак того, что вы используете локаль, которая ожидает , вместо . в качестве десятичного разделителя. В зависимости от того, как ваше приложение работает с локалями, вы можете запустить его с правильно установленной переменной среды (например, LC_NUMERIC=C) или сделать setlocale(LC_NUMERIC,"C"); себя перед любым разбором.

В любом случае вы должны проанализировать, кто в вашем приложении использует зависящие от локали вещи и для чего, чтобы не столкнуться с ними. Другой возможный путь — везде требовать ввода, зависящего от локали, поэтому каждый должен дать вам цифры с , в качестве десятичного разделителя.

2

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

Вы можете увидеть документацию atof Вот . Некоторые числа с плавающей запятой не могут быть представлены в 32 битах, и, следовательно, вы получаете ошибку, и возвращаемое значение равно нулю.

//Try these
float f = 0.9999999 ;
cout << atof("0.9999999") << " " << f << endl;//output is 1 1

То, что вы видите, — это правильное поведение.
Вы можете попробовать strtod()

0

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