如何在C / C ++中检查整数溢出?
我想知道如何确定C / C ++中的溢出。 如果我的整数输入是9999999999999999999999,这是一个非常大的数字,如果我运行下面的代码,我将得到一个垃圾输出。
#include int main(){ int a; scanf("%d",&a); printf("%d",a); return 0; }
有没有办法知道,如果输入是一个大数字,我可以输出“输入太大”。
注意,我已经检查了如何检测整数溢出? 。 但问题与我的问题不同。
在您的情况下,读取字符串中的输入,然后根据长度做出决定。 你可以在字符串中编码整数,长整数等的限制,如果输入的长度(数字的数量)等于或小于你的一个字符串限制,移动一个与比较,如果它小于字符串表示限制,您可以安全地将其转换为整数类型。
UPDATE
或者如果您愿意,可以在C ++中使用流操作符,正如David Brown建议的那样……
正如在注释中发布的那样,有一种方法可以在算术运算后检测溢出,这在这种情况下部分有用:
你可以做的是通过char读取char并检查每一步的溢出:(不确定你是否使用C或C ++,包括
或
)
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)
这会捕获其他错误以及溢出:
#include #include #include int main() { std::string line; std::getline(std::cin, line); try { std::cout << boost::lexical_cast(line) << "\n"; } catch (const boost::bad_lexical_cast &e) { std::cout << e.what() << "\n"; } }
Boost当然是非标准的,你必须为你的系统安装它。 如果失败了,或者你想让库函数区分输入“99999999999”和“123abc”,那么你将不得不使用std::stoi
或std::strtol
。 两者都不太方便。
是的,您可以检查从输入读取的数字溢出,但scanf
不是这样做的方法。 当输入数字太大而无法表示为int
时scanf("%d", &n)
调用scanf("%d", &n)
实际上具有未定义的行为 。 (恕我直言,这是非常不幸的,并且使scanf
几乎不可能安全地用于数字输入。)
但是strto*
function:
-
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文档,了解相关function的详细信息。
由于int
没有strtoi
函数,你可以使用strtol
,检查输入是否为有效long
,然后检查long
值是否在INT_MIN
范围内INT_MAX
; 类似于unsigned int
和strtoul
。
如果你需要检查这样的事情,读一个字符串,然后检查字符串是要走的路。