如何将字符串转换为浮点数?

63
#include<stdio.h>
#include<string.h>

int main() 
{
    char s[100] ="4.0800" ; 

    printf("float value : %4.8f\n" ,(float) atoll(s)); 
    return 0; 
}
我希望输出结果为4.08000000,但我只得到了4.00000000。有没有办法获取小数点后面的数字?
9个回答

74

1
printf("浮点数数值:%4.8f\n" , atof(s)); # 输出结果:浮点数数值:0.00000000 - abubacker
1
因为建议使用 atof 而被踩,但它会忽略解析错误,应该使用 strtof。你应该知道得更好;-) - zwol
1
@Zack 两年前我甚至不知道这个函数的存在。特别是因为它似乎是C99/C++11的函数。 - Mysticial
2
@Mysticial 哦,对了,所有的短浮点数函数都是C99。但是strtod在C89中,并且与atof具有相同的优点(明确报告解析错误)。 - zwol
1
请注意,atof() 返回 double 类型,尽管它的名称中包含 "float"。相应的函数是 strtod(),而 strtof() 返回 floatstrtold() 返回 long double - Jonathan Leffler

36
很遗憾,没有简单的方法来做到这一点。每种解决方案都有其缺点。
  1. 直接使用 atof() 或者 strtof() 函数:大多数人会建议你这样做,这在大多数情况下是有效的。然而,如果程序设置了区域设置或者使用了设置了区域设置的库(例如显示本地化菜单的图形库),并且用户将其区域设置为小数分隔符不是. 的语言(例如分隔符为,fr_FR 语言),这些函数将停止在 . 处解析,你将仍然得到 4.0

  2. 使用 atof() 或者 strtof(),但更改区域设置;只需在调用 atof() 或类似函数之前调用 setlocale(LC_ALL|~LC_NUMERIC, ""); 就可以了。 setlocale 的问题在于它将对进程全局有效,可能会干扰程序的其他部分。请注意,可以查询当前区域设置,并在完成操作后恢复它。

  3. 编写自己的浮点数解析程序。如果您不需要像指数解析或十六进制浮点数之类的高级功能,则可能很快。

另外,请注意,值 4.08 无法精确表示为浮点数;你将得到的实际值是 4.0799999237060546875


29

为什么不应该使用函数atof()将字符串转换为double?

如果成功,atof()函数会将转换后的浮点数作为双精度值返回。 如果无法进行有效转换,则该函数返回零(0.0)。 如果转换后的值超出了双精度表示范围,它会导致未定义行为

参考资料:http://www.cplusplus.com/reference/cstdlib/atof/

相反地,使用函数strtod()更加可靠。

尝试以下代码:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
    char s[100] = "4.0800";
    printf("Float value : %4.8f\n",strtod(s,NULL));
    return 0;
}

您将获得以下输出:

浮点值:4.08000000


1
太棒了,我试了两个小时用atof()找这个bug,直到看到这个。谢谢! - MasterPJ
1
请注意,strtod函数的结果与所在地区有关。有关详细信息,请参阅Sam Hocevar的答案。 - 4LegsDrivenCat
1
“strtod”不是标记为“c”的问题范围吗?我知道它是C++的,但是我正在寻找ANSI C :c - Ludovic Zenohate Lagouardette
1
@LudovicZenohateLagouardette strtod() 在 C 中被定义并处于作用域内。(C11dr 7.22.1.3 The strtod, strtof, and strtold functions) - chux - Reinstate Monica

5

2
建议使用 sscanf() 并不比现在的方法更好。我建议使用 strtod() 代替。 - Jeff Mercado
1
printf("浮点数值 : %4.8f\n" , atof(s));

输出结果 : 浮点数值 : 0.00000000

- abubacker
请使用atof()函数。但是这个函数已经被弃用了,请参考相关文献。 - chux - Reinstate Monica
1
即便 atof() 并未被弃用,但它是不精确的、危险的,最终对于编写强壮代码来说毫无用处。 atof() 永远不应该被使用。 它没有任何方法返回错误,并且如果输入超出可表示范围,则会引发未定义行为。 因此,安全使用它的唯一方法是通过其他方式完全解析输入并在调用 atof() 之前确保输入有效 - 这样使 atof() 完全没有用处。 - Andrew Henle
1
@AndrewHenle 没有理由认为 atof()strtod() 存在任何精度差异 - 因此,不准确性不是一个问题。 atof() 存在溢出 UB,*scanf(flt, "%f", &f); 也存在这个问题 - 所有这些都当前不符合 "健壮性"。 atof() 的用途有限:例如:确保一个字符串由(-、+、0-9、.)组成,长度小于30,在重写 atof() 方面是微不足道的。 对这样的字符串调用 atof() 具有良好的定义行为。 无论如何,从 C11 开始(我想C17也是),atof() 不会被弃用 - 因此答案是事实错误的,这里使用 sscanf() 没有任何改进。 - chux - Reinstate Monica
1
@chux 我认为在出现错误时返回一个有效值0.0是一种不精确的形式。 而且,鉴于glibc实现,重写atof()非常简单。 确保一个字符串由(-、+、0-9、.)组成,长度不超过30个字符。我的观点是,只有在使用atof()或一些类似于*scanf()家族中的非强大函数(我认为在许多方面它们比atof()更糟糕 - 我故意没有在这里评论scanf()的使用...)时,您才需要这样做。 - Andrew Henle

1

提醒: 在使用atof()函数时,请确保字符串中没有""的字符。 atof("1.123")会返回0.000或类似的结果。

解决方案:

str_val[0] = "0";
str_val[len-1] = "\n"; //len = length of string

1
通过使用sscanf,我们可以将字符串转换为浮点数。
#include<stdio.h>    
#include<string.h>    

int main() 
{
    char str[100] ="4.0800" ;     
    const char s[2] = "-";   
    char *token;
    double x;
   /* get the first token */ 
   token = strtok(str, s);
   sscanf(token,"%f",&x);
    printf( " %f",x );

    return 0; 
}


-2
double x;

char *s;

s = " -2309.12E-15";

x = atof(s);     /* x = -2309.12E-15 */

printf("x = %4.4f\n",x);

-3
Main()  {
    float rmvivek,arni,csc;
    char *c="1234.00";
    csc=atof(c);
    csc+=55;
    printf("the value is %f",csc);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接