Checking for Integers (in C code)

When processing text data , either from a text file or input entered via the keyboard, we sometimes need to check the data to see if it’s an integer first, then use it for processing.

Note: All code in this example can be downloaded here

Logical error…

In this example, we ask our user to enter a valid integer and we output the square of the integer:

/*
we ask our user to enter a valid integer
and we output the square of the integer
*/
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int inputInteger; //used to store user input
    int  inputSquared;// used to store the square of a valid integer.

    printf("Enter an Integer value....\n");
    scanf("\n%d",&inputInteger);//get input from user

    printf("You entered : %d\n", inputInteger);

    inputSquared = inputInteger*inputInteger;//find square
    printf("\n%d squared is %d\n",inputInteger, inputSquared);
    printf("\nSuccess!  Exiting program\n");

    return 0;
}

This code works when we enter valid input , in this case the user enters 12:

However, if the user enters alpha text data, we get strange results:

A simple fix…

To fix this issue we adhere to 2 rules:

  1. Read all text data as character strings, and then
  2. use the atoi(…) function to convert the string to a valid integer

The previous example can be fixed by using the rules above applied to the current situation:

  1. Read all text data as character strings, and then
  2. use the atoi(…) function to TRY to convert the string to a valid integer
  3. If the user had entered alpha text data, generate an error message, prompt the user to re-enter the data, and go to step 1, otherwise :
  4. Calculate the valid output.

Below is the code…

