我希望将整数作为命令行参数,但如果用户传递一个非整数字符串,这将导致堆栈溢出。确保 atoi() 成功的标准方法是什么?
9 回答
您可以使用:
long int strtol(const char *nptr, char **endptr, int base);
然后检查是否*endptr != nptr
。这意味着字符串至少以整数开头。您还可以检查 *endptr 是否指向终止零,这意味着整个字符串已成功解析。
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 *
(当然,除非指针为 null 或错误) .
无论如何,您可以轻松实现自己的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
返回。0
您的(非)处理0
是导致堆栈溢出的原因。
导致堆栈溢出?好吧,我想如果字符串中的值超出范围,这是未定义行为的一种可能结果int
。在实践中,虽然它通常只是包装或返回一个虚假的结果。
如果您想要更好的错误检查,请使用strtol
而不是atoi
. 它在溢出时具有明确定义的行为(它设置errno
,您需要在调用之前将其清除为 0,strtol
以便您可以区分错误返回和返回的合法值)并且您可以检查字符串中停止转换的点以查看如果完整的字符串是一个整数,或者是否有超出结尾的附加内容。
这可能会帮助你。检查stdlib.h 中可用的strtol
atoi()
如果字符串仅包含数字字符,则将字符串转换为整数,否则将返回 0。
我不认为标准的atoi会stackoverflow,但是没有办法判断你是否没有整数。改为使用strtol
- 可以处理非整数。
您可以这样做并输入未定义行为领域,您可以编写一个简单的验证函数,如下所示:
/* returns 0 on success, 1 on failure. */
int verify(char * string)
{
int x = 0;
int len = strlen(string);
while(x < len) {
if(!isdigit(*(string+x)))
return 1;
++x;
}
return 0;
}
请注意,您必须在调用 atoi()之前调用此函数,并且需要 string.h 和 stdio.h。
要检查溢出,您只需将获得的数字转换atoi
回字符串即可。现在将此字符串与您的输入字符串进行比较。如果它们匹配,则不是溢出,否则是。
在此处查看伪代码:
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。