确定字符串是ANSI C中的整数还是浮点数
仅使用ANSI C,可以肯定地确定C样式字符串是整数还是实数(即float / double)的最佳方法是什么?
解决方案
回答
我想我们可以逐步检查字符串并检查其中是否包含任何.
字符。但是,这只是我脑海中的第一件事,因此,我敢肯定,还有其他(更好)的方法可以更加确定。
回答
如果不能,atoi和atof将转换或者返回0。
回答
这实际上取决于我们为什么首先要问。
如果我们只想解析一个数字而又不知道它是浮点数还是整数,那么只要解析一个浮点数,它也会正确解析一个整数。
如果我们实际上想知道类型(也许是为了分类),那么我们应该真正考虑按我们认为最相关的顺序测试类型。就像尝试解析一个整数,如果不能,则尝试解析一个浮点数。 (反之则只会产生更多的浮动...)
回答
不要使用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。
回答
即使有尾随的非数字字符,atoi和atof也会转换数字。但是,如果我们使用strtol和strtod,它不仅会跳过前导空格和可选符号,还会为我们提供指向第一个字符(而不是数字)的指针。然后,我们可以检查其余部分是否为空格。
回答
使用sscanf,可以确定字符串是float还是int或者其他类型,而无需特殊情况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. ...
回答
使用strtol / strtoll(不是atoi)检查整数。
使用strtof / strtod(而不是atof)检查双打。
atoi和atof转换字符串的初始部分,但不要告诉我们它们是否使用了所有字符串。 strtol / strtod告诉我们字符转换后是否还有多余的垃圾。
因此,在两种情况下,请记住都传递一个非空的TAIL参数,并检查它是否指向字符串的末尾(即** TAIL == 0)。还要检查下溢和上溢的返回值(有关详细信息,请参见手册页或者ANSI标准)。
还要注意,strod / strtol会跳过初始空格,因此,如果要将初始空格的字符串视为格式错误,还需要检查第一个字符。
回答
我同意Patrick_O的观点,strto {l,ul,ull,ll,d}函数是最好的选择。不过,有几点要注意。
- 在调用函数之前,将errno设置为零;否则,将其设置为0。没有功能为我们做到这一点。
- 链接到的"打开组"页面(在注意到Patrick也已经链接到该页面之前,我曾去过该页面)指出可能未设置errno。如果该值超出范围,则将其设置为ERANGE;否则,将其设置为ERANGE。如果参数无效,则可以将其设置为(但同样可以不设置)为EINVAL。
根据当前的工作,有时我会安排从返回的转换指针的末尾跳过尾随的空白,然后抱怨(拒绝)最后一个字符不是终止null'\ 0'。或者我可以草率地让垃圾出现在末尾,或者我可以接受可选的乘数,例如千字节,兆字节,千兆字节,兆兆字节,...或者其他的" K"," M"," G"," T"基于上下文的需求。