在调用atoi()之前如何检查以确保你有一个整数?

问题描述 投票:0回答:9

我希望将整数作为命令行参数,但是如果用户传递非整数字符串,这将导致堆栈溢出。 确保 atoi() 成功的标准方法是什么?

c casting atoi
9个回答
25
投票

您可以使用:

long int strtol(const char *nptr, char **endptr, int base);

然后检查是否

*endptr != nptr
。这意味着字符串至少以整数开头。 您还可以检查 *endptr 是否指向终止零,这意味着整个字符串已成功解析。


3
投票
如果字符串包含数字以外的字符,

atoi()
将(不应该)导致堆栈溢出。它会简单地转换为
int
从字符串开头找到的任何数字,直到没有更多数字为止。

  int x = atoi("12monkeys"); // x is 12
  int y = atoi("monkeys12"); // y is 0

您可以检查是否存在整数溢出(现代(当前)PC 架构上的数字超出 [-2^31, 2^31-1] 范围)。

编辑(评论)

虽然 C 标准会在值无法表示时警告“未定义行为”,但如果值不可接受,最常见的 C 最新编译器(gcc、MS...)不会“崩溃”(除非 char *当然,指针为空或错误)。 无论如何,您可以轻松实现自己的

atoi()
(与我的答案具有相同的限制)

#include <ctype.h> int myatoi(char *s) { int res = 0, minus = *s == '-'; if (minus) s++; while (isdigit(*s)) { res = res*10 + (*s++ - '0'); } return minus ? -res : res; }

    

我不认为标准的 atoi 会出现 stackoverflow,但是没有办法判断你是否没有整数。  使用 
strtol

1
投票

http://en.wikipedia.org/wiki/Strtol

导致堆栈溢出?好吧,我认为如果字符串中的值超出了

int

1
投票
未定义行为

的可能结果。但在实践中,它通常只是包装或返回虚假结果。 如果您想要更好的错误检查,请使用

strtol
而不是

atoi

。它在溢出时具有明确定义的行为(它设置

errno
,您需要在调用
strtol
之前将其清除为 0,以便您可以区分错误返回和返回的合法值),并且您可以检查字符串中的点它停止转换以查看完整字符串是否是整数或者末尾是否有其他内容。
    
你可以这样做并进入未定义行为领域,你可以编写一个简单的验证函数,如下所示:


1
投票

请注意,您必须在调用 atoi() 之前

调用此函数,并且需要 string.h 和 stdio.h。
    

这可能对你有帮助。检查 stdlib.h 中可用的 strtol


1
投票

atoi() 如果字符串只包含数字字符,则将其转换为整数,否则将返回 0。


0
投票

要检查溢出,您只需将从

atoi
获得的数字转换回字符串即可。现在将此字符串与您的输入字符串进行比较。如果它们匹配,则不是溢出,否则就是溢出。


0
投票

int check_overflow(int num, char *arr, int len){ char buf[len + 1]; sprintf(buf, "%d", num); if(strcmp(buf, arr) == 0){ return 0; } return -1; }

如果溢出,函数返回 -1,否则返回 0。

在调用 atoi() 之前如何检查以确保你有一个整数?


0
投票
atoi
(函数族)。它们是危险的,而且是 100% 多余的功能,几十年前就应该被标记为过时的。

问题是这样的(C17 7.22.1):

7.22.1 数值转换函数
函数

atof

atoi

atol

atoll
发生错误时不需要影响整数表达式
errno
的值。如果结果的值无法表示,则行为未定义。

因此,它们 1) 不需要以任何方式处理错误,2) 在发生错误时具有未定义的行为,这意味着您的程序可能会出错、崩溃或被休眠错误污染,从而在以后引起问题。
幸运的是,C 标准还定义了更好且 100% 兼容的替代方案 (C17 7.22.1.2)

atoi、atol 和 atoll 函数分别将 nptr 指向的字符串的初始部分转换为 int、long int 和 long long int 表示形式。除了错误时的行为外,它们相当于


atoi: (int)strtol(nptr, (char **)NULL, 10) atol: strtol(nptr, (char **)NULL, 10) atoll: strtoll(nptr, (char **)NULL, 10)

事实上,许多 C 库将 ato* 函数实现为调用 strto* 函数的宏,如上面所示,基数为 10(十进制)。这就是为什么 ato* 在许多编译器上的表现可能是可预测的,尽管 C 语言没有做出这样的保证。

至于
atoi
导致堆栈溢出,这似乎不太可能,因为该函数没有理由分配大量堆栈空间。我认为理论上,一些功能失调的 C 库可能只是为了好玩而用递归来实现它,从而带来堆栈溢出的风险,但明智的库编写者不会这样做。

问题中的陈述更有可能将堆栈溢出与未定义的行为混淆 - 理论上前者可能是后者引起的众多结果之一。


© www.soinside.com 2019 - 2024. All rights reserved.