我们如何检查输入字符串是否是有效的双精度?

时间:2013-10-29 23:23:24

标签: c

如果我从stdin读取 double 类型的数字,我如何检查正在读取的数字是否实际上有效(这些数字实际上是双数)?

4 个答案:

答案 0 :(得分:3)

您可以使用strtod。根据手册页:

,检查结果是否为零,然后检查endptr == nptr
  

如果没有执行转换,则返回零,并且nptr的值存储在endptr引用的位置。

这样的事情:

char input[50];
char * end;
double result = 0;

fgets(input, sizeof input, stdin);

errno = 0;

result = strtod(input, &end);

if(result == 0 && (errno != 0 || end == input)){
    fprintf(stderr, "Error: input is not a valid double\n");
    exit(EXIT_FAILURE);
}

编辑 the standard与手册页之间似乎存在一些差异。当没有执行转换时,手册页说endptr == nptr,而标准似乎暗示这不一定是这种情况。更糟糕的是它表示如果没有转换errno 可能设置为EINVAL。编辑了示例代码以检查errno

或者,可以使用sscanf(首选scanf),与fgets结合使用:

/* just fgetsed input */
if(sscanf(input, "%lf", &result) != 1){
    fprintf(stderr, "Error: input is not a valid double\n");
    exit(EXIT_FAILURE);
}

此外,如果失败,请不要忘记检查fgets的{​​{1}}的返回值!

答案 1 :(得分:1)

简单的strtodsscanf都不足以将1,51blah等案例与所需的1.0区分开来 - 所有这些都会导致{{ 1}}。原因是

  

1.0strtod()strtof()函数将nptr指向的字符串的初始部分转换为double,float和long double表示分别。

要确保整个字符串是有效的双字符,请使用strtold(),如下所示:

strtod

如果无法表示值#include <stdlib.h> #include <errno.h> #include <stdio.h> ... char *endptr; errno = 0; double result = strtod(input, &endptr); if (errno != 0 || *endptr != '\0') { fprintf("the value could not be represented as a double exactly\n"); } ,则会设置errno。此外,ERANGE将指向未转换的第一个字符。如果区域设置尚未设置,则在解析end1,5时,1blah将指向第二个字符。 Iff 整个字符串已成功解析为双常量,endptr将指向终止'\ 0'

请注意,在调用函数之前必须将*endptr设置为零,否则它将保留先前失败函数调用的值。

答案 2 :(得分:0)

  

我们如何检查输入字符串是否为有效的双精度数?


开头 strtod()的{​​{1}},
doublestrtof() float strtold()的{​​{1}}。

long double
  

double strtod(const char * restrict nptr, char ** restrict endptr); ,...函数将strtod指向的字符串的初始部分转换为nptr ....

     

指向最终字符串的指针存储在double指向的对象中,前提是endptr不是空指针。

     

C11dr§7.22.1.32&amp; 5

简化代码以便有效地检查。不抱怨过度/下溢或额外的文本。

endptr

使用// Return true on valid bool valid_string_to_double(const char *s) { char *end; strtod(s, &end); return s != end; } 的挑战包括:strto*()算术溢出和可能 underflow。溢出时的返回值仅在默认舍入模式中指定。该值为errno == RANGE,可能是无穷大或大数。下溢的返回值是实现定义的。已知{C}规范未指定的条件下,HUGE_VAL被设置为其他非零值。允许使用前导空白区域,不考虑尾随空白区域。

寻找1)转换,2)额外空间,3)上/下溢的样本函数。它不仅返回有效的指示,还会在之后解决转换的值和errno的状态。

errno
  

如果结果下溢(7.12.1),则函数返回一个值,该值的大小不大于返回类型中的最小归一化正数; // Return 0 on success // Return non-0 on error, adjust these values as needed - maybe as an `enum`? int convert_string_to_double(double *y, const char *s) { char *end; errno = 0; *y = strtod(s, &end); if (s == end) { return 1; // Failed: No conversion, *y will be 0 } // This may/may not constitute an error - adjust per coding goals // Too great or too small (yet not exactly 0.0) if (errno == ERANGE) { if (fabs(*y) > 1.0) { return 2; // Overflow } // In the case of too small, errno _may_ be set. See §7.22.1.3 10. // For high consistency, return 0.0 and/or clear errno and/or return success. // *y = 0.0; errno = 0; } // What to do if the remainder of the string is not \0? // Since leading whitespace is allowed, // let code be generous and tolerate trailing whitespace too. while (isspace((unsigned char) *end)) { end++; } if (*end) { return 3; // Failed: Extra non-white-space junk at the end. } return 0; // success } 获取值errno是否是实现定义的。 C11dr§7.22.1.310

在此功能完成后,考虑因素包括ERANGE的值。 {c}仅针对errno的C spec errno == ERANGE种,但由于其他原因(包括“无转换”),已知各种实现将strtod()设置为其他值。代码可以清除errno,除非errno具有高一致性。

答案 3 :(得分:-1)

您可以使用标准atof功能。失败时返回0 - 您可以预先测试字符串是否为0。

http://www.cplusplus.com/reference/cstdlib/atof/