trueThari
trueThari

Reputation: 135

Endless while loop when input a string to a variable that expected integer value

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?

Upvotes: 3

Views: 1066

Answers (2)

ryyker
ryyker

Reputation: 23208

"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;
}

Upvotes: 1

Vlad from Moscow
Vlad from Moscow

Reputation: 310930

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.

Upvotes: 1

Related Questions