如何检查C / C ++中的整数溢出?

时间:2013-10-27 18:26:26

标签: c++ c

我想知道如何确定C / C ++中的溢出。如果我的整数输入是9999999999999999999999,这是一个非常大的数字,如果我运行下面的代码,我将得到一个垃圾输出。

#include <stdio.h>

int main(){
    int a;
    scanf("%d",&a);
    printf("%d",a);
    return 0;
}

有没有办法知道,如果输入是一个大数字,我可以输出“输入太大”。

请注意,我已经检查了How to detect integer overflow?。但问题与我的问题不同。

5 个答案:

答案 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::stoistd::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 intstrtoul

答案 4 :(得分:0)

如果你需要检查这样的话,读一个字符串然后检查字符串是可行的方法。