6

I am trying to read an unsigned int using cin as follows:

#include <limits.h>
#include <iostream>

using namespace std;

int main(int argc, char* argv[])
{
    unsigned int number;

    // UINT_MAX = 4294967295
    cout << "Please enter a number between 0 and " << UINT_MAX << ":" << endl;

    cin >> number;

    // Check if the number is a valid unsigned integer
    if ((number < 0) || ((unsigned int)number > UINT_MAX))
    {
        cout << "Invalid number." << endl;
        return -1;
    }
    return 0;
}

However, whenever I enter a value greater than the upper limit of unsigned integer (UINT_MAX), the program displays 3435973836. How do I check if the input given by user falls between 0 to UINT_MAX?

andand
  • 17,134
  • 11
  • 53
  • 79
user1250836
  • 63
  • 1
  • 4

5 Answers5

5

Two things:

  • Checking if an unsigned integer is < 0 or > UINT_MAX is pointless, since it can never reach that value! Your compiler probably already complains with a warning like "comparison is always false due to limited range of type".

  • The only solution I can think of is catching the input in a string, then use old-fashioned strtoul() which sets errno in case of overflow.

I.e.:

#include <stdlib.h>

unsigned long number;
std::string numbuf;
cin >> numbuf;
number = strtoul(numbuf.c_str(), 0, 10);
if (ULONG_MAX == number && ERANGE == errno)
{
    std::cerr << "Number too big!" << std::endl;
}

Note: strtoul returns an unsigned long; there's no function strtou(), returning an unsigned int.

andand
  • 17,134
  • 11
  • 53
  • 79
JvO
  • 3,036
  • 2
  • 17
  • 32
3

Your check makes no sense (which a compiler with properly enabled warnings would tell you) as your value is never under 0 and never over UINT_MAX, since those are the smallest and biggest value a variable of the type unsigned int (which number is) can hold.

Use the stream state to determine if reading into the integer worked properly.

PlasmaHH
  • 15,673
  • 5
  • 44
  • 57
2

You could read into an unsigned long long and test that against the unsigned int limit.

AShelly
  • 34,686
  • 15
  • 91
  • 152
  • @BoPersson, are you saying the `>>` automatically promotes to long long? Even if it does, it would need to truncate when storing in an unsigned int. – AShelly Mar 05 '12 at 22:21
  • I'm saying that `operator>>` is using `num_get` which collects characters, converts to the largest unsigned integer type and then verifies the target range before assigning the result. Just like if you had done that yourself. – Bo Persson Mar 05 '12 at 22:30
2

When users enter a number higher than UINT_MAX, cin caps it at UINT_MAX anyway. The value cannot be negative, either.

If you need to extend the range, use unsigned long long for input, and cast to unsigned int after the check. This will not guard against numbers that are outside of range of unsigned long long, though.

For a general-purpose solution, you can read a string, and do a conversion yourself using unsigned long long as your result.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

If you try to read it into an unsigned int you are going to have to limit yourself to the constraints of an unsigned int.

The most general way to do what you're asking is to read the input as a string and parse it to make sure it's in the proper range. Once you have validated it, you can convert it to an unsigned int.

andand
  • 17,134
  • 11
  • 53
  • 79