0

I have this code, but it prints garbage when I enter a value which exceeds integer value. I have actually if condition to check for the range. How to make it work? I know this is easy for you. I just forgot some things in C++ and I have no time.

#include <iostream>
#include <typeinfo>
#include<cfloat>
#include<climits>

using namespace std;

int    g1, g2;
string text  = " year";
string text2 = " age";

int main() {
  g1 = 2100000000000000000000000;
  g2 = 16;

  if (g1 < INT_MIN || g1 > INT_MAX) {
    std::cout << "Please enter an integer";
  } else {
    std::cout << g1 << text;
    std::cout << g2 << text2;
  }

  return 0;
}
Biffen
  • 6,249
  • 6
  • 28
  • 36
  • 5
    You're checking if an `int` is less than `INT_MIN`. How could it ever be? – Biffen Mar 05 '17 at 09:03
  • Possible duplicate with: http://stackoverflow.com/questions/18625964/checking-if-an-input-is-within-its-range-of-limits-in-c http://stackoverflow.com/questions/18728754/checking-input-value-is-an-integer – Jaege Mar 05 '17 at 09:05
  • Jou could just try to parse to an integer. If it gives a false back, it's not an integer because it contains invalid chars or it's bigger than `INT_MAX` or smaller than `INT_MIN`. – H. Pauwelyn Mar 05 '17 at 09:05
  • 1
    This smells like an [XY problem](http://mywiki.wooledge.org/XyProblem). What are you *really* trying to achieve? – Biffen Mar 05 '17 at 09:29
  • Turn on compiler warnings and use a level high enough to get something like `warning: overflow in implicit constant conversion` – Christian Hackl Mar 05 '17 at 10:07
  • Your check is too late. If it were possible for `g1` to store a value that was lower than the lowest value it can hold, or for it to store a value that was higher than the highest value it can hold, then those limits would be (by definition) wrong. – Lightness Races in Orbit Nov 07 '18 at 13:43

6 Answers6

8

Because C++ is deliberately vague about the minimum and maximum sizes of primitive types like int, big integer literals like 2100000000000000000000000 are dangerously platform-dependent.

Your program may even be ill-formed and not compile at all as a result of it. Fortunately, checking user input does not have anything to do with integer literals. The former occurs at runtime, the latter is a compile-time aspect.

This means that your example code is an unrealistic scenario. In a real program, the value of g1 will not be a compile-time constant but a number entered by the user.

A very good practice is to first let the user enter the number into a std::string with std::getline, and then use std::stoi to convert the string into an int.

If you follow that practice, all error checking is performed by the standard library and you don't have to use INT_MIN, INT_MAX or their C++ counterparts std::numeric_limits<int>::min() and std::numeric_limits<int>::max() at all.

Example:

#include <iostream>
#include <string>

auto const text  = " year";
auto const text2 = " age";

int main() {
  try {
    std::string input;

    std::getline(std::cin, input);
    auto const g1 = std::stoi(input);

    std::getline(std::cin, input);
    auto const g2 = std::stoi(input);

    std::cout << g1 << text;
    std::cout << g2 << text2;
    std::cout << '\n';

  } catch (std::out_of_range const&) {
    std::cout << "Please enter an integer\n";
  }
}

The great thing is that this will also detect other kinds of bad user input, for example when the user enters letters instead of digits. Extending the error handling in this piece of example code to catch other kinds of exceptions is left as an exercise to the reader.

Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
  • Couldn't put it better. And that's a good example how to get value in a minimal way, though it doesn't expose mechanism that is used by stoi(), which does what question asks about (and we may have an X-Y there hidden). Sometimes one might want to create own function, to add custom actions or error handling, or use exception-less code – Swift - Friday Pie Mar 05 '17 at 10:46
  • @Swift: In fact, I'd personally wrap `std::stoi` in a function of my own and use something other than exceptions to report errors, because wrong user input is not really an exception. Perhaps return a tuple or struct of `std::optional` and an error code. – Christian Hackl Mar 05 '17 at 11:15
4

In C++ you should use std::numeric_limits (from <limits>). Name of header <climits> starting with C suggests that it is an old C header, left for compatibility (former limits.h). You forgot parenthesis in expression, it would be evaluated wrong way. Literal is too big for int. Value can't actually exceed bounds for bound types

http://en.cppreference.com/w/cpp/types/numeric_limits

#include <iostream>
#include <typeinfo>
#include<limits>

long long g1, g2;

int main() 
{
  //...

  if ((g1 > std::numeric_limits<int>::lowest()) 
       || (g1 < std::numeric_limits<int>::max())) 
  {
       //...
  } 

  return 0;
}

You must handle input from cin in way that would reset input if user done something wrong. To actually (close can of worms) check for range, you need a bigger (can of worms) storage. Consider this function:

int  getInt()
{
    while (1) // Loop until user enters a valid input
    {
        std::cout << "Enter an int value: ";
        long long x;  // if we'll use char, cin would assume it is character
        // other integral types are fine
        std::cin >> x;

        if (std::cin.fail()) // has a previous extraction failed?
        {
            // yep, so let's handle the failure, or next >> will try parse same input
            std::cout << "Invalid input from user.\n";
            std::cin.clear(); // put us back in 'normal' operation mode
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n'); // and remove the bad input
        }
        // Thechnically you may do only the above part, but then you can't distingusih invalid format from out of range
        else if(( x  > std::numeric_limits<int>::max()) ||
            ( x  < std::numeric_limits<int>::min()))
        {
            std::cout << "Invalid value.\n";
        }
        else // nope, so return our good x
            return x;
    }
}

If istream fails to parse input into required type, the remaining content of buffer is left unmodified until you clear it or you request action that will result in success. For example you can check if user had entered a float.. or if he entered a command to stop program.

Biffen
  • 6,249
  • 6
  • 28
  • 36
Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42
1

What you want to do is really hard to check for. Just like checking if you have saved a negative number into unsigned integer. Once it is saved there, the information is lost and the value becomes corrupted, because of different representation of information stored inside that variable.

I'm not sure what happens if you try to save a value bigger than variable space but still the best option would be to load it up as string and parse it with std::stoi(), which would give you error if the values was exceeding the int range.

Maroš Beťko
  • 2,181
  • 2
  • 16
  • 42
  • Checking user input always a tricky thing, you must assume that user was wrong, may be wrong and HOW they may be wrong. What lies beyond may appear to be an edge case (and Little Johnny Drop Tables will get ya https://xkcd.com/327/ ). Streams do have error state for that, described in documentation for >> operator – Swift - Friday Pie Mar 05 '17 at 10:14
0

If your goal is to check whether an input number is in the range of integer or not? Then you can take the input number as string and with string functions you can check if the number is in the range or not. Here is one implementation.

std::string inputNum = ""; //input number as string
std::cin>>inputNum; //assuming you are going to input numbers only
std::string maxNum = std::to_string(INT_MAX); //2147483647
std::string minNum = std::to_string(INT_MIN); //-2147483648

if(inputNum[0] == '-') //negative number
{
    /* if num of digits are more than min Number's digit
     * then the number is already out of range 
     * if num of digits are equal then you would have 
     * to check whether it is less than the min number or not
     * all numbers with lesser number of digits are in the range
    */
    if(inputNum.length() > minNum.length()) 
        std::cout<<"Not an integer" << std::endl;
    else if(inputNum.length() == minNum.length())
        if(inputNum > minNum)
            std::cout<<"Not an integer" << std::endl;
        else
            std::cout<<"Integer" << std::endl;
    else
        std::cout<<"Integer" << std::endl;
}

else //positive number
{
    if(inputNum.length() > maxNum.length())
        std::cout<<"Not an integer" << std::endl;
    else if(inputNum.length() == maxNum.length())
        if(inputNum > maxNum)
            std::cout<<"Not an integer" << std::endl;
        else
            std::cout<<"Integer" << std::endl;
    else
        std::cout<<"Integer" << std::endl;
}
Sunil Kumar
  • 390
  • 1
  • 7
  • 25
0

Simply check that the input has succeeded:

#include <iostream>


int main()
{
    int val;
    if (std::cin >> val)
        std::cout << "value is " << val << "\n";
    else
        std::cout << "value input failure\n";

    return 0;
}

Live on Coliru

wilx
  • 17,697
  • 6
  • 59
  • 114
-4

c++ has the header file, there are some minimum and maximum for different datatypes for the implementation you are using.

look there. furthermore, you must use 64bit integer, see if its smaller then the maximum or bigger then the minimum for 32bit integere, then you can convert.

jonas_toth
  • 872
  • 5
  • 8
  • It is not as easy as "using" a 64bit type as in C++ the size of short,int,long are only guaranteed to at least be a certain size. A simple "int" might be anything that holds at least 16 bits - it could be 16,32,64bit or even larger. There are fixed-width types but they are optional. And your answer does not really help much "there is something you need to do - but i will not give the names of either the headers or datatypes i mention". – ABaumstumpf Aug 02 '21 at 07:44