清空键盘缓冲区很多种方法,如用fflush(stdin); rewind(stdin);setbuf(stdin, NULL);前两者仅对windows有用,最后一个则对Linux系统也适用。那么为什么需要清空键盘缓冲区呢?
以下几个实例:
Sample one
01#include
02
03int main(void)
04{
05char ch1;
06char ch2;
07
08ch1 = getchar();
09ch2 = getchar();
10printf("%d %d", ch1, ch2);
11return 0;
12}
程序的本意很简单,就是从键盘读入两个字符,然后打印出这两个字符的ASCII码值。可是执行程序后会发现出了问题:当从键盘输入一个字符后,就打印出了结果,根本就没有输入第二个字符程序就结束了。例如用户输入字符’a’, 打印结果是97,10。这是为什么呢?
【分析】:
scanf()和getchar()函数是从输入流缓冲区中读取值的,而并非从键盘(也就是终端)缓冲区读取。而读取时遇到回车(n)而结束的,这个n会一起读入输入流缓冲区的,所以第一次接受输入时取走字符后会留下字符n,这样第二次的读入函数直接从缓冲区中把n取走了,显然读取成功了,所以不会再从终端读取!其实这里的10恰好是回车符!这就是为什么这个程序只执行了一次输入操作就结束的原因!
【解决办法】:
清空缓冲区的残留数据。
使用 fflush(stdin); 或 rewind(stdin); 均可起到清空键盘缓冲区的作用,这两个函数均包含在stdio.h这个头文件中
修正后的写法:
Sample two
01
05
06#include
07
08int main()
09{
10char ch1;
11char ch2;
12
13scanf("%c", &ch1);
14printf("ch1 = %d", ch1);
15
16fflush(stdin);
17
18scanf("%c", &ch2);
19printf("ch2 = %d", ch2);
20return 0;
21}
上面的实例只适用于Windows系统,在Linux环境下上面两种写法都是不起作用的,所以还要换个函数。
Sample three
01
07
08#include
09
10int main()
11{
12char ch1;
13char ch2;
14
15scanf("%c", &ch1);
16printf("ch1 = %d", ch1);
17
18setbuf(stdin, NULL);
19
20scanf("%c", &ch2);
21printf("ch2 = %d", ch2);
22return 0;
23}
gets
在前面从键盘输入字符串是使用 scanf 和 %s。其实还有更简单的方法,即使用 gets() 函数。该函数的原型为:
include
char *gets(char *str);
这个函数很简单,只有一个参数。参数类型为 char* 型,即 str 可以是一个字符指针变量名,也可以是一个字符数组名。
gets() 函数的功能是从输入缓冲区中读取一个字符串存储到字符指针变量 str 所指向的内存空间。
下面将前面中使用 scanf 输入字符串的程序改一下:
# include
int main(void)
{
char str[20] = "\0"; //字符数组初始化\0
printf("请输入字符串:");
gets(str);
printf("%s\n", str);
return 0;
}
输出结果是:
请输入字符串:i love you
i love you
可见,gets() 函数不仅比 scanf 简洁,而且,就算输入的字符串中有空格也可以直接输入,不用像 scanf 那样要定义多个字符数组。也就是说:
gets(str);
完全可以取代:
scanf("%s", string);
不仅代码更简洁,而且可以直接输入带空格的字符串。同样,前面章节中,对字符指针变量所指向的内存单元进行初始化也可以用 gets(),下面将那个程序也改一下,将 scanf 换成 gets():
# include
int main(void)
{
char str[30];
char *string = str; //一定要先将指针变量初始化
printf("请输入字符串:");
gets(string); //也可以写成gets(str);
printf("%s\n", string); //输出参数是已经定义好的“指针变量名”
return 0;
}
输出结果是:
请输入字符串:Hi i…like you
Hi i…like you
此外,关于使用 gets() 函数需要注意:使用 gets() 时,系统会将最后“敲”的换行符从缓冲区中取出来,然后丢弃,所以缓冲区中不会遗留换行符。这就意味着,如果前面使用过 gets(),而后面又要从键盘给字符变量赋值的话就不需要吸收回车清空缓冲区了,因为缓冲区的回车已经被 gets() 取出来扔掉了。下面写一个程序验证一下:
# include
int main(void)
{
char str[30];
char ch;
printf("请输入字符串:");
gets(str);
printf("%s\n", str);
scanf("%c", &ch);
printf("ch = %c\n", ch);
return 0;
}
输出结果是:
请输入字符串:i love you
i love you
Y
ch = Y
我们看到,没有清空缓冲区照样可以输入’Y’,因为 gets() 已经将缓冲区中的回车取出来丢掉了。如果前面使用的不是 gets() 而是 scanf,那么通过键盘给 ch 赋值前就必须先使用 getchar() 清空缓冲区。
本文同步分享在 博客“瑞 新”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。