How to check for integer range?

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;
}

Upvotes: 1

Views: 20724

Answers (6)

wilx
wilx

Reputation: 18228

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

Upvotes: 0

Christian Hackl
Christian Hackl

Reputation: 27528

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.

Upvotes: 9

Swift - Friday Pie
Swift - Friday Pie

Reputation: 14589

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.

Upvotes: 5

Sunil Kumar
Sunil Kumar

Reputation: 416

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;
}

Upvotes: 0

Maroš Beťko
Maroš Beťko

Reputation: 2329

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.

Upvotes: 1

jonas_toth
jonas_toth

Reputation: 872

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.

Upvotes: -4

Related Questions