这段代码是基于dasblinkenlight的回答进行了修改。我想它可以作为思考的食粮。它给出的一些答案可能不是你想要的。
#include <stdio.h>
#include <string.h>
static void test_float(const char *str)
{
int len;
float dummy = 0.0;
if (sscanf(str, "%f %n", &dummy, &len) == 1 && len == (int)strlen(str))
printf("[%s] is valid (%.7g)\n", str, dummy);
else
printf("[%s] is not valid (%.7g)\n", str, dummy);
}
int main(void)
{
test_float("5.23.fkdj");
test_float(" 255. ");
test_float("255.123456");
test_float("255.12E456");
test_float(" .255 ");
test_float(" Inf ");
test_float(" Infinity ");
test_float(" Nan ");
test_float(" 255 ");
test_float(" 0x1.23P-24 ");
test_float(" 0x1.23 ");
test_float(" 0x123 ");
test_float("abc");
test_float("");
test_float(" ");
return 0;
}
在运行macOS Sierra 10.12.6的Mac上,使用GCC 7.1.0作为编译器进行测试,我得到了以下输出:
[5.23.fkdj] is not valid (5.23)
[ 255. ] is valid (255)
[255.123456] is valid (255.1235)
[255.12E456] is valid (inf)
[ .255 ] is valid (0.255)
[ Inf ] is valid (inf)
[ Infinity ] is valid (inf)
[ Nan ] is valid (nan)
[ 255 ] is valid (255)
[ 0x1.23P-24 ] is valid (6.775372e-08)
[ 0x1.23 ] is valid (1.136719)
[ 0x123 ] is valid (291)
[abc] is not valid (0)
[] is not valid (0)
[ ] is not valid (0)
十六进制数可能特别棘手。各种形式的无穷大和非数字也可能有问题。而带指数的一个例子(
255.12E456
)会溢出
float
并生成无穷大——这真的可以吗?
这里提出的大多数问题都是定义性的——也就是说,如何定义您想要接受什么。但请注意,
strtod()
将接受所有有效字符串(以及一些无效的字符串,但其他测试将揭示这些问题)。
显然,测试代码可以修改为使用包含字符串和所需结果的结构体数组,并可用于遍历所示的测试用例和任何其他额外的测试用例。
strlen()
结果的强制转换避免了编译警告(因为我使用
-Werror
编译),即
comparison between signed and unsigned integer expressions [-Werror=sign-compare]
。如果您的字符串足够长,以至于
strlen()
的结果会使有符号的
int
溢出,则假装它们是有效值时还有其他问题。另一方面,您可能想尝试小数点后500位——那是有效的。
此代码记录了对dasblinkenlight答案的评论:
5.0 米
这样的情况。 - Daniel H