3

My C code as follows

int main() {
    int userInput = 0;

    while (userInput != 4) {
        printf("Enter a number : ");
        scanf("%d", &userInput);
    };
    return 0;
}

This normally work when input a integer value. But when input a string value it not asking again to a input. It goes to a endless loop printing the "Enter a number" phrase. Then, I tried the code as follows.

int main() {
    int userInput = 0;

    while (userInput != 4) {
        userInput = 0;             // reset the userInput value
        printf("Enter a number : ");
        scanf("%d", &userInput);
    };
    return 0;
}

Even that not solved my problem. Why is this happening? How can it be fixed?

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
trueThari
  • 105
  • 1
  • 8
  • 3
    You should check the return value of `scanf` to see if it succeeded. If the input does not match the format string, it remains in the stream and will be read (and failing) over and over. – Eugene Sh. Nov 17 '21 at 18:56
  • 2
    Your `%d` format is only looking for integers. It will stop if it sees a non-integer character. So it's just looking at the same character over and over. You'd be better off reading an entire line, then looking at what you read. – Tom Karzes Nov 17 '21 at 18:56
  • 2
    Does this answer your question? [Entering a character instead of integer](https://stackoverflow.com/questions/34299269/entering-a-character-instead-of-integer) – DYZ Nov 17 '21 at 18:56
  • 1
    trueThari, Note that you are not entering a _string_ so much as a _line of text_, likely with a terminating `'\n'`. A _string_ in C is character array with a terminating _null chracter_. – chux - Reinstate Monica Nov 17 '21 at 18:58

2 Answers2

1

You need to free the input buffer from an invalid data. Something like the following.

do
{
    printf("Enter a number : ");
    if ( scanf("%d", &userInput) != 1 )
    {
        scanf( "%*[^\n]" );
        userInput = 0;
    }
} while ( userInput != 4 );

Another approach is to use the function fgets to read the whole string in a character array and then convert it to an integer using strtol and check whether the conversion was successful.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

"This normally work when input a integer value. But when input a string value it not asking again to a input."

If a data scan is not converted by scanf(), the input stream, in this case stdin, is not advanced. When scanf() is called again, it will attempt to scan & convert the same data from the same incorrect input, with the same result. This is what causes your infinite loop. Inputting alpha characters when `scanf() is setup to convert numeric characters will always fail.

The good news is scanf() returns a value indicating how many items were converted successfully. alpha input scanned using the %d format specifier, should result in converting zero items. Code using scanf() should always check it's return value:

int num_converted = scanf("%d", &userInput);
if(num_converted != 1) 
{
     //handle error 
     ...
}

As an aside, scanf() is considered by many as as sub-optimal method for handling user input. For example

"...it will tell you whether it succeeded or failed, but can tell you only approximately where it failed, and not at all how or why. You have very little opportunity to do any error recovery."
(jamesdlin).

Consider an alternative method based on using fgets().

The following reads the entire input line into a buffer, eliminates unwanted white space and validates input. Only then does it convert the input buffer to the specified type...

int main(void) {
    int userInput = 0;
    char inBuf[20] = {0};
    
    printf("Enter a number : ");
    //int num = scanf("%d", &userInput);
    while (fgets(inBuf, sizeof inBuf, stdin)) {
        inBuf[strcspn(inBuf, "\r\n")] = 0;//remove unwanted white space
        if(digits_only(inBuf))//example validation for numeric only input
        {
            userInput = atoi(inBuf);
            printf("\n%d entered, and converted!\n\nctrl-c to exit\n...Or enter a number : \n", userInput);
        }
        else
        {
            printf("\n%s contains non-numeric characters, it cannot be converted.\n\nctrl-c to exit\n...Or enter a number : \n", inBuf);
        }
    };
    return 0;
}

//test for numeric only input   
//(note that other validations can be coded with expansions 
//to accommodate float or double, alpha only, etc.)    
bool digits_only(const char *in)
{
    while(*in)
    {
        if(!isdigit(*in)) return false;
        in++;
    }
    return true;
}
ryyker
  • 22,849
  • 3
  • 43
  • 87