简体   繁体   English

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

[英]how can I check integer overflow in C/C++?

I want to know how to determine overflow in C/C++.我想知道如何确定 C/C++ 中的溢出。 if my input for integer is 9999999999999999999999 , It is a very big number and if I run the below code I will get a garbage output.如果我的整数输入是 9999999999999999999999 ,这是一个非常大的数字,如果我运行下面的代码,我会得到一个垃圾输出。

#include <stdio.h>

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

Is there any way to know , if the input is a big number, I can output "Input is too big" .有什么办法可以知道,如果输入是一个大数字,我可以输出“输入太大”。

Note that, I have already checked How to detect integer overflow?请注意,我已经检查了如何检测整数溢出? . . But the question is different from my one.但问题与我的不同。

In your case, read the input in a string and then, depending of the length, make a decision.在您的情况下,读取字符串中的输入,然后根据长度做出决定。 You can encode in string the limits of integer, long long etc and if the input has the length (the number of figures) equal or less than one of your string limits, move one with the comparison and if it is smaller than the string representation of a limit, you can safely convert it to an integer type.您可以在字符串中对整数、long long 等的限制进行编码,如果输入的长度(数字的数量)等于或小于您的字符串限制之一,则通过比较移动一个,如果它小于字符串表示的限制,您可以安全地将其转换为整数类型。

UPDATE更新

or if you prefer you can use stream operators in C++ as David Brown suggested...或者,如果您愿意,您可以像 David Brown 建议的那样在 C++ 中使用流运算符...

As posted in comments there is a way to detect overflow after arithmetic operation, which is partially helpful in this case:正如评论中发布的那样,有一种方法可以检测算术运算后的溢出,这在这种情况下有部分帮助:

What you can do is to read char by char and check for overflow at every step: (Not sure if you use C or C++, either include <limits> or <limits.h> )您可以做的是逐个字符读取字符并在每一步检查溢出:(不确定您是使用 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);
}

This catches other errors as well as overflow:这会捕获其他错误以及溢出:

#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 of course is non-standard, you'll have to install it for your system. Boost 当然是非标准的,你必须为你的系统安装它。 Failing that, or if you want the library function to distinguish input "99999999999" from "123abc" for you then you'll have to use std::stoi or std::strtol .如果失败,或者如果您希望库函数为您区分输入“99999999999”和“123abc”,那么您将不得不使用std::stoistd::strtol Both are somewhat less convenient.两者都不太方便。

Yes, you can check for overflow of numbers read from input, but scanf is not the way to do it.是的,您可以检查从输入读取的数字是否溢出,但scanf不是这样做的方法。 Calling scanf("%d", &n) when the input number is too big to be represented as an int actually has undefined behavior .当输入数字太大而无法表示为int时调用scanf("%d", &n)实际上具有未定义的行为 (IMHO this is very unfortunate, and makes scanf nearly impossible to use safely for numeric input.) (恕我直言,这是非常不幸的,并且使得scanf几乎不可能安全地用于数字输入。)

But the strto* functions:但是strto*函数:

  • strtol (for long ) strtol ( long )
  • strtoll (for long long ) strtoll ( 为long long )
  • strtoul (for unsigned long ) strtoul (对于unsigned long
  • strtoull (for unsigned long long ) strtoull (用于unsigned long long
  • strtof (for float ) strtof (用于float
  • strtod (for double ) strtod (用于double
  • strtold (for long double ) strtold (对于long double

though they're a bit more difficult to use, have well defined behavior for all inputs.尽管它们有点难以使用,但对所有输入都有明确定义的行为。

Use fgets to read a line of input, then use one of the strto* functions to convert the input to a number of the appropriate type.使用fgets读取一行输入,然后使用strto*函数之一将输入转换为适当类型的数字。

On overflow, these functions return the minimum or maximum value of the appropriate type and set errno to ERANGE .溢出时,这些函数返回适当类型的最小值或最大值,并将errnoERANGE You should set errno to 0 before the call.您应该在调用之前将errno0 (Checking errno setting lets you distinguish between an overflow and an actual input of, say, 2147483647 .) (检查errno设置可以让您区分溢出和实际输入,例如2147483647 。)

Read the man documentation for the appropriate function for the gory details.阅读 man 文档以了解相应功能的详细信息。

Since there's no strtoi function for int , you can use strtol , check whether the input was a valid long , and then check whether the long value is in the range INT_MIN .. INT_MAX ;由于int没有strtoi函数,您可以使用strtol ,检查输入是否为有效long ,然后检查long值是否在INT_MIN .. INT_MAX范围内; similarly for unsigned int and strtoul .对于unsigned intstrtoul也类似。

如果你需要检查这样的事情,读入一个字符串然后检查字符串是要走的路。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM