Chinaunix首页 | 论坛 | 博客
  • 博客访问: 343723
  • 博文数量: 60
  • 博客积分: 1570
  • 博客等级: 上尉
  • 技术积分: 620
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-02 23:37
文章分类

全部博文(60)

文章存档

2012年(2)

2010年(2)

2009年(56)

分类: LINUX

2009-11-08 15:29:54

如何清除stdin缓存中的数据?

一。这问题没有什么很标准的做法:
方法1、fflush(): VC上面使用fflush()可以成功, 而在gcc上面使用fflush()却不能成功。
方法2、setbuf(): 虽然在gcc上面,使用这种方式确实可以清空输入流. 但不建议使用
方法3、通过 while 循环把输入流中的余留数据“吃”掉:
        int c;
        while ((c=getchar()) != '\n' && c != EOF);


        /*可直接将这2句代码当成fflush(stdin)的替代,直接运行可清除输入缓存流*/

二。解释:

1. fflush()不行的原因如下:

C-FAQ中如下:
Question 12.26
How can I flush pending input so that a user's typeahead isn't read at the next prompt? Will fflush(stdin) work?

--------------------------------------------------------------------------------
fflush is defined only for output streams. Since its definition of ``flush'' is to complete the writing of buffered characters (not to discard them), discarding unread input would not be an analogous meaning for fflush on input streams.

There is no standard way to discard unread characters from a stdio input stream, nor would such a way be sufficient unread characters can also accumulate in other, OS-level input buffers.

C标准(ISO/IEC 9899:1999 standard)规定fflush(stdin)操作是未定义的<参看《ISO/IEC 9899:1999 standard》p270>;。也就是说不一定能实现刷新功能,但有的编译器可能不遵循标准,对fflush(stdin)操作不予警告,并且有时可能产生正确的结果,但最好不要这样使用。

VC上面使用fflush()可以成功, 而在gcc上面使用fflush()却不能成功。


以下是 C99 对 fflush 函数的定义:

int fflush(FILE *stream);
如果 stream 指向输出流或者更新流(update stream),
并且这个更新流最近执行的操作不是输入,
那么 fflush 函数将把这个流中任何待写数据传送至宿主环境(host environment)写入文件
否则,它的行为是未定义的。

原文如下:
int fflush(FILE *stream);
If stream points to an output stream or an update stream in which
the most recent operation was not input, the fflush function causes
any unwritten data for that stream to be delivered to the host environment
to be written to the file; otherwise, the behavior is undefined.

其中,宿主环境可以理解为操作系统或内核等。

由此可知,如果 stream 指向输入流(如 stdin),那么 fflush 函数的行为是不确定的。故而使用 fflush(stdin)   是不正确的,至少是移植性不好的。

2.
setbuf()的方法也是不符合标准的. 虽然在有些场合它通过将输入设置为无缓冲形式, 以此来刷新输入流, 但是不太可靠。
虽然在gcc上面,使用这种方式确实可以清空输入流. 但不建议使用.

三。示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void pr_buf(char *buf)
{
        int len;
        len = strlen(buf);

        if (buf[len - 1] == '\n')
                printf("buf = %s", buf);
        else
                printf("buf = %s\n", buf);
}

int main(int argc, char *argv[])
{
        char buf[5] = {0};

        fgets(buf, sizeof(buf), stdin);
        pr_buf(buf);
 

        /*这2句代码为fflush(stdin)的替代,直接运行可清除输入缓存流*/
        int c;
        while ((c=getchar()) != '\n' && c != EOF);

        fgets(buf, sizeof(buf), stdin);
        pr_buf(buf);

        exit(0);
}

 


参考文章:

%D4%C6%D2%A3/blog/item/fe72660005979f16728b6588.html


 

阅读(1558) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~