Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.5k views
in Technique[技术] by (71.8m points)

c - scanf not working on invalid input

On a character input in the first scanf(), the second one doesn't run. getchar() isn't working either for Try Again input. It skips to take input for Would you like to play again? (Y/N)? It seems that your_choice is supposed to take the character and check it afterward but the character is actually being taken by ch. What is causing it to work like this and how to resolve the issue. I've tried re-initializing the variables but doesn't work.

#include <stdio.h>

void choice(int);

int main() {
    char ch;
    int random, your_choice;

    do {
        srand(time(NULL));
        system("cls");
        printf("** 0 is for Rock **
");
        printf("** 1 is for Scissors **
");
        printf("** 2 is for Lizard **
");
        printf("** 3 is for Paper **
");
        printf("** 4 is for Spock **
");

        printf("
Enter your choice here:");
        scanf("%d", &your_choice);

        random = rand() % 5; //random number between 0 & 4
        if ((your_choice >= 0) && (your_choice <= 4)) {
            //choice printer omitted for this post

            if ((random == ((your_choice + 1) % 5)) || (random == ((your_choice + 2) % 5)))
                printf("

... and you win!!!
");
            else if ((random == ((your_choice + 3) % 5)) || (random == ((your_choice + 4) % 5)))
                printf("

... and you lose!!!
");
            else if (random == your_choice)
                printf("

Unfortunately, it's a tie!
");
        } else
            printf("
Well, this is wrong! Try again with a number from 0 to 4!!
");

        printf("
Would you like to play again? (Y/N)?: ");
        scanf(" %c", &ch);

    } while (ch == 'y' || ch == 'Y');

    return 0;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If the user enters characters that cannot be converted to a number, scanf("%d", &your_choice); returns 0 and your_choice is left unmodified, so it is uninitialized. The behavior is undefined.

You should test for this and skip the offending input this way:

    if (scanf("%d", &your_choice) != 1) {
        int c;
        /* read and ignore the rest of the line */
        while ((c = getchar()) != EOF && c != '
')
            continue;
        if (c == EOF) {
            /* premature end of file */
            return 1;
        }
        your_choice = -1;
    }

Explanation:

  • scanf() returns the number of successful conversions. If the user types a number, it is converted and stored into your_choice and scanf() returns 1, if the user enters something that is not a number, such as AA, scanf() leaves the offending input in the standard input buffer and returns 0, finally if the end of file is reached (the user types ^Z enter in windows or ^D in unix), scanf() returns EOF.

  • if the input was not converted to a number, we enter the body of the if statement: input is consumed one byte at a time with getchar(), until either the end of file or a linefeed is read.

  • if getchar() returned EOF, we have read the entire input stream, no need to prompt the user for more input, you might want to output an error message before returning an error code.

  • otherwise, set your_choice to -1, an invalid value so the read of the code complains and prompts for further input.

Reading and discarding the offending input is necessary: if you do not do that, the next input statement scanf(" %c", &ch); would read the first character of the offending input instead of waiting for user input in response to the Would you like to play again? (Y/N)?: prompt. This is the explanation for the behavior you observe.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...