c--getchar() 清空缓存

getchar()

该函数的原型为:

# include <stdio.h>
int getchar(void);

功能是从缓冲区中读取一个字符。这个函数非常简单,连参数都没有,非常好用。下面用 scanf 给字符变量赋值和吸收回车的程序用 getchar() 修改一下:

 
  1. # include <stdio.h>
  2. int main(void)
  3. {
  4. int a;
  5. char ch;
  6. while (1)
  7. {
  8. printf("请输入一个数字:");
  9. scanf("%d", &a);
  10. printf("a = %d\n", a);
  11. printf("您想继续吗(Y/N):");
  12. getchar(); /*用getchar吸收回车, 简单、方便、好用, 都不需要定义变量用来存储获取的回车符*/
  13. ch = getchar(); //用getchar从缓冲区中读取一个字符赋给字符变量ch
  14. if (('Y' == ch) || ('y' == ch))
  15. {
  16. ;
  17. }
  18. else
  19. {
  20. break; // 跳出本层循环体
  21. }
  22. }
  23. return 0;
  24. }

输出结果是:
请输入一个数字:10
a = 10您想继续吗(Y/N):y
请输入一个数字:5
a = 5您想继续吗(Y/N):y
请输入一个数字:333
a = 333您想继续吗(Y/N):n

在程序中,“ch=getchar();”这句之前我们先用 getchar() 清空缓冲区,然后重新从键盘输入一个字符。同样,必须按回车 getchar() 才会进去取这个字符。这时候需要注意的是,同 scanf 一样,按的这个回车也会被遗留在缓冲区中,大家要注意。

这时有人会说,如果前面有多个 scanf 给 int 型变量赋值,那么每个 scanf 都会遗留一个回车,那这时是不是有几个 scanf 就要用几个 getchar() 呢?

回答是“不需要”,仍然只需要一个 getchar()!前面说过,当 scanf 用 %d 取缓冲区数据的时候,如果遇到空格、回车或 Tab 键就跳过去。不仅如此,这些被跳过去的空白符都被释放了。所以假如前面有三个 scanf 给 int 型变量赋值,那么第一个 scanf 输入回车后把回车遗留在了缓冲区,而第二个 scanf 取值时会越过第一个 scanf 遗留在缓冲区中的回车,那么这个回车就会从缓冲区中释放。但第二个 scanf 取完值后也在缓冲区中留下了一个回车,而当第三个 scanf 到缓冲区中取值时会跳过第二个 scanf 遗留的回车,这个回车同样也会从缓冲区中释放,所以归根结底最后缓冲区中只有一个回车,也就是说,缓冲区中永远不可能遗留多个回车。

下面来写一个程序验证一下:

 
  1. # include <stdio.h>
  2. int main(void)
  3. {
  4. int a, b, c, d;
  5. char ch;
  6. printf("请输入第一个数:");
  7. scanf("%d", &a);
  8. printf("请输入第二个数:");
  9. scanf("%d", &b);
  10. printf("请输入第三个数:");
  11. scanf("%d", &c);
  12. printf("您想继续吗(Y/N):");
  13. getchar(); //只需要用一个getchar吸收回车
  14. ch = getchar(); //用getchar获取一个字符赋给ch
  15. if (('Y' == ch) || ('y' == ch))
  16. {
  17. printf("请输入密码:");
  18. scanf("%d", &d);
  19. printf("恭喜成功获得密码%d\n", d);
  20. }
  21. return 0;
  22. }

输出结果是:
请输入第一个数:1
请输入第二个数:2
请输入第三个数:3
您想继续吗(Y/N):y
请输入密码:5678
恭喜成功获得密码5678

由此我们知道,当用 %d 获取输入流中的数据的时候,如果遇到字符(空格、回车、Tab 除外),则直接从输入流中退出来,什么都不取。但如果是用 %c 获取,那么任何数据都会被当作一个字符。所以如果你要从输入流中取一个字符,但在之前使用过 scanf,那么此时就必须要先用 getchar() 吸收回车。否则取到的将不是你想要的字符,而是 scanf 遗留在输入流中的回车。如果你要从输入流中取的不是字符,那就不需要用 getchar() 吸收回车了。

以上详细分析了什么时候需要吸收回车,什么时候不需要。但实际编程中,程序往往很长,我们很难预测到下一次到缓冲区中取数据的是 %d 还是 %c 或者是 gets()、fgets()。所以为了避免忘记吸收回车或耗费精力考虑回车的问题,习惯上 scanf 后面都加上 getchar()。

fflush(stdin)

前面介绍了使用 getchar() 吸收回车的方法,除此之外还有一个更强大、更直接的方法,就是直接将输入缓冲区全部清空。

清空缓冲区只需加一句 fflush(stdin) 即可。fflush 是包含在文件 stdio.h 中的函数。stdin 是“标准输入”的意思。std 即 standard(标准),in 即 input(输入),合起来就是标准输入。fflush(stdin) 的功能是:清空输入缓冲区。下面将前面的一个程序修改一下:

 
  1. # include <stdio.h>
  2. int main(void)
  3. {
  4. int a;
  5. char i;
  6. while (1)
  7. {
  8. printf("请输入一个数字:");
  9. scanf("%d", &a); //因为读取的是数字, 所以不需要清空缓冲区
  10. printf("a = %d\n", a);
  11. printf("您想继续吗, Y想, N不想:");
  12. fflush(stdin);
  13. scanf("%c", &i);
  14. if ('Y'==i || 'y'==i)
  15. {
  16. ;
  17. }
  18. else
  19. {
  20. break; // 跳出本层循环体
  21. }
  22. }
  23. return 0;
  24. }

输出结果是:
请输入一个数字:10safa
a = 10
您想继续吗, Y想, N不想:Y
请输入一个数字:58jlkj\*&**^
a = 58
您想继续吗, Y想, N不想:N

fflush 一般用于清除用户前面遗留的垃圾数据,提高代码的健壮性。因为如果是自己编程的话,一般都会按要求输入。但对于用户而言,难免会有一些误操作,多输入了一些其他没有用的字符,如果程序中不对此进行处理的话可能会导致程序瘫痪。所以编程时一定要考虑到各种情况,提高代码的健壮性和容错性。使用 fflush 就可以将用户输入的垃圾数据全部清除。

但是 fflush 有一个问题,就是可移植性。并不是所有的编译器都支持 fflush,比如 gcc 就不支持。那么此时怎么办?还是用 getchar()。

getchar()的高级用法

while (getchar() != '\n');

这种用法其实在前面也使用过,它可以完全代替 fflush(stdion) 来清空缓冲区。不管用户输入多少个没用的字符,他最后都得按回车,而且只能按一次。只要他按回车那么回车之前的字符就都会被 getchar() 取出来。只要 getchar() 取出来的不是回车 ('\n') 那么就会一直取,直到将用户输入的垃圾字符全部取完为止。q

  • 16
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值