atof и непустой массив символов

using namespace std;
int main(int argc, char *argv[]) {
char c[] = {'0','.','5'};
//char c[] = "0.5";
float f = atof(c);
cout << f*10;
if(c[3] != '\0')
{
cout << "YES";
}
}

ВЫХОД: 5YES

Работает ли atof с массивами символов, не оканчивающимися на NULL? Если так, как он знает, где остановиться?

3

Решение

Работает ли atof с массивами символов, не оканчивающимися на NULL?

Нет не. std::atof требует ввода строки с нулевым символом в конце. Невыполнение этого условия является Неопределенное поведение.

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

Вы должны исправить свою программу следующим образом:

char c[] = {'0', '.', '5', '\0'};
//                         ^^^^
5

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

Нет, atof не работает с массивами с ненулевым завершением: он останавливается всякий раз, когда обнаруживает ноль после конца массива, который вы передаете. Передача массива без завершения является неопределенным поведением, потому что это заставляет функцию читать за концом массива. В вашем примере функция, вероятно, получила доступ к байтам, которые вы выделили f (хотя там нет уверенности, потому что f не нужно следовать c[] в памяти).

char c[] = {'0','.','5'};
char d[] = {'6','7','8'};
float f = atof(c); // << Undefined behavior!!!
float g = atof(d); // << Undefined behavior!!!
cout << f*10;

Выше печать 5.678, указывая на то, что было выполнено чтение за концом массива.

2

Нет … atof () требует строки с нулевым символом в конце.

Если у вас есть строка, которую нужно преобразовать, которая не заканчивается нулем, вы можете попробовать скопировать ее в целевой буфер на основе значения каждого символа, являющегося действительной цифрой. Что-то с эффектом …

char buff[64] = { 0 };

for( int i = 0; i < sizeof( buff )-1; i++ )
{
char input = input_string[i];

if( isdigit( input ) || input == '-' || input == '.' )
buff[i] = input;
else
break;
}

double result = atof( buff );
1

Из описания atof() Функция на MSDN (вероятно, относится к другим компиляторам):

Функция прекращает чтение входной строки с первого символа, который она не может распознать как часть числа. Этот символ может быть нулевым символом (‘\ 0’ или L ‘\ 0’), оканчивающим строку.

0

Он должен быть либо завершен 0, либо текст должен содержать символы, которые не принадлежат к числу.

0

std :: string уже завершает строку с NULL!

Так почему не

std::string number = "7.6";
double temp = ::atof(number.c_str());

Вы также можете сделать это с помощью stringstream или boost :: lexical_cast

http://www.boost.org/doc/libs/1_53_0/doc/html/boost_lexical_cast.html
http://www.cplusplus.com/reference/sstream/stringstream/

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector