简体   繁体   中英

Scanf taking incorrect input

This is the only block of code where scanf doesn't seem to pick up the entered values correctly. It always works as designed the very first time it executes the code. When it asks the second time (after executing newGame once) no matter what you type it always takes the value 1 and then on the second iteration of the infinite loop it works correctly. Using pointers didn't help like I thought it would.

Edit: updated the code for new readers, this doesn't work either

void newGame(void){
int option;
puts("Would you like to play a new game? 1: Yes 2: Return to the main menu");

while (1) {
    scanf("%d", &option);

    switch(option) {
        case 1: 
            newGame(); 
            break;
        case 2: 
            return;
        default: 
            printf("Invalid input %d!\n", option); 
            break;
    }
}

If I understand the observed misbehavior correctly, it manifests like this (for example):

  1. The function emits the prompt
  2. You type "1" and hit [enter]
  3. The function emits the prompt
  4. You type "2" and hit [enter]
  5. Nothing seems to happen
  6. You type "2" and hit [enter]
  7. Control passes to the next statement after the initial call to newGame()

At least, that's an observable behavior of the function presented. Interpreting that to describe the problem assumes that the "Nothing seems to happen" at (5) is what the question describes as "no matter what you type it always takes the value 1". I find it hard to reconcile those, but I assume that the code presented actually manifests the problem, so I have to somehow connect the claim to the actual behavior.

That particular behavior (having to type "2" twice or more to return to the main menu) arises from the recursive implementation of the function. It goes like this:

  • Control enters the function on the initial call to it.
  • The function prints the prompt.
  • The function enters the while loop, where:
    • it scans the user's choice (and will run into trouble either then or later if the user has entered anything non-numeric);
    • the user having entered "1", the function calls itself recursively, in which new execution it
      • prints the prompt,
      • enters the while loop,
      • scans the user's input ("2" this time),
      • returns from the recursive call .
    • (back in the top-level newGame() execution) the function reaches the bottom of the while loop and loops back to scan a new input (another "2" in the example session).
    • The function returns from the top-level execution of newGame() .

The simplest way to revise the code so that the user only needs to select option "2" once would be to add a return statement immediately after the recursive call to newGame() . The recursive call will not return until the user has chosen option "2", so there is no need to loop back for more input in that case.

But the best solution would be to structure the menu system to be non-recursive. In real-world programs, recursion is almost never the right answer. Even in this case, the recursive approach puts a (system dependent) limit on how many games can be played in a row before the program overflows its stack. That might be in the hundreds or perhaps even thousands, but there doesn't need to be any limit at all.

You need to check the return value of scanf to ensure that the input value was actually a number -- if it is not, scanf will return 0 and not read anything. It also might return EOF if an end-of-file is reached. So you want something like:

if (scanf("%d", &option) != 1) {
    if (feof(stdin)) {
        printf("Unexpected end of file");
        exit(0); }
    printf("Unexpected character %c in input", getchar());
    continue; }

in your while loop to read your number.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM