这段代码是我正在处理的大型项目的简化,它在一个简单的例子中总结了这个问题。我从用户获取输入,他们的名字,然后从任何不适合C字符串的输入中清除缓冲区。问题是输入名称后,用户必须按两次输入以使程序响应,并且因为我使用getchar()来刷新缓冲区,所以我创建的循环逻辑中只有一个明显的误解。如何防止用户输入两次,换句话说我错过了什么?谢谢!
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#define BUFFSIZE 10
int main(void)
{
unsigned char name[BUFFSIZE];
printf("ENTER YOUR NAME: ");
fgets(name, BUFFSIZE, stdin);
name[strcspn(name, "\n")] = '\0';
//flush the input buffer
int flush;
while (flush = getchar() != '\n' && flush != EOF);
printf("Your name is: %s!\n ", name);
printf("Press enter to continue...");
getchar();
return 0;
}
答案 0 :(得分:1)
首先,如果没有余数,则不应使用该行的其余部分,否则将跳过另一行。其次,赋值的优先级低于大多数操作,这意味着flush =
在执行后评估
getchar() != '\n' && flush != EOF
。
在比较分配结果时,应加上明确的括号:
flush = getchar() != '\n'
至(flush = getchar()) != '\n'
或者,可以将分配移到条件之外,见下文。
以下编辑使用strlen
来获取最终字符,并将分配移动到循环中。
#include <stdio.h>
#include <string.h>
#define BUFFSIZE 10
int main(int argc, char *argv[])
{
char name[BUFFSIZE];
size_t len;
int c;
printf("ENTER YOUR NAME: ");
fgets(name, BUFFSIZE, stdin);
len = strlen(name);
if (name[len - 1] == '\n')
name[len - 1] = '\0';
else
do
c = getchar();
while (c != '\n' && c != EOF);
printf("Your name is: %s!\n ", name);
printf("Press enter to continue...");
getchar();
return 0;
}
答案 1 :(得分:1)
你的程序中的问题是你不区分这两种情况:a)用户的输入适合缓冲区而b)输入不适合。这些情况的区别在于缓冲区中是否存在换行符。当您覆盖该字符时,该信息将被销毁:
fgets(name, BUFFSIZE, stdin);
name[strcspn(name, "\n")] = '\0';
我们需要的是:
size_t nlcspn = strcspn(name, "\n");
bool incomplete = name[nlcspn] == 0;
name[nlcspn] = 0;
现在我们要测试一个incomplete
标志。只有当此标志通知输入不包含换行符时,我们才能继续完成fgets
的“get line”操作,并使用一个小循环扫描,直到收到换行符。 (在这种情况下,一些错误恢复也可能是一个好主意,比如告知用户输入太长,并创建纠正错误的机会)。
需要注意的另一件事是fgets
返回一个应该检查的值。如果它返回空指针,则表示在消耗任何输入之前流已结束。问题是,在这种情况下,fgets
不会将任何内容放入数组中。该数组保留其先前的值(可能是先前读取的输入),或者由于未初始化的内容而保留的不确定值(“垃圾”)。
答案 2 :(得分:-2)
我只是在阅读你的代码时猜测错误就在这里:
while (flush = getchar() != '\n' && flush != EOF);
您需要getchar()
,直到输出缓冲区为&#39; \ n&#39;还是EOF,对吧?然后试试这个:
while (flush = getchar() != '\n' || flush != EOF);