/*
this program shows how to validate user input as integers.
if the user enters a valid integer, we output the square of the integer,
otherwise we output an error message and prompt the user to re enter  a valid integer
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> //in order to use true and false

int main()
{
    char input[50]; //string used to store user input
    int  inputAsAnInteger;//used to store the converted input  as an integer
    int  inputSquared;// used to store the square of a valid integer.

    while(true)//loop 'infinitely'
    {
        printf("Enter an Integer value....\n");
        scanf("%s",&input);//get input from user

        printf("You entered : %s\n", input);

        inputAsAnInteger=atoi(input);//convert input to integer

        if (inputAsAnInteger==0)//if the input is not a number......
        {
            printf("Invalid input entered\n\n");
        }
        else//input is a number
        {

            inputSquared = inputAsAnInteger*inputAsAnInteger;//find square
            printf("\n%d squared is %d\n",inputAsAnInteger, inputSquared);
            printf("\nSuccess!  Exiting program\n");
            break;//exit 'infinite' loop.
        }
    }
    return 0;
}


And a sample run shown below with invalid input and valid input:

However, note that atoi(…) returns 0 when 0 is entered or invalid input entered, an edge case which produces erroneous results:

Fixing the fix…

This problem can be solved by checking every digit in the input string to see if they are all digits, before converting to an integer. In this way, we cater for a correct result if the text data “0” is entered.

Our rules to fix the problem now become:

  1. Read all text data as character strings, and then
  2. Check each character of the string to ensure they’re all digits, then
  3. use the atoi(…) function to convert the string to a valid integer

This code uses a function which performs that check:

/*
this program shows how to validate user input as integers.
if the user enters a valid integer, we output the square of the integer,
otherwise we output an error message and prompt the user to re enter  a valid integer
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h> //in order to use true and false
#include <ctype.h>   // in order to use the isdigit function.

bool isNumber(char* stringArray);

int main()
{
    char input[50]; //string used to store user input
    int  inputAsAnInteger;//used to store the converted input  as an integer
    int  inputSquared;// used to store the square of a valid integer.

    while(true)//loop 'infinitely'
    {
        printf("Enter an Integer value....\n");
        scanf("%s",&input);//get input from user

        printf("You entered : %s\n", input);


        if (!isNumber(input))//if the input is not a number......
        {
            printf("Invalid input entered\n\n");
        }
        else//input is a number
        {
            inputAsAnInteger=atoi(input);//convert input to integer
            inputSquared = inputAsAnInteger*inputAsAnInteger;//find square
            printf("\n%d squared is %d\n",inputAsAnInteger, inputSquared);
            printf("\nSuccess!  Exiting program\n");
            break;//exit 'infinite' loop.
        }
    }
    return 0;
}

bool isNumber(char* stringArray)
{

    //go through each character
    //location in the array until
    //we reach the null character (end of input)
    for (int i = 0; stringArray[i]!='\000'; i++)
    {
        if(isdigit(stringArray[i])==0)//if the current character is not a digit....
            return false; //return false and end function here

    }

    return true;//return true since the entire array contained numeric characters
}

Now, we get correct results in all cases:

Conclusion And Thoughts

The basic strategy for checking for integer input, is to read all input as text and use the atoi(…) function to try converting the input whilst performing error checking.

To best understand the coded examples, I insist that you use the data in the sample runs to :

  1. perform a dry run as well as
  2. step through each line of code by running the code in debug mode .

The examples above contain minimal explanation, is intended pre-class preparation and presentation in our classroom where we can have a broader discussion and I can answer any questions that you may have.

An improved version (2026)

The last program works for the sample runs above, but it still has some limits. Try these inputs on it yourself:

  • Negative numbers are rejected. isNumber only accepts digits, so the minus sign in -5 makes it return false, and the program says “Invalid input entered” even though -5 is a perfectly good integer.
  • scanf("%s",&input) has a stray & and no size limit. input is an array, and the name of an array already gives scanf its address, so it should be written scanf("%s", input). GCC warns about the & (format '%s' expects argument of type 'char *'). Worse, %s does not know that input only has room for 49 characters plus the '\0'. If the user types more, scanf keeps writing past the end of the array (a buffer overflow), which can crash the program or overwrite other variables.
  • Very large numbers do not fit in an int. 99999999999 is all digits, so it passes the isNumber check, but the largest value an int can hold is usually 2147483647. atoi then gives a wrong number: on my computer the program printed 1215752191 squared is 559034369. Even a number that fits can have a square that does not: 50000 printed 50000 squared is -1794967296.
  • atoi(...) cannot report errors. It returns 0 for abc, the same as for 0, and it returns 12 for 12abc without complaining. That is why we needed isNumber in the first place. atoi has no way to tell us that something went wrong.

The version below fixes all four. It reads the whole line with fgets(…), which is told the size of the array, and then converts it with strtol(…) (“string to long”). Unlike atoi(…), strtol(…) tells us where it stopped reading (through end) and whether the number was out of range (through errno).

Our rules now become:

  1. Read the whole line of text as a character string using fgets(…), and remove the newline at the end, then
  2. use the strtol(…) function to TRY to convert the string to a number (an optional + or – sign is allowed), then
  3. check that some digits were found, that nothing except spaces is left over, and that the number fits in an int.
  4. If any check fails, generate an error message, prompt the user to re-enter the data, and go to step 1, otherwise:
  5. Calculate the valid output.

The checks are done in a function, toInteger, which returns true and stores the number only when the whole string is a valid int:

/*
this program shows an improved way to validate user input as integers.
it accepts negative numbers, and rejects text, numbers followed by text,
and numbers that are too big (or too small) to fit in an int.
if the user enters a valid integer, we output the square of the integer,
otherwise we output an error message and prompt the user to re-enter a valid integer
*/
#include <stdio.h>
#include <stdlib.h>  // in order to use the strtol function
#include <stdbool.h> // in order to use true and false
#include <string.h>  // in order to use the strchr and strcspn functions
#include <ctype.h>   // in order to use the isspace function
#include <errno.h>   // in order to use errno and ERANGE
#include <limits.h>  // in order to use INT_MIN and INT_MAX

bool toInteger(const char *text, int *result);

