在致电scanf("%d", &variable);
后,我们会在 stdin 处挂一个换行符,该换行符应在拨打fgets
之前清除,否则我们最终会将其输入换行并使其过早返回。
我发现答案建议在第一次拨打scanf("%*[^\n]%*c");
之后使用scanf
来丢弃换行符,而其他人建议使用scanf("%*[^\n]\n");
。从理论上讲,两者都应该有效:第一个会消耗所有非换行符(但不包括换行符本身),然后消耗完全一个字符(换行符)。第二个将消耗不是换行符(不包括它)的所有内容,然后\n
(空白字符)将指示scanf
读取每个空格字符直到第一个非空白字符。 / p>
然而,尽管我看起来这些方法在某些答案中起作用,但我无法让他们在这里工作(下面的代码)。
为什么scanf
方法都不起作用?
测试:
Ubuntu Linux - gcc
5.4.0
scanf("%*[^\n]\n");
方法:#include <stdio.h>
int main(int argc, char **argv){
int number;
char buffer[1024];
printf("Write number: \n");
scanf("%d", &number);
//Clearing stdin?
scanf("%*[^\n]\n");
printf("Write phrase: \n");
fgets(buffer, 1024, stdin);
printf("\n\nYou wrote:%u and \"%s\"\n", number, buffer);
return 0;
}
$ ./bug
Write number:
2
Write phrase:
You wrote:2 and "
"
scanf("%*[^\n]%*c");
方法:#include <stdio.h>
int main(int argc, char **argv){
int number;
char buffer[1024];
printf("Write number: \n");
scanf("%d", &number);
//Clearing stdin?
scanf("%*[^\n]%*c");
printf("Write phrase: \n");
fgets(buffer, 1024, stdin);
printf("\n\nYou wrote:%u and \"%s\"\n", number, buffer);
return 0;
}
$ ./bug2
Write number:
3
Write phrase:
You wrote:3 and "
"
以下方法是唯一按预期方式运作的方法:
#include <stdio.h>
int main(int argc, char **argv){
int number;
char buffer[1024];
printf("Write number: \n");
scanf("%d", &number);
//Clearing stdin!
int c;
while((c = getchar()) != '\n' && c != EOF){
//Discard up to (and including) newline
}
printf("Write phrase: \n");
fgets(buffer, 1024, stdin);
printf("\n\nYou wrote:%u and \"%s\"\n", number, buffer);
return 0;
}
$ ./notbug
Write number:
4
Write phrase:
phrase :D
You wrote:4 and "phrase :D
"
答案 0 :(得分:3)
基本问题是scanf模式%[^\n]
匹配 ONE OR MORE 不是换行符的字符。因此,如果下一个字符 是换行符,则该模式将失败并且scanf
将立即返回而不会读取任何内容。添加*
不会更改该基本事实。事实证明,只有一次通话你无法做到这一点,你需要两个:
scanf("%*[^\n]"); scanf("%*c");
请注意,将裸线换入扫描模式几乎总是没用 - 它会导致scanf读取并丢弃所有空格,直到它看到非空白字符(将留在输入缓冲区中)。特别是如果您尝试在交互式程序中使用它,它将一直挂起,直到您输入非空白行。