3
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";
    }
}

OUTPUT: 5YES

Does atof work with non-null terminated character arrays too? If so, how does it know where to stop?

Richard Chambers
  • 16,643
  • 4
  • 81
  • 106
tez
  • 4,990
  • 12
  • 47
  • 67

8 Answers8

5

Does atof work with non-null terminated character arrays too?

No, it doesn't. std::atof requires a null-terminated string in input. Failing to satisfy this precondition is Undefined Behavior.

Undefined Behavior means that anything could happen, including the program seeming to work fine. What is happening here is that by chance you have a byte in memory right after the last element of your array which cannot be interpreted as part of the representation of a floating-point number, which is why your implementation of std::atof stops. But that's something that cannot be relied upon.

You should fix your program this way:

char c[] = {'0', '.', '5', '\0'};
//                         ^^^^
Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
  • 1
    There isn't a `'\0'` behind the array, actually. Notice the test for that in the code (that also invokes UB). `atof` stops on any character that can't be interpreted as a part of a floating point number representation. – jrok Mar 22 '13 at 12:29
  • 2
    @jrok: However there is no *requirement* that it stop on encountering a character that's not part of the floating point number. That's just a quality of implementation issue. A crappy `atof` interpretation is certainly permitted to call `strlen` on its input even though this could make it 1000 times slower in some cases. – R.. GitHub STOP HELPING ICE Mar 22 '13 at 12:35
2

No, atof does not work with non-null terminated arrays: it stops whenever it discovers zero after the end of the array that you pass in. Passing an array without termination is undefined behavior, because it leads the function to read past the end of the array. In your example, the function has likely accessed bytes that you have allocated to f (although there is no certainty there, because f does not need to follow c[] in memory).

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

The above prints 5.678, pointing out the fact that a read past the end of the array has been made.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

No... atof() requires a null terminated string.

If you have a string you need to convert that is not null terminated, you could try copying it into a target buffer based on the value of each char being a valid digit. Something to the effect of...

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 );
K Scott Piel
  • 4,320
  • 14
  • 19
  • 1
    [_note that C strings do not imply the use of ASCII..._](http://en.wikipedia.org/wiki/Null-terminated_string) – masoud Mar 22 '13 at 12:29
  • 1
    Indeed, ASCIIZ is not a proper term. In the C language, the term is just "string", which is defined to include the requirement of null termination. Otherwise you might clarify it as as "C string" (i.e. a string using C's definition of the term) or a "null-terminated string". – R.. GitHub STOP HELPING ICE Mar 22 '13 at 12:34
0

From the description of the atof() function on MSDN (probably applies to other compilers) :

The function stops reading the input string at the first character that it cannot recognize as part of a number. This character may be the null character ('\0' or L'\0') terminating the string.

Roger Rowland
  • 25,885
  • 11
  • 72
  • 113
0

It must either be 0 terminated or the text must contain characters that do not belong to the number.

Bryan Olivier
  • 5,207
  • 2
  • 16
  • 18
0

std::string already terminate a string with NULL!

So why not

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

You can also do it with the stringstream or 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/

Saqlain
  • 17,490
  • 4
  • 27
  • 33
0

Since C++11, we have std::stof. By replacing atof with std::stof, it would be easier to handle.

I made a handy wrapper if you always pass a known size of char array.

Live Demo

#include <fmt/core.h>
#include <type_traits>
#include <iostream>

// SFINAE fallback  
template<typename T, typename =
    std::enable_if< std::is_pointer<T>::value >
>
float charArrayToFloat(const T arr){  // Fall back for user friendly compiler errors
    static_assert(false == std::is_pointer<T>::value, "`charArrayToFloat()` dosen't allow conversion from pointer!");
    return -1;
}

// Valid for both null or non-null-terminated char array
template<size_t sz>
float charArrayToFloat(const char(&arr)[sz]){
    // It doesn't matter whether it's null terminated or not
    std::string str(arr, sz);
    return std::stof(str);
}


int main() {
    char number[4] = {'0','.','4','2'};
    float ret = charArrayToFloat(number);
    fmt::print("The answer is {}. ", ret);
    return 0;
}

Output: The answer is 0.42.

Louis Go
  • 2,213
  • 2
  • 16
  • 29
0

Does atof work with non-null terminated character arrays too?

No, this function expects a pointer to a null terminated string. Failing to do so, say for example by passing a pointer to a non-null terminated string(or a non-null terminated character array) is undefined behavior.

Undefined behavior means anything1 can happen including but not limited to the program giving your expected output. But never rely(or make conclusions based) on the output of a program that has undefined behavior.

So the output that you're seeing(maybe seeing) is a result of undefined behavior. And as i said don't rely on the output of a program that has UB. The program may just crash.

So the first step to make the program correct would be to remove UB. Then and only then you can start reasoning about the output of the program.


1For a more technically accurate definition of undefined behavior see this where it is mentioned that: there are no restrictions on the behavior of the program.

Jason
  • 36,170
  • 5
  • 26
  • 60