int main()
{
    char input[50]; //string used to store user input
    int  inputAsAnInteger;//used to store the converted input as an integer
    long long inputSquared;// used to store the square. long long, since the square of a big int does not fit in an int

    while(true)//loop 'infinitely'
    {
        printf("Enter an Integer value....\n");

        if (fgets(input, sizeof input, stdin) == NULL)//get a whole line from the user (at most 49 characters)
        {
            printf("No more input. Exiting program\n");
            return 1;
        }

        if (strchr(input, '\n') == NULL && !feof(stdin))//no newline means the line was too long to fit in input
        {
            int c;
            while ((c = getchar()) != '\n' && c != EOF)//throw away the rest of the line from the input buffer
                ;
            printf("Input too long\n\n");
            continue;//go back to the top of the loop and ask again
        }

        input[strcspn(input, "\n")] = '\0';//remove the newline that fgets keeps at the end

        printf("You entered : %s\n", input);

        if (!toInteger(input, &inputAsAnInteger))//if the input is not a valid integer......
        {
            printf("Invalid input entered\n\n");
        }
        else//input is a valid integer
        {
            inputSquared = (long long)inputAsAnInteger * inputAsAnInteger;//find square
            printf("\n%d squared is %lld\n", inputAsAnInteger, inputSquared);
            printf("\nSuccess!  Exiting program\n");
            break;//exit 'infinite' loop.
        }
    }
    return 0;
}

//tries to convert text to an int.
//returns true and stores the number in *result if the text is a valid int,
//otherwise returns false and leaves *result unchanged.
bool toInteger(const char *text, int *result)
{
    char *end;  //strtol points this at the first character it could not use
    long value; //strtol returns a long, which can hold bigger numbers than an int

    errno = 0;//clear any old error before calling strtol
    value = strtol(text, &end, 10);//convert the text to a base 10 number. Leading spaces and a + or - sign are allowed

    if (end == text)//no digits were found, e.g. "" or "abc"
        return false;

    if (errno == ERANGE || value < INT_MIN || value > INT_MAX)//the number is too big or too small for an int
        return false;

    while (isspace((unsigned char)*end))//skip any spaces after the number
        end++;

    if (*end != '\0')//something other than spaces was left over, e.g. "12abc"
        return false;

    *result = (int)value;//the text is a valid int, so store it
    return true;
}

A few things to notice:

  • fgets(input, sizeof input, stdin) never writes more than 50 characters (including the '\0') into input, so it cannot overflow. Unlike %s, it also keeps spaces.
  • fgets keeps the Enter key as a '\n' at the end of the string. input[strcspn(input, "\n")] = '\0'; replaces it with the null character.
  • If a line is too long to fit, the rest of it is still waiting in the input buffer, so the getchar() loop throws it away before asking again.
  • strtol returns a long, so we check it against INT_MIN and INT_MAX before storing it in an int.
  • The square is stored in a long long, and (long long) converts the number before multiplying, so even 2147483647 squared fits.

Here is a sample run. Every invalid input (text, a number followed by text, an empty line, and a number that is too big) is rejected until 12 is entered:

Enter an Integer value....
abc
You entered : abc
Invalid input entered

Enter an Integer value....
12abc
You entered : 12abc
Invalid input entered

Enter an Integer value....

You entered : 
Invalid input entered

Enter an Integer value....
99999999999
You entered : 99999999999
Invalid input entered

Enter an Integer value....
12
You entered : 12

12 squared is 144

Success!  Exiting program

And four separate runs, with 0, a negative number, a + sign, and spaces around the number. All of them are accepted:

Enter an Integer value....
0
You entered : 0

0 squared is 0

Success!  Exiting program

Enter an Integer value....
-5
You entered : -5

-5 squared is 25

Success!  Exiting program

Enter an Integer value....
+7
You entered : +7

7 squared is 49

Success!  Exiting program

Enter an Integer value....
 42 
You entered :  42 

42 squared is 1764

Success!  Exiting program

To learn more about strings, char arrays, %s and fgets, see Strings in C: char Arrays, %s, fgets, and strlen. The input buffer, where the rest of a long line waits, is explained in Using Library Functions: #include, getch(), and the Input Buffer.

Updates

2026/10/04

– Added an improved version that accepts negative numbers and uses fgets and strtol.

– Fixed a few typos.

© 2020 Vedesh Kungebeharry. All rights reserved.

Leave a Reply