我了解到可以像这样清空输入缓冲区:
while((ch = getchar()) != EOF && ch != 'n');
if (ch == EOF) {
// oops
}
那么为什么我不能用以下行清空一个字符来清空缓冲区:
c = getchar();
此行将导致程序等待用户输入。上下文:
void strfuncs()
{
char name[50] = {0};
char lastname[50] = {0};
char c;
printf("Enter name...:");
fgets(name, 50, stdin);
printf("Enter last name...:");
fgets(lastname, 50, stdin);
c=getchar();
printf("Enter a character...:");
fgets(&c, 1, stdin);
printf("c: %c",c);
}
c = getchar();
如果有缓冲区,这确实会清空一个字符的缓冲区。但是,考虑到人类键入相对于计算机运行速度的速度,当执行该行时,缓冲区很可能为空。如果缓冲区为空getchar
将等到它不为空。
while((ch = getchar()) != EOF && ch != 'n');
以上也不例外。大多数情况下,计算机将在getchar
内等待缓冲区变为非空。
在正常模式下,当标准输入来自终端时,操作系统仅在收到换行符时将字符发送到程序的输入缓冲区,或者如果用户键入ctrl-D
(在 *nixes 上,不确定 Windows 上的等效字符是什么)。循环实际上会在第一getchar()
阻塞,直到您键入整行并按回车键。然后,它将尽可能快地循环旋转,消耗您键入的所有字符。这一切都发生在您按下回车键后。
char c; // <<<< Wrong!
c = getchar();
这与问题无关,但getchar()
的类型int
.这很重要,因为EOF
需要与可以输入的所有有效字符区分开来,并且在某些字符集中,char
的每个可能值(在所有现代通用实现中为 0 到 255 或 -128 到 127)都是有效字符。
这种清空输入流的习惯用法仅在输入流中有字符要读取时才有效;否则getchar()
将阻塞,等待输入。如果输入流中有字符,getchar()
将读取其中一个字符。
fgets()
函数保留换行符,因此在以这种方式获取一行输入后似乎没有必要清理输入流。但是,如果缓冲区不够大,则会留下字符。处理此问题的一种方法是检查输入缓冲区中的换行符,如果输入流不存在,则清理输入流。如果在输入缓冲区中找到换行符,通常会将其删除:
char buffer[1000];
puts("Enter a line:");
if (fgets(buffer, sizeof buffer, stdin) == NULL) {
perror("Error in fgets()");
exit(EXIT_FAILURE);
}
char *ch;
int c;
if ((ch = strchr(buffer, 'n')) == NULL) {
while ((c = getchar()) != 'n' && c != EOF) {
continue;
}
} else {
*ch = ' ';
}
请注意,应使用int
变量来接收getchar()
返回的值,以确保正确处理EOF
。