两部分问题;
我来自高级语言,所以这是关于形式不是功能的问题;
我编写了一个带有char []的isnumeric()函数,如果字符串是一个利用ctype中的isdigit()函数的数字,则返回1。类似的函数内置于其他语言,我总是使用类似的函数来检查数据,然后再将其转换为数字类型。主要是因为如果尝试将非数字字符串转换为整数,某些语言转换函数会严重失败。
但它似乎是一个必须完成所有循环以补偿C中缺少字符串的kludge,这构成了问题的第一部分;
在调用atoi()之前,在C中捕获来自atoi()的0返回以代替对数据进行完整性检查是否可以接受? atoi()(以及其他ascii到xx函数)的工作方式似乎很适合完全消除完整性检查。跳过支票肯定会更有效率。
问题的第二部分是; 是否有C函数或公共库函数用于数字完整性检查 在一个字符串? (通过字符串,我当然是指char [])
答案 0 :(得分:1)
在调用atoi()之前,在C中捕获来自atoi()的0返回代替对数据进行完整性检查是否可以接受?
永远不会陷入错误,除非错误表明如果代码中没有错误就不会发生编程错误。如果出现错误,请务必返回某种错误结果。查看OpenBSD strtonum
函数,了解如何设计这样的接口。
问题的第二部分是;是否有C函数或公共库函数用于字符串的数字完整性检查? (通过字符串,我当然是指char [])
永远不要使用atoi
,除非您编写的程序没有错误检查,因为atoi
没有进行任何错误检查。 strtol
系列函数允许您检查错误。这是一个如何使用它们的简单示例:
int check_is_number(const char *buf)
{
const char *endptr;
int errsave = errno, errval;
long result;
errno = 0;
result = strtol(buf, &endptr, 0);
errval = errno;
errno = errsave;
if (errval != 0)
return 0; /* an error occured */
if (buf[0] == '\0' || *endptr != '\0')
return 0; /* not a number */
return 1;
}
请参阅之前链接的手册页,了解strtol
(基础)的第三个参数如何影响它的作用。
errno
),则 ERANGE
设置为long
。在这种情况下,返回值为LONG_MAX
或LONG_MIN
。
答案 1 :(得分:1)
如果转换方法返回错误指示(与发生错误的香蕉不同,或者没有提供确定是否发生错误的确定方法),那么实际上不需要检查字符串是否为数字试图转换它。
考虑到这一点,如果您需要检查转换错误,使用atoi()
并不是一个特别好的功能。零输入将返回零,以及错误,并且无法检查原因。使用的更好的函数是(假设您想要读取整数值)是strtol()
。虽然strtol()
在整数上返回零,但它也返回可用于检查失败的信息。例如;
long x;
char *end;
x = strtol(your_string, &end, 10);
if (end == your_string)
{
/* nothing was read due to invalid character or the first
character marked the end of string */
}
else if (*end != '\0`)
{
/* an integral value was read, but there is following non-numeric data */
}
其次,使用strtol()
有其他选择,虽然涉及更多开销。可以检查sscanf()
(实际上,scanf()
系列中的所有函数)的返回值是否存在错误情况。
没有标准函数来检查字符串是否为数字,但可以使用上面的内容轻松滚动。
int IsNumeric(char *your_string)
{
/* This has undefined behaviour if your_string is not a C-style string
It also deems that a string like "123AB" is non-numeric
*/
long x;
char *end;
x = strtol(your_string, &end, 10);
return !(end == your_string || *end != '\0`);
}
上述任何选项中都没有(显式)循环。
答案 2 :(得分:1)
在调用atoi()之前,在C中捕获来自atoi()的0返回以代替对数据进行完整性检查是否可以接受?
没有。 @FUZxxl很好地回答了这个问题。
对字符串进行数字完整性检查是否有C函数或公共库函数?
在C中,将字符串转换为数字并检查转换是否有效通常是一起完成的。使用的功能取决于所寻求的号码类型。 " 1.23"对浮点类型有意义,但不是整数。
// No error handle functions
int atoi(const char *nptr);
long atol(const char *nptr);
long long atoll(const char *nptr);
double atof(const char *nptr);
// Some error detection functions
if (sscanf(buffer, "%d", &some_int) == 1) ...
if (sscanf(buffer, "%lf", &some_double) == 1) ...
// Robust methods use
long strtol( const char *nptr, char ** endptr, int base);
long long strtoll( const char *nptr, char ** endptr, int base);
unsigned long strtoul( const char *nptr, char ** endptr, int base);
unsigned long long strtoull( const char *nptr, char ** endptr, int base);
intmax_t strtoimax(const char *nptr, char ** endptr, int base);
uintmax_t strtoumax(const char *nptr, char ** endptr, int base);
float strtof( const char *nptr, char ** endptr);
double strtod( const char *nptr, char ** endptr);
long double strtold( const char *nptr, char ** endptr);
这些强大的方法使用char ** endptr
来存储扫描停止的字符串位置。如果找到否数字数据,则*endptr == nptr
。所以常见的测试可能是
char *endptr;
y = strto...(buffer, ..., &endptr);
if (buffer == endptr) puts("No conversion");
if (*endptr != '\0') puts("Extra text");
如果范围超过这些函数,则都设置全局变量errno = ERANGE;
并返回该类型的最小值或最大值。
errno = 0;
double y = strtod("1.23e10000000", &endptr);
if (errno == ERANGE) puts("Range exceeded");
整数函数允许从基数2到36进行基数选择。如果使用0
,则字符串"0x"
,"0X"
,"0"
,{的前导部分{1}} - >基数16,16,8,10。
other
阅读规范或帮助页面了解更多详情。
答案 3 :(得分:0)
您可能不需要函数来检查字符串是否为数字。您很可能需要将字符串转换为数字,以便这样做。然后检查转换是否成功。
long number;
char *end;
number = strtol(string, &end, 10);
if ((*string == '\0') || (*end != '\0'))
{
// empty string or invalid number
}
strtol
的第二个参数用于指示解析结束的位置(第一个非数字字符)。如果我们到达字符串的末尾,那个字符将是\0
。如果您想在号码后面允许其他字符(例如),您可以使用
switch
进行检查。
strtol
适用于long
个整数。如果您需要其他类型,请参阅手册页:man 3 strtol
。对于浮点数,您可以使用strtod
。
如果程序逻辑允许字符串不是数字(例如,如果它来自用户或文件),请不要陷阱。
答案 4 :(得分:0)
OP稍后commneted:
我正在寻找一种方法来确定该字符串是仅包含10位基数还是小数或逗号。所以如果字符串是100,000.01我想要从func获得正回报。字符串中任何位置的任何其他ascii字符都会导致负的返回值。
如果您有兴趣,请使用;
if (buffer[strspn(buffer, "0123456789.,")] == '\0') return 0; // Success
else return -1; // Failure