C: scanf for char not working as expected [duplica

2019-01-27 11:40发布

问题:

This question already has an answer here:

  • Scanf is not scanning %c character but skips the statement, why is that? 4 answers

I was recently running a c program in my PC. It have a for loop in which some char d is scanned. The for loop runs for 3 times. During each running it prints the the count of running and then scans the value of char d. The program is as follows

#include<stdio.h>

int main(){
    int f;
    char d;
    for(f=0;f<3;f++){
        printf("Choice %d\n", f);
        scanf("%c", &d);
    }
    return 0;
}

Now the trouble is that when I run the program, the for skips the scanf part when f is 1. Now if i changed the code as follows

#include<stdio.h>

int main(){
    int f;
    int d;
    for(f=0;f<3;f++){
        printf("Choice %d\n", f);
        scanf("%d", &d);
    }
    return 0;
}

Now the program works fine. and scanf is executed for every iteration of for loop.

What does seem to be the problem here? I mean when d is of type int it works fine, but when d is of type char it does not work correctly.

回答1:

You have to change

scanf("%c", &d);

to

scanf(" %c", &d);
       ^
       |

Otherwise, scanf() will consider the previously entered ENTER key press.

Note:

  1. ENTER key press generates a \n, which is a vaild input for %c format specifier. Adding a space before %c tells scanf() to ignore all leading whitespace-like inputs (including that previously stored \n) and read the first non-whitespace character from stdin.

  2. As for the case with %d format specifier, it consumes (and ignores) any leading whitespace-like inputs before scanning for numeric inputs, so the second case does not suffer any issues.



回答2:

The problem is that when you enter a character for scanf("%c", &d);, you press the enter key. The character is consumed by the scanf and the newline character stays in the standard input stream(stdin). When scanf(with %c) is called the next time, it sees the \n character in the stdin and consumes it, and thus does not wait for further input.

To fix it, change

scanf("%c", &d);

to

scanf(" %c", &d);
//    ^Note the space before %c

The space before the %c instructs scanf to scan any number of whitespace characters including none and stops scanning when it encounters a non-whitespace character. Quoting the standard:

7.21.6.2 The fscanf function

[...]

  1. A directive composed of white-space character(s) is executed by reading input up to the first non-white-space character (which remains unread), or until no more characters can be read. The directive never fails.

The reason that using %d worked is that the %d format specifier automatically skips whitespace characters and since \n is a whitespace character, %d does not scan it. Quoting the standard again:

7.21.6.2 The fscanf function

[...]

  1. Input white-space characters (as specified by the isspace function) are skipped, unless the specification includes a [, c, or n specifier. 284


标签: c char scanf