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

输出:5YES

atof 是否也适用于非空终止字符数组?如果是这样,它怎么知道在哪里停下来?

4

8 回答 8

5

atof 是否也适用于非空终止字符数组?

不,它没有std::atof在输入中需要一个以 null 结尾的字符串。未能满足此先决条件是Undefined Behavior

未定义的行为意味着任何事情都可能发生,包括程序似乎运行良好。这里发生的情况是,您偶然在数组的最后一个元素之后在内存中有一个字节,该字节不能被解释为浮点数表示的一部分,这就是您的实现std::atof停止的原因。但这是不能依赖的。

你应该这样修复你的程序:

char c[] = {'0', '.', '5', '\0'};
//                         ^^^^
于 2013-03-22T12:21:12.670 回答
2

不,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;

上面的prints 5.678指出了已经读取到数组末尾的事实。

于 2013-03-22T12:21:38.240 回答
1

不... atof() 需要一个以空字符结尾的字符串。

如果您需要转换的字符串不是以 null 结尾的,则可以尝试根据每个 char 的值是有效数字将其复制到目标缓冲区中。有什么影响...

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 );
于 2013-03-22T12:26:21.067 回答
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/

于 2013-03-22T12:47:18.627 回答
0

atof()MSDN 上对函数的描述(可能适用于其他编译器):

该函数在它无法识别为数字的一部分的第一个字符处停止读取输入字符串。此字符可能是终止字符串的空字符('\0' 或 L'\0')。

于 2013-03-22T12:21:35.253 回答
0

它必须以 0 结尾,或者文本必须包含不属于该数字的字符。

于 2013-03-22T12:22:36.133 回答
0

从 C++11 开始,我们有std::stof. 通过替换atofstd::stof,它会更容易处理。

如果您总是传递已知大小的 char 数组,我制作了一个方便的包装器。

现场演示

#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;
}

输出:The answer is 0.42.

于 2022-03-01T09:57:42.080 回答
0

atof 是否也适用于非空终止字符数组?

不,此函数需要一个指向空终止字符串的指针。不这样做,例如通过将指针传递给非空终止字符串(或非空终止字符数组)是未定义的行为

未定义的行为意味着任何事情1都可能发生,包括但不限于给出预期输出的程序。但永远不要依赖(或基于)具有未定义行为的程序的输出。

所以你看到的输出(也许看到)是未定义行为的结果。正如我所说,不要依赖具有 UB 的程序的输出。该程序可能会崩溃。

因此,使程序正确的第一步是删除 UB。只有这样,您才能开始推理程序的输出。


1有关未定义行为的更技术上准确的定义,请参见此处提到:对程序的行为没有限制

于 2022-03-01T10:44:14.457 回答