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? Если так, как он знает, где остановиться?
Работает ли atof с массивами символов, не оканчивающимися на NULL?
Нет не. std::atof
требует ввода строки с нулевым символом в конце. Невыполнение этого условия является Неопределенное поведение.
Неопределенное поведение означает, что что-нибудь может произойти, в том числе программа, похоже, работает нормально. Здесь происходит то, что случайно у вас есть байт в памяти сразу после последнего элемента вашего массива, который не может быть интерпретирован как часть представления числа с плавающей запятой, поэтому ваша реализация std::atof
останавливается. Но на это нельзя полагаться.
Вы должны исправить свою программу следующим образом:
char c[] = {'0', '.', '5', '\0'};
// ^^^^
Нет, 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
, указывая на то, что было выполнено чтение за концом массива.
Нет … 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 );
Из описания atof()
Функция на MSDN (вероятно, относится к другим компиляторам):
Функция прекращает чтение входной строки с первого символа, который она не может распознать как часть числа. Этот символ может быть нулевым символом (‘\ 0’ или L ‘\ 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/