我想知道如何确定C / C ++中的溢出。如果我的整数输入是9999999999999999999999,这是一个非常大的数字,如果我运行下面的代码,我将得到一个垃圾输出。
#include <stdio.h>
int main(){
int a;
scanf("%d",&a);
printf("%d",a);
return 0;
}
有没有办法知道,如果输入是一个大数字,我可以输出“输入太大”。
请注意,我已经检查了How to detect integer overflow?。但问题与我的问题不同。
答案 0 :(得分:4)
在您的情况下,读取字符串中的输入,然后根据长度做出决定。你可以在字符串中编码整数,long long等的限制,如果输入的长度(数字的数量)等于或小于你的一个字符串限制,移动一个与比较,如果它小于字符串表示限制,您可以安全地将其转换为整数类型。
更新
或者如果您愿意,您可以在C ++中使用流操作符,正如David Brown建议的那样......
答案 1 :(得分:3)
正如在评论中发表的那样,有一种方法可以在算术运算后检测溢出,这在这种情况下部分有用:
你可以做的是通过char读取char并检查每一步的溢出:
(不确定您是使用C还是C ++,包括<limits>
或<limits.h>
)
int x=0;
while(1){
char c='\0';
scanf(" %c",&c);
if (c<'0' || c>'9')
break;//Input finished
if (!willOverflow(x,c-'0'))
x=x*10+c-'0';
else
break;//Overflow would happen, handle code belongs here
}
int willOverflow(int cur,int next){//Perform your overflow check
//for example i would use
return ((INT_MAX-next)/10)<cur);
}
答案 2 :(得分:1)
这会捕获其他错误以及溢出:
#include <iostream>
#include <string>
#include <boost/lexical_cast.hpp>
int main() {
std::string line;
std::getline(std::cin, line);
try {
std::cout << boost::lexical_cast<int>(line) << "\n";
} catch (const boost::bad_lexical_cast &e) {
std::cout << e.what() << "\n";
}
}
Boost当然是非标准的,你必须为你的系统安装它。如果失败了,或者您希望库函数将输入“99999999999”与“123abc”区分开来,那么您将不得不使用std::stoi
或std::strtol
。两者都不太方便。
答案 3 :(得分:1)
是的,您可以检查从输入中读取的数字溢出,但scanf
不是这样做的。当输入数字太大而无法表示为scanf("%d", &n)
时,调用int
实际上有未定义的行为。 (恕我直言,这是非常不幸的,并使scanf
几乎不可能安全地用于数字输入。)
但是strto*
功能:
strtol
(适用于long
)strtoll
(适用于long long
)strtoul
(适用于unsigned long
)strtoull
(适用于unsigned long long
)strtoull
(适用于unsigned long long
)strtof
(适用于float
)strtod
(适用于double
)strtold
(适用于long double
)尽管它们使用起来有点困难,但对所有输入都有明确定义的行为。
使用fgets
读取一行输入,然后使用strto*
函数之一将输入转换为适当类型的数字。
在溢出时,这些函数返回相应类型的最小值或最大值,并将errno
设置为ERANGE
。您应该在通话前将errno
设置为0
。 (检查errno
设置可以区分溢出和实际输入,例如2147483647
。
阅读man文档,了解相关功能的详细信息。
由于strtoi
没有int
功能,您可以使用strtol
,检查输入是否有效long
,然后检查long
是否有效}值在INT_MIN
.. INT_MAX
范围内;同样适用于unsigned int
和strtoul
。
答案 4 :(得分:0)
如果你需要检查这样的话,读一个字符串然后检查字符串是可行的方法。