使用fflush清空缓冲区

在看《C陷阱与缺陷》时候,看到如下代码:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  int i = 0;
  char c;
  for(i = 0; i < 5; i++)
  {
        scanf("%d", &c);
        printf("%d ", i);
  }
  printf("\n");
  system("PAUSE");   
  return 0;
}
    表面上看会输出0 1 2 3 4,可是测试的时候输出的却是1 0 2 0 3 0 a 1 2 3 4(红色字体为我输入的,以下相同)
    为什么?《C陷阱与缺陷》解释因为c的声名是char而不是int。当你令scanf()去读取一个整数时,它需要一个指向一个整数的指针。但这里它得到的是一个字符的指针。但scanf()并不知道它没有得到它所需要的:它将输入看作是一个指向整数的指针并将一个整数存贮到那里。由于整数占用比字符更多的内存,这样做会影响到c附近的内存。c附近确切是什么是编译器的事;在这种情况下这有可能是i的低位。因此,每当向c中读入一个值,i就被置零。当程序最后到达文件结尾时,scanf()不再尝试向c中放入新值,i才可以正常地增长,直到循环结束。

然后我又把这个程序稍微修改了下:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  int i = 0;
  char c;
  for(i = 0; i < 5; i++)
  {
        scanf("%c", &c);
        printf("%d ", i);
  }
  printf("\n");
  system("PAUSE");   
  return 0;
}
测试时结果如下:a 0 1 b 2 3c 4
刚开始我是很吃惊,我以为结果会是a 0 b 1 c 2 d 3 e 4的情形。仔细考虑下,输入字母后,字母会停留在缓冲区,因为缓冲区有数据,所以scanf函数不会等待用会输入数据,而是直接读取缓存区的数据。对于为什么每次输出两个数字后提示我输入字母,这个问题还没想清楚,可能与编译器有关吧。

于是我又修改了这个程序,在sacnf之前fflush了一把:
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  int i = 0;
  char c;
  for(i = 0; i < 5; i++)
  {
        fflush(stdin);
        scanf("%c", &c);
        printf("%d ", i);
  }
  printf("\n");
  system("PAUSE");   
  return 0;
}
结果是a 0 b 1c 2d 3 e 4(这下正常了,呵呵)

最后,说下fflush(),
并非所有的编译器都可以使用这个函数(gcc 就不支持),这个函数的移植性不好。

我们可以自己写代码来实现缓冲区的清空:
#include <stdio.h>
#include <stdlib.h>

int main( void )
{
     int i, c;
     for ( ; ; )
     {
          scanf("%d", &i);

          if ( feof(stdin) || ferror(stdin) )
          {
                break;
          }
         //没有发生错误,清空输入流。                
         //通过 while 循环把输入流中的余留数据“吃”掉
          while ( (c = getchar()) != '\n' && c != EOF ) ;
          //使用 scanf("%*[^\n]"); 也可以清空输入流,
          //不过会残留 \n 字符。                       
               printf("%d\n", i);
       }
       printf("\n");
       system("PAUSE");  
       return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值