原因:
scanf %c
读取字符时, 不会跳过任何空白字符(包括空格、制表符等)!
起因: scanf 太常用了。问题也多。做一下记录。以后再随时补充。
问题1: while 循环里面多次执行?
#include <stdio.h>
void just_read() {
printf("Enter 3 characters:\n");
char what;
int row, col;
while (scanf("%c %d %d", &what, &row, &col) != EOF) {
// while 这里面执行了很2次。
printf("what=%c, row: %d, col: %d \n", what, row, col);
printf("\n\n");
}
}
int main(void) {
just_read();
return 0;
}
输出:
原因分析:
这段代码中的while
循环设计有问题,它会导致循环体执行两次的原因如下:
-
当用户输入三个字符时,
scanf
首先读取第一个字符(%c
),然后尝试读取接下来的两个整数(%d %d
)。但是,由于%c
读取字符时不会跳过任何空白字符(包括空格、制表符等),如果用户在输入字符后直接输入两个数字,scanf
会将第一个数字前的空白字符(如果有的话)也当作%c
的输入。 -
假设用户输入了
'a' 1 2
,scanf
会读取'a'
作为what
变量的值,然后尝试读取1
作为row
变量的值。但是,由于%c
在读取'a'
时没有跳过后面的空格,scanf
在尝试读取row
时会立即成功,因为空格被当作了%c
的输入,而没有触发scanf
的失败。 -
由于
scanf
在读取%c
后没有遇到任何错误,它会继续尝试读取%d %d
。这时,scanf
会读取1
和2
作为row
和col
的值。 -
因此,即使用户只输入了三个字符,
scanf
也会认为它成功读取了三个值(一个字符和两个数字),这导致while
循环条件scanf("%c %d %d", &what, &row, &col) != EOF
为真,循环体执行。 -
循环体执行后,
scanf
会再次尝试读取输入,但由于没有更多的输入,scanf
将返回EOF,循环结束。
解决办法:
要修复这个问题,你可以在%c
和%d %d
之间添加一个空格,以确保scanf
在读取字符后跳过任何空白字符。修改后的代码如下:
#include <stdio.h>
void just_read() {
printf("Enter 3 characters:\n");
char what;
int row, col;
while (scanf(" %c %d %d", &what, &row, &col) != EOF) { // 添加了一个空格
// while 现在应该只执行一次。
printf("what=%c, row: %d, col: %d \n", what, row, col);
printf("\n\n");
}
}
int main(void) {
just_read();
return 0;
}
现在就正常了。