• 技术文章 >后端开发 >C#.Net教程

    使用C语言怎样清空输入缓冲区?这里有多种方法值得借鉴

    php是最好的语言php是最好的语言2018-08-01 11:46:59原创1127
    C语言中有几个基本输入函数:

    //获取字符系列
    int fgetc(FILE *stream);
    int getc(FILE *stream);
    int getchar(void);
    //获取行系列
    char *fgets(char * restrict s, int n, FILE * restrict stream);
    char *gets(char *s);//可能导致溢出,用fgets代替之。
    //格式化输入系列
    int fscanf(FILE * restrict stream, const char * restrict format, …);
    int scanf(const char * restrict format, …);
    int sscanf(const char * restrict str, const char * restrict format, …);

    这里仅讨论输入函数在标准输入(stdin)情况下的使用。纵观上述各输入函数,

    MINGW 4.4.3中FILE结构体源码

      _iobuf
    {
    	char*	_ptr;//指向当前缓冲区读取位置
    	int	_cnt;//缓冲区中剩余数据长度
    	char*	_base;
    	int	_flag;
    	int	_file;
    	int	_charbuf;
    	int	_bufsiz;
    	char*	_tmpfname;
    } FILE;

    各编译器实现可能不一样,这里获取字符系列函数只用到_ptr和_cnt。

    MINGW 4.4.3中getchar()实现

    __CRT_INLINE int __cdecl __MINGW_NOTHROW getchar (void)
    {
      return (--stdin->_cnt >= 0)
        ?  (int) (unsigned char) *stdin->_ptr++
        : _filbuf (stdin);
    }

    其中stdin为FILE指针类型,在MINGW 4.4.3中,getc()和getchar()实现为内联函数,fgetc()实现为函数。顺便说一句,C99标准中已经加入对内联函数的支持了。

    =================分 割 线=================

    提到缓冲区,就不得不提setbufsetvbuf两个缓冲区设置函数,其声明如下:

     setbuf(FILE * restrict stream,  * restrict buf);
    int setvbuf(FILE * restrict stream, char * restrict buf, int mode, size_t size);

    setvbuf的mode参数有:

    setbuf(stream, buf);在:

    注:BUFSIZ宏在stdio.h中定义。

    这里还要提一下传说中的setbuf经典错误,在《C陷阱和缺陷》上有提到:

     main()
    {
        int c;
        char buf[BUFSIZ];

        setbuf(stdout,buf);
        while((c = getchar()) != EOF)
            putchar(c);
        
        return 0;
    }

    问题是这样的:程序交回控制给操作系统之前C运行库必须进行清理工作,其中一部分是刷新输出缓冲,但是此时main函数已经运行完毕,buf缓冲区作用域在main函数中,此时buf字符数组已经释放,导致输出诡异乱码。

    解决方案:可以将buf设置为static,或者全局变量,或者调用malloc来动态申请内存。

    =================分 割 线=================

    下面来看看几种流行的缓冲区清空方法:

    由C99标准文档中:

    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.

    可以看出fflush对输入流为参数的行为并未定义。但由MSDN上的fflush定义:

    If the file associated with stream is open for output, fflush writes to that file the
    contents of the buffer associated with the stream. If the stream is open for input,
    fflush clears the contents of the buffer.

    可以看出fflush(stdin)在VC上还是有效地!鉴于各编译器对fflush的未定义行为实现不一样,不推荐使用fflush(stdin)刷新输入缓冲区。

    由前面对setbuf函数的介绍,可以得知,setbuf(stdin, NULL);是使stdin输入流由默认缓冲区转为无缓冲区。都没有缓冲区了,当然缓冲区数据残留问题会解决。但这并不是我们想要的。

    这里用到了scanf格式化符中的“*”,即赋值屏蔽;“%[^集合]”,匹配不在集合中的任意字符序列。这也带来个问题,缓冲区中的换行符’\n’会留下来,需要额外操作来单独丢弃换行符。

     c;
    while((c = getchar()) != '\n' && c != EOF);

    由代码知,不停地使用getchar()获取缓冲区中字符,直到获取的字符c是换行符’\n’或者是文件结尾符EOF为止。这个方法可以完美清除输入缓冲区,并且具备可移植性。

    相关文章:

    禁止页面缓存的方法 多语言下禁止页面缓存

    如何批量清理系统临时文件(语言:C#、 C/C++、 php 、python 、java )

    相关视频:

    C 语言教程

    以上就是使用C语言怎样清空输入缓冲区?这里有多种方法值得借鉴的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:方法 语言
    上一篇:【C++】深入了解继承方式基础知识及其与访问限定符的关系 下一篇:C++11新特性- 纯虚函数和final说明符的用法
    PHP编程就业班

    相关文章推荐

    • 分享一道逻辑面试题,看看你能答对吗!• c语言中形参的缺省存储类别是什么• C++设计模式浅识装饰模式• SUNWEN教程之----C#进阶(五)• C#基础知识整理:基础知识(11) 值类型,引用类型

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网