确定字符串是整数还是 ANSI C 中的浮点数

Determine if a string is an integer or a float in ANSI C

提问人:Christopher Dolan 提问时间:9/17/2008 最后编辑:James McNellisChristopher Dolan 更新时间:2/15/2014 访问量:27039

问:

仅使用 ANSI C,确定 C 样式字符串是整数还是实数(即浮点数/双精度数)的最佳方法是什么?

c 浮点

评论


答:

2赞 nutbar 9/17/2008 #1

我想您可以单步执行字符串并检查其中是否有任何字符。不过,这只是我脑海中浮现的第一件事,所以我相信还有其他(更好的)方法可以更加确定。.

评论

0赞 Arafangion 6/20/2010
还有 ',' 字符。不要忘记本地化。
3赞 itsmatt 9/17/2008 #2

如果不能,Atoi 和 ATOF 将转换或返回 0。

评论

0赞 itsmatt 9/17/2008
当然 - 你的答案肯定涵盖了这种情况。
0赞 Patrick_O 9/17/2008
我更改了我的显示名称以阻止这种混淆!
1赞 Vincent Robert 9/17/2008 #3

这真的取决于你为什么首先问。

如果你只想解析一个数字,不知道它是浮点数还是整数,那么只需解析一个浮点数,它也会正确解析一个整数。

如果你真的想知道类型,也许是为了分类,那么你真的应该考虑按照你认为最相关的顺序测试类型。就像尝试解析一个整数,如果不能,则尝试解析浮点数。(反之亦然,只会产生更多的浮子......

34赞 Patrick_O 9/17/2008 #4

不要使用 atoi 和 atof,因为这些函数在失败时返回 0。上次我检查时,0 是有效的整数和浮点数,因此无法确定类型。

使用 strto{l,ul,ull,ll,d} 函数,因为这些函数在失败时设置 errno,并报告转换后的数据结束位置。

strtoul: http://www.opengroup.org/onlinepubs/007908799/xsh/strtoul.html

此示例假定字符串包含要转换的单个值。

#include <errno.h>

char* to_convert = "some string";
char* p = to_convert;
errno = 0;
unsigned long val = strtoul(to_convert, &p, 10);
if (errno != 0)
    // conversion failed (EINVAL, ERANGE)
if (to_convert == p)
    // conversion failed (no characters consumed)
if (*p != 0)
    // conversion failed (trailing data)

感谢 Jonathan Leffler 指出我忘了先将 errno 设置为 0。

评论

0赞 vodkhang 4/28/2010
对不起,我知道这已经很老了,但是在这一行中,我们没有任何错误?无符号长值 Val = strtoul(to_convert, &p, 10);正确的是无符号的 long errno = strtoul(to_convert, &p, 10);
0赞 Ben Gartner 6/20/2010
@vodkhang 这是有效的代码,但您可能需要使用 #include < errno.h>,具体取决于您的编译器。errno 本质上是一个全局变量,可以使用错误代码进行设置。它可以作为宏或“可修改的左值”实现。
0赞 R.. GitHub STOP HELPING ICE 12/24/2010
errno 是一个扩展为可修改左值的宏。通常,它会扩展到或类似。(*__errno_location())
0赞 Dave Appleton 7/1/2013
为了避免任何人的头痛,您可能需要添加 #include < errno.h> 才能使其正常工作。
1赞 Russ Ryan 9/17/2008 #5

Atoi 和 ATOF 将转换数字,即使有尾随的非数字字符。但是,如果您使用 strtol 和 strtod,它不仅会跳过前导空格和可选符号,还会留下指向数字中不的第一个字符的指针。然后,您可以检查其余部分是否为空格。

9赞 Patrick 9/17/2008 #6

使用 sscanf,您可以确定字符串是浮点数还是 int 或其他值,而不必像 atoi 和 atof 解决方案那样出现特殊情况 0。

下面是一些示例代码:

int i;
float f;
if(sscanf(str, "%d", &i) != 0) //It's an int.
  ...
if(sscanf(str "%f", &f) != 0)  //It's a float.
  ...

评论

1赞 Patrick_O 9/17/2008
我很确定您需要针对 str 的大小测试 sscanf 的返回值,以确保整个字符串已转换,否则如果“%d”被传递到“1.374”,它不会失败,它将返回 1。
0赞 Patrick 9/17/2008
真。这也可以通过首先测试 %f 来解决,但这会导致“1.”出现问题。就个人而言,我喜欢您的解决方案中最好的解决方案。
0赞 Jens 9/3/2013
@Patrick_O 根据字符串长度检查 的返回是行不通的,因为它返回的是成功转换的项目数,而不是用于转换的字符数。但格式可能在这里有所帮助。sscanf%n
2赞 Steve Jessop 9/17/2008 #7

使用 strtol/strtoll(不是 atoi)检查整数。 使用 strtof/strtod(不是 atof)检查双精度。

Atoi 和 ATOF 转换字符串的初始部分,但不会告诉您它们是否使用了所有字符串。strtol/strtod 告诉您字符转换后是否有额外的垃圾。

因此,在这两种情况下,请记住传入一个非 null 的 TAIL 参数,并检查它是否指向字符串的末尾(即 **TAIL == 0)。还要检查下溢和溢出的返回值(有关详细信息,请参见手册页或 ANSI 标准)。

另请注意,strod/strtol 会跳过初始空格,因此如果要将带有初始空格的字符串视为格式不正确,则还需要检查第一个字符。

3赞 Jonathan Leffler 9/17/2008 #8

我同意Patrick_O,strto{l,ul,ull,ll,d} 函数是最好的方法。不过,有几点值得关注。

  1. 在调用函数之前将 errno 设置为零;没有任何功能可以为您做到这一点。
  2. 链接到的 Open Group 页面(在注意到 Patrick 也链接到它之前,我去了该页面)指出 errno 可能没有设置。如果该值超出范围,则将其设置为 ERANGE;如果参数无效,则可以将其设置为(但同样,可能不会设置为)EINVAL。

根据手头的工作,我有时会安排跳过返回的转换指针末尾的尾随空格,如果最后一个字符不是终止 null '\0',则抱怨(拒绝)。或者我可以草率地让垃圾出现在最后,或者我可以接受可选的乘数,如“K”、“M”、“G”、“T”表示千字节、兆字节、千兆字节、太字节......或基于上下文的任何其他要求。

0赞 Katie 2/15/2014 #9

好吧,如果您不想使用像 strtoul 这样的新函数,您可以添加另一个 strcmp 语句来查看字符串是否为 0。

if(atof(token) != NULL || strcmp(token, "0") == 0)

评论

0赞 Michael 2/25/2016
这认为“0.0”(及其其他变体)不是数字。