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

时间:2008-09-16 23:55:42

标签: c floating-point numbers

仅使用ANSI C,以公平的确定性确定C样式字符串是整数还是实数(即float / double)的最佳方法是什么?

9 个答案:

答案 0 :(得分:34)

不要使用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。

答案 1 :(得分:9)

使用sscanf,您可以确定字符串是浮点数还是整数或其他没有特殊情况0的情况,就像atoi和atof解决方案一样。

以下是一些示例代码:

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

答案 2 :(得分:3)

atoi和atof如果不能转换或返回0。

答案 3 :(得分:3)

我同意Patrick_O的观点,即{l,ul,ull,ll,d}功能是最佳选择。但是有几点值得关注。

  1. 在调用函数之前将errno设置为零;没有任何功能可以帮助你。
  2. 链接到的Open Group页面(在注意到Patrick已经链接到它之前我去过)指出可能没有设置errno。如果值超出范围,则设置为ERANGE;如果参数无效,可以设置(但同样地,可以 设置)到EINVAL。
  3. 根据手头的工作,我有时会安排从返回的转换指针末尾跳过尾随空白区域,然后如果最后一个字符不是终止空值'\ 0'则抱怨(拒绝)。或者我可以马虎,让垃圾出现在最后,或者我可以接受可选的乘数,如'K','M','G','T'为千字节,兆字节,千兆字节,太字节,......或任何其他基于背景的要求。

答案 4 :(得分:2)

我想您可以单步检查字符串并检查其中是否有.个字符。这只是我头脑中的第一件事,所以我确信还有其他(更好)的方法可以更加确定。

答案 5 :(得分:2)

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

atoi和atof转换字符串的初始部分,但不要告诉你他们是否使用了所有的字符串。 strtol / strtod告诉你转换后的字符是否有额外的垃圾。

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

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

答案 6 :(得分:1)

这实际上取决于你首先要问的原因。

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

如果您真的想知道类型,也许是为了分类,那么您应该考虑按照您认为最相关的顺序测试类型。就像尝试解析整数一样,如果不能,则尝试解析一个浮点数。 (另一种方式只会产生更多浮动......)

答案 7 :(得分:1)

即使有非数字字符的尾随,

atoi和atof也会转换该数字。但是,如果您使用strtol和strtod,它不仅会跳过前导空格和可选符号,而且还会指向不在数字中的第一个字符。然后你可以检查其余的是空格。

答案 8 :(得分:0)

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

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