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

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

你可以使用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); } 

编辑 标准和手册页之间似乎有点差异。 手册页说没有执行转换时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的返回值为NULL ,以防它失败!

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

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

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

 #include  #include  #include  ... 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"); } 

如果无法表示值,则设置errnoERANGE )。 此外, end将指向未转换的第一个字符。 如果尚未设置语言环境,则在解析1,51blahendptr将指向第二个字符。 Iff整个字符串被成功解析为双常量, *endptr将指向终止‘\ 0’

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

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

从…开始
strtod()double
strtof()用于float
strtold()long double

 double strtod(const char * restrict nptr, char ** restrict endptr); 

strtod ,…函数将nptr的字符串的初始部分转换为double ….

如果endptr不是空指针,则指向最终字符串的指针存储在endptr指向的对象中。

C11dr§7.22.1.32&5

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

 // Return true on valid bool valid_string_to_double(const char *s) { char *end; strtod(s, &end); return s != end; } 

使用strto*()挑战包括: errno == RANGE算术溢出和下溢 。 溢出时的返回值仅在默认舍入模式中指定。 该值为HUGE_VAL ,可能是无穷大或大数。 下溢的返回值是实现定义的。 已知errno在C规范未指定的条件下设置为其他非零值。 允许使用前导空白区域,不考虑尾随空白区域。


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

 // 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 } 

如果结果下溢(7.12.1),则函数返回一个值,该值的大小不大于返回类型中的最小归一化正数; 是否errno获取值ERANGE是实现定义的。 C11dr§7.22.1.310


考虑因素包括完成此function后的errno值。 对于strtod() ,C规范只有物种errno == ERANGE ,但是已知各种实现由于其他原因将errno为其他值,包括“无转换”。 代码可以清除errno除非ERANGE具有高一致性。

您可以使用标准的atoffunction。 失败时返回0 – 您可以事先测试字符串是否为0。

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