2
votes

Does anyone know why I am getting a segfault when I run this code? Valgrind tells me that I have "uninitialized value of size 4" on line 13 if( !isdigit(x) ) and an invalid read size 2 on the same line -- address is not stack'd, malloc'd, or free'd.

#include <stdio.h> 
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>

int main()
{
    int x;

    printf("Please enter a number: ");
    scanf("%d", &x);

    if( !isdigit(x) )
    {
        printf("You entered %d\n", x);
    }
    else
    {
        printf("You did not enter a valid number!\n");
    }

    return 0;
}
4
isdigit is meant to be used against character values; it will return true for an input of '1' and false for an input of 'a', for example. What are you entering for your input? - John Bode
isdigit() isn't going to work in the way you are hoping if you use using %d. If you enter 1, for instance, x will not contain the ASCII code for the character 1, so isdigit() will return false. - Crowman
Please remember to always check whether input succeeded: scanf(...) == 1? - Deduplicator
Unrelated, but scanf will fail if the input is not a digit. So instead of checking, "isdigit" you can replace it with the result of scanf. - Tim Z.
"getting a segfault" - it's not a segfault. - Karoly Horvath

4 Answers

1
votes

I think that the problem is that if scanf will fail x will be uninitialized. It is better to enter data in a character array. Otherwise your code has no sense because you are unable to enter a non-number in an object of type int. Moreover if you enter a number the result of using function isdigit can be unexpected.

1
votes

I compiled your code with g++, resulting in no segfault.

Entering values of:

5, -1, 27, 43545gbb, and gggg

produced results:

5, -1, 27, 43545, and 1729208414

0
votes

Try the following :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int x = 0;
    char a;

    printf("Please enter a number: ");

    while(scanf("%d%c",&x,&a) != 2 || a != '\n')
    {
        printf("Please enter an integer only : ");
        do
        {
            scanf("%c",&a);
        }while(a != '\n');
    }

    printf("You entered %d\n", x);
    return 0;
}

The code show you a complex way of how to use scanf. For more information : Working of scanf and checking if input is int

According to the c documentation : isdigit

Prototype:

int isdigit( int ch );

Parameters:

ch  -   character to classify

Purpose:

Checks if the given character is a numeric character (0123456789). The behavior is undefined if the value of ch is not representable as unsigned char and is not equal to EOF.

Return value:

Non-zero value (true) if the character is a numeric character, 0 (false) otherwise.

-1
votes

Why the problem on Line 13?. Line 13 is if( !isdigit(x) )
You did not initialize x when you created it on line 8,
Therefore, if an unacceptable value is entered, and processed by scanf() on line 11, it will continue to be uninitialized by the time it gets to the isdigit() function.

The problem is that isdigit() expects The input must be a character with integer value between 0 and 255. Any other value will lead to undefined behavior. Segfaults are one of the possible outcomes of undefined behavior.

There are other ways to implement this, for example:
Here is an example using a char array (string). Note the comments to explain why certain things were done.

int main()
{
    //int x;
    char x[2];  //Good for only one digit

    printf("Please enter an integer with up to 10 digits: ");
    //scanf("%d", &x); 
    scanf("%1s", x); //Edited to allow maximum field width of 1.

   // if( !isdigit(x) )        
    if( isdigit(x[0]) ) //note the "!" was removed for logic to work
    {
        printf("You entered %d\n", atoi(x)); //note use of atoi() to convert string to int.
    }
    else
    {
        printf("You did not enter a valid number!\n");
    }

    return 0;
}