1. fflush()失效问题:fflush(stdin)是未定义行为,该函数用于输出流,即fflush(stdout) 。 用rewind(stdin)代替刷新输入缓冲区。
2. 参考文章:https://blog.csdn.net/qq_40843865/article/details/81072212
3.关于C++的清空缓冲区的方法:https://www.cnblogs.com/youngforever/articles/3125860.html
清空缓冲区
C++清空缓冲区:
法一:以下语句在 cin 输入之前调用,用于清理输入时,残留在输入缓冲区的字符。
cin.clear() // 是用来更改cin的状态标示符的。
cin.sync() // 是用来清除缓存区的数据流的。
法二:
cin.ignore( numeric_limits<streamsize>::max(), '\n' );
//cin.ignore(1024, '\n'),通常把第一个参数设置得足够大,这样实际上总是只有第二个参数'\n'起作用,
//这一句就是把回车(包括回车)之前的所以字符从输入缓冲(流)中清除出去。
C语言清空(输入)缓冲区:
- rewind(stdin); 仅windows下生效
- while((getchar())!=EOF); 清除所有内容
- setbuf(stdin, NULL); 关闭缓冲区
对于 _getch() 无回显有效
//控制台清空缓冲区
FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));
在循环中读取单个字符时,需要考虑过滤回车的问题。
例如:我们循环5次,分别被输入 h e l l o. 预期输出也是这5个字母。
while (1)
{
ch1 = getchar(); //无回显,控制台
printf("ch1 = %d , ch1 = %c\n", ch1, ch1);
}
然而结果却与预期不符,应为我们没有考虑到过滤每次输入后的回车符。
这里有几种过滤回车的方法。(回车符本质是一个字符,使用一个变量将其接收即可)
法一:额外接收一个字符,去除残留在输入缓冲区的 \n
缺点,必须严格按照一个输入一个回车,一旦多敲一个回车,ch1将不能收到正常的结果。
ch1 = getchar();
getchar(); // 过滤回车
解决方案:使用多个候选变量,一个候选变量存储输入的字符时,另一个为回车。
ch1 = getchar(); // 候选变量1
ch2 = getchar(); // 候选变量2
if (ch1 != '\n' || ch2 != '\n') // 任意一个候选变量得到字符
{
if (ch1 == '\n') // 确保ch1得到字符
{
ch1 = ch2;
}
// 注意这的输出,代表的是永远可以确定ch1为有效输入字符
printf("ch1 = %d , ch1 = %c\n", ch1, ch1);
}
注意:因为getchar() 一次只能得到一个字符,因此我们一次输入多个的时候,与预期不符。这里可以使用while替代if判断,只要有正确的输入,我们就替换到ch1使用。
ch1 = getchar();
ch2 = getchar();
while (ch1 != '\n' || ch2 != '\n') // 任意一个得到字符
{
if (ch1 == '\n')
{
swap(ch1, ch2);
}
printf("ch1 = %d , ch1 = %c\n", ch1, ch1);
// ... ch1使用过后置为 '\n'
ch1 = '\n';
}
法二:清空缓冲区
在输入前清空缓冲区内残留的数据
ch1 = getchar();
scanf("%*[^\n]"); scanf("%*c");
//while ((c = getchar()) != '\n' && c != EOF); // 等价
//rewind(stdin); // 刷新输入缓冲区,仅windows下生效
//setbuf(stdin, NULL); // 关闭输入缓冲区
缺点是无法一次输入多个。
法三:使用scanf输入
scanf支持 %*c 过滤字符。缺点:同样不能多输入一个回车,否则会混乱。
while (1)
{
scanf("%c%*c", &ch1);
printf("ch1 = %d , ch1 = %c\n", ch1, ch1);
}
解决方案:读取非回车字符(scnaf支持使用[]
选择字符集合)
while (1)
{
scanf("%[^\n]c", &ch1); // 只接收非回车字符
getchar(); // 过滤回车
printf("ch1 = %d , ch1 = %c\n", ch1, ch1);
}
改进:检查scanf读取到了字符,再进行输出。
while (1)
{
if (scanf("%[^\n]c", &ch1) > 0)
{
printf("ch1 = %d , ch1 = %c\n", ch1, ch1);
}
getchar();
}
缺点是不支持连续输入。
法四:输入到字符串中,每次取一个。
char str[100];
while (1)
{
scanf("%s", str);
int n = strlen(str);
for (int i = 0; i < n; ++i)
{
printf("ch1 = %d , ch1 = %c\n", str[i], str[i]);
}
}
scanf("%c", &ch1); // 将回车存到ch1中
ch1 = getchar();
rewind(stdin); // 刷新输入缓冲区
setbuf(stdin, NULL); // 关闭输入缓冲区
scanf("%*[^\n]"); scanf("%*c"); // %* 可以过滤字符,该语句可以清空缓冲区中所有字符
while ((c = getchar()) != '\n' && c != EOF); // 同理,清除换冲过去所有字符
/// C++
// 1.
// cin.clear();
// cin.sync();
// 2.
//cin.ignore( numeric_limits<streamsize>::max(), '\n' );
// cin.ignore(1024, '\n'),通常把第一个参数设置得足够大,这样实际上总是只有第二个参数'\n'起作用,
//所以这一句就是把回车(包括回车)之前的所以字符从输入缓冲(流)中清除出去。
// 3.对于 _getch() 无回显有效
//控制台清空缓冲区 FlushConsoleInputBuffer(GetStdHandle(STD_INPUT_HANDLE));