4

I want to know how to determine overflow in 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.

#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.

Community
  • 1
  • 1
Md. Al-Amin
  • 1,423
  • 1
  • 13
  • 26
  • 3
    Is this C or C++? In C++ you should probably use stream operations following [this question/answer](http://stackoverflow.com/questions/17116690/c-read-int-from-istream-detect-overflow). – David Brown Oct 27 '13 at 18:31
  • 3
    This question is not at all a duplicate of that one. That one is about detecting overflow happening due to arithmetic operations. This question is about handling string input which, if parsed as an integer, would not fit into the specified integer type. – Benjamin Lindley Oct 27 '13 at 18:33
  • check this thread http://stackoverflow.com/questions/1787892/overflow-over-scanf8s-string – Vishnu Kanwar Oct 27 '13 at 18:35
  • @rightfold: C and C++ share a common subset. Don't remove C++ tags from questions about code which lies in that subset. http://meta.stackexchange.com/questions/158450/retagging-c-questions-as-c-without-consulting-asker – Benjamin Lindley Oct 27 '13 at 18:37
  • @Kninnug , I have checked that question. My question is different from it. – Md. Al-Amin Oct 27 '13 at 18:38
  • @BenjaminLindley, Thank you for understanding my question. – Md. Al-Amin Oct 27 '13 at 18:40
  • Any solution would work for me. Either in C or C++ @DavidBrown – Md. Al-Amin Oct 27 '13 at 18:41

5 Answers5

4

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.

UPDATE

or if you prefer you can use stream operators in C++ as David Brown suggested...

asalic
  • 949
  • 4
  • 10
  • @Md.Al-Amin have you checked David Brown's answer? It is a pretty way to check for what you want, just take a look at the first response for the linked question. – asalic Oct 27 '13 at 18:56
  • Yes, I checked David Brown's answer. But I didn't get it. I want to take input from the terminal, I mean stdin. – Md. Al-Amin Oct 27 '13 at 19:08
  • 2
    @Md.Al-Amin very well, read the input using std::cin in a std::string and then call the **istringstream** initialization constructor with the string you read as a parameter. Check this page for more details about **istringstream** : http://www.cplusplus.com/reference/sstream/istringstream/istringstream/ – asalic Oct 28 '13 at 08:45
  • Sure, I will :) @asalic – Md. Al-Amin Oct 28 '13 at 09:31
  • 1
    Checking the number of digits isn't enough. For example if `INT_MAX == 2147483647`, you'd eliminate any number above `999999999`. – Keith Thompson Nov 02 '13 at 03:30
  • @KeithThompson No I wouldn't because I would take into account the numbers with 10 digits and less not numbers with 9 digits and less. If it has 9 or less it is okay no comp is needed, if it has 10, then do the comparison... – asalic Nov 02 '13 at 07:51
  • You don't say how to do the comparison. – Keith Thompson Nov 02 '13 at 18:26
3

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>)

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);
}
Kyborek
  • 1,519
  • 11
  • 20
  • 1
    I do not think it is the right test anyway, but you let the arithmetic overflow happen when you write `(x*10+(c-'0'))`. Signed arithemtic overflow is undefined behavior, this allows the compiler to generate the code it wants, including to optimize away the entire test and `else` branch. – Pascal Cuoq Oct 27 '13 at 19:34
  • You are right, the overflow check "might" or "might not" work. I have modified the check. Thank you for your comment. – Kyborek Oct 29 '13 at 12:12
  • Yes, I think it is fine now. There are more versions than you might want to see (both correct and incorrect) in the answers to a “challenge” by John Regehr: http://blog.regehr.org/archives/914 – Pascal Cuoq Oct 29 '13 at 12:30
2

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. 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. Both are somewhat less convenient.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
1

Yes, you can check for overflow of numbers read from input, but scanf is not the way to do it. Calling scanf("%d", &n) when the input number is too big to be represented as an int actually has undefined behavior. (IMHO this is very unfortunate, and makes scanf nearly impossible to use safely for numeric input.)

But the strto* functions:

  • strtol (for long)
  • strtoll (for long long)
  • strtoul (for unsigned long)
  • strtoull (for unsigned long long)
  • strtof (for float)
  • strtod (for double)
  • strtold (for 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.

On overflow, these functions return the minimum or maximum value of the appropriate type and set errno to ERANGE. You should set errno to 0 before the call. (Checking errno setting lets you distinguish between an overflow and an actual input of, say, 2147483647.)

Read the man documentation for the appropriate function for the gory details.

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; similarly for unsigned int and strtoul.

MDXZ
  • 160
  • 12
Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
0

Reading in a string and then checking the string is the way to go, if you need to check for such a thing.

ThunderGr
  • 2,297
  • 29
  • 20