如何检查字符串是否可以转换为浮点数?

时间:2009-12-20 10:51:42

标签: c floating-point type-conversion

首先,我的上下文是需要将浮点文字(字符串)转换为float / double值的编译器编写器。在过去的15年里,我没有做任何浮点编程,所以我很确定这是一个完全愚蠢的新手问题。

double res; 
errno=0; 
*res = strtod((const char*)literal,NULL); 
if (errno==ERANGE) throw_a_literal_out_of_range_exception();
return res;

但是c运行时库中没有“strtof”函数?

编辑:澄清。我已经知道字符串'literal'是C浮点的有效模式。它已经通过了正则表达式测试。我只想检查是否存在范围/精度问题。

原因在于用户可以编写的Eiffel源代码

a := {REAL_32} 3.1415
b := {REAL_32} 3.0E200

将写入的浮点数explit转换为32位浮点数。我认为在第二种情况下,编译器应检测到该值超出范围并引发错误或至少发出警告。

7 个答案:

答案 0 :(得分:9)

在C89中你可以使用sscanf。

例如:

float myfloat;

if(sscanf(str, "%f", &myfloat) != 1)
    /* String could not be converted */
else
    /* String was converted, myfloat is usable */

答案 1 :(得分:6)

@Nicholas Goy: 我不认为sscanf(str, "%f, &float) == 1(或!= 1)确实做了所需的事情。

如果str中有其他字符(例如“1.1foo”),它将无错误地解析,这可能是不合需要的。这可以通过以下方式纠正:

char dummy;
if (sscanf(str, "%f%c", &float, &dummy) != 1) {
   /* Parse error. */
} else {
   /* Parsed cleanly. */
}

代替。但是,带有sscanf的{​​{1}}可能会在内部使用%f并且无论如何都会转换为浮动。 C标准中的语言表示:

  

a,e,f,g匹配可选的带符号浮点数,无穷大或NaN,其中   格式与strtod的主题序列的预期相同   功能。相应的参数应该是浮动的指针。

哪种意味着这一点,对我来说似乎是对的(FreeBSD上的gcc 4.2.1)。使用上面的strtod代码,“1.79e308”成功解析但值为+ inf,“5e-300”值为0.0,这些结果与您从{{1}获得的结果相同}和sscanf

反正。总而言之,我怀疑为什么OP想要使用float而不是double。

答案 2 :(得分:5)

我打算说,只需使用你已经拥有的代码,但是将strod()的结果赋给float而不是double。但是你的代码在几个方面都是错误的。

首先,除非出现错误,否则无法测试errno。其次,除了范围错误之外,strtod()不会设置errno。如果您传递一个无效的数字,例如“XYZ”,则不会设置它。

更正确地使用strtod是:

char *p;
double d = strtod( "123.4xyz", & p );
if ( * p != 0 ) {
   // not a number - in this case will point at 'x'
}

使用strtod()来读取浮点数,你可能会失去一些精度,但这是你使用浮点数所付出的代价 - 一般来说,除非你有充分的理由不这样做,你应该总是喜欢使用double来浮。

答案 3 :(得分:4)

C89中不存在

strtof,但它在C99中存在。

答案 4 :(得分:4)

我建议先转换为双倍,然后转换为浮动。如果相对差异(f-d)/f大于浮点精度(粗略地,1e-7)那么数字可以比浮动中安全存储的数字多。

答案 5 :(得分:2)

在MSVC上,您可以使用stdlib.h中定义的_atoflt()

答案 6 :(得分:2)

由于您的价值在double,因此您只需检查它是否超出float的范围:

#include <stdlib.h>
#include <stdio.h>
#include <float.h>

int main(int argc, char *argv[])
{
    double d = FLT_MAX;
    if (argc > 1) {
        d = strtod(argv[1], NULL);
    }
    if ((d > 0 && (d > FLT_MAX || d < FLT_MIN))
                || (d < 0 && (d < -FLT_MAX || d > -FLT_MIN)))
        printf("Invalid float: %g\n", d);
    else
        printf("Valid: %g\n", d);

    return EXIT_SUCCESS;
}

运行程序:

$ ./a.out
Valid: 3.40282e+38
$ ./a.out 3.5e38
Invalid float: 3.5e+38
$ ./a.out -1e40
Invalid float: -1e+40

您可能需要也可能不需要为正确的strtod()返回添加测试,具体取决于double类型是否有可能出现溢出。