I want to read a int from stdin but I want to validate if the user exceeds the int max value. How can I do it?
int n;
scanf("%d", &n);
scanf reads the decimal input and stores in the int, causing overflow. How can I check and avoid this?
The only way to convert a string representation of a number to the actual value and to watch for overflow is to use functions from strto..
group. In your case you need to read in a string representation of the number and then convert it using strtol
function.
Beware of responses that suggest using atoi
or sscanf
to perform the final conversion. None of these functions protect from overflow.
According to §7.21.6.2 ¶10 of the ISO C11 standard, if the result of a conversion performed by the function scanf
cannot be represented, then the behavior is undefined. Therefore, this function cannot be reliably used for the purpose of input validation.
However, when converting a string to an integer using the function strtol
, if a range error occurs, the behavior is well-defined. In this case errno
will be set to ERANGE
. This will tell you if the number the user entered is out of range of a long
. If you want to determine whether it is out of range of an int
, then you must additionally verify that the number is larger than or equal to INT_MIN
and smaller than or equal to INT_MAX
. Note that you must #include <limits.h>
to use these constants.
Therefore, I recommend the following code to read a number from the user and to validate it:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>
int main( void )
{
char buffer[1024], *p;
long num_long;
int num_int;
//prompt user for input
printf( "Enter a number: " );
//get one line of input from input stream
if ( fgets( buffer, sizeof buffer, stdin ) == NULL )
{
fprintf( stderr, "Unrecoverable error reading from input!\n" );
exit( EXIT_FAILURE );
}
//make sure that entire line was read in (i.e. that
//the buffer was not too small)
if ( strchr( buffer, '\n' ) == NULL )
{
printf( "Line input was too long!\n" );
exit( EXIT_FAILURE );
}
//attempt to convert string to number
errno = 0;
num_long = strtol( buffer, &p, 10 );
if ( p == buffer )
{
printf( "Error converting string to number\n" );
exit( EXIT_FAILURE );
}
//make sure that no range error occurred
if ( errno == ERANGE || num_long < INT_MIN || num_long > INT_MAX )
{
printf( "Range error!\n" );
exit( EXIT_FAILURE );
}
//range is ok, so we can convert to int
num_int = (int)num_long;
//make sure that remainder of line contains only whitespace,
//so that input such as "6sdfh4q" gets rejected
for ( ; *p != '\0'; p++ )
{
if ( !isspace( (unsigned char)*p ) )
{
printf( "Unexpected input encountered!\n" );
exit( EXIT_FAILURE );
}
}
//number was successfully converted, so we print it
printf( "You entered the following valid number: %d\n", num_int );
}
Example output of this program when entering a valid number:
Enter a number: 65
You entered the following valid number: 65
Example output of this program when entering invalid input:
Enter a number: 6sdfh4q
Unexpected input encountered!
Example output of this program when entering out of range input:
Enter a number: 3000000000
Range error!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With