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

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)情况下的使用。纵观上述各输入函数,

获取字符系列的的前三个函数fgetc、getc、getchar。以getchar为例,将在stdin缓冲区为空时,等待输入,直到回车换行时函数返回。若stdin缓冲区不为空,getchar直接返回。getchar返回时从缓冲区中取出一个字符,并将其转换为int,返回此int值。

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()实现

立即学习“C语言免费学习笔记(深入)”;

__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标准中已经加入对内联函数的支持了。

获取行系列的fgets和gets,其中由于gets无法确定缓冲区大小,常导致溢出情况,这里不推荐也不讨论gets函数。对于fgets函数,每次敲入回车,fgets即返回。fgets成功返回时,将输入缓冲区中的数据连换行符’\n’一起拷贝到第一个参数所指向的空间中。若输入数据超过缓冲区长度,fgets会截取数据到前n-1(n为fgets第二个参数,为第一个参数指向空间的长度),然后在末尾加入’\n’。因此fgets是安全的。通常用fgets(buf, BUF_LEN, stdin);代替gets(buf);。

格式化输入系列中,fscanf从文件流进行格式化输入很不好用。常用的还是scanf,格式化输入系列函数舍去输入数据(根据函数不同可能是标准输入也可能是字符串输入,如:sscanf)前的空白字符(空格、制表符、换行符)直至遇到非空白字符,然后根据格式参数尝试对非空白字符及后续字符进行解析。该系列函数返回成功解析赋值的变量数,若遇文件尾或错误,返回EOF。

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

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

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

setvbuf的mode参数有:

_IOFBF(满缓冲):缓冲区空时读入数据;缓冲区满时向流写入数据。

_IOLBF(行缓冲):每次从流读入一行数据或向流写入数据。如:stdio,stdout

_IONBF(无缓冲):直接从流读入数据,或者直接向流写入数据,而没有缓冲区。如:stderr

setbuf(stream, buf);在:

buf == NULL:等价于(void)setvbuf(stream, NULL, _IONBF, 0);

buf指向长度为BUFSIZ的缓冲区:等价于(void)setvbuf(stream, buf, _IOFBF, BUFSIZ);

注: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来动态申请内存。

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

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

fflush(stdin);式

由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(stdin, NULL);式

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

scanf(“%*[^\n]”);式(《C语言程序设计 现代方法 第二版》中提到)

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

经典式

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

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

相关文章:

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

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

相关视频:

C 语言教程

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1432805.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月17日 08:37:32
下一篇 2025年12月14日 03:57:51

相关推荐

  • .net WINFORM的GDI双缓冲的实现方法_实用技巧

    下面小编就为大家分享一篇.net winform的gdi双缓冲的实现方法,具有很好的参考价值,希望对大家学习.net有所帮助。对.net感兴趣的小伙伴们一起跟随小编过来看看吧 有时候在窗体中执行不断的GDI+操作的时候会出现闪速的状况,除了修改窗体的参数,更应该解决刷新本身的问题,双缓冲可能就是这样…

    好文分享 2025年12月17日
    000
  • C#中实现复制与删除文件的方法

    这篇文章主要介绍了c# 复制与删除文件的实现方法的相关资料,希望通过本文能帮助到大家,让大家理解掌握这部分内容,需要的朋友可以参考下 C# 复制与删除文件的实现方法 1、首先是复制文件 首先打开我们的对话框获得文件路径,当然也可以直接编写路径 private void BtnAddFile_Clic…

    好文分享 2025年12月17日
    000
  • XML验证的基本方法有哪些?

    XML验证通过DTD、XSD和Schematron确保XML文档结构和数据符合预设规则。DTD语法简单但功能有限,适用于简单场景;XSD支持丰富数据类型和命名空间,是主流选择;Schematron用XPath表达复杂业务逻辑,补充XSD不足。选择时应根据需求:XSD适合大多数项目,DTD用于简单或遗…

    2025年12月17日
    000
  • 如何用python写2048

    答案:2048游戏核心是4×4网格合并数字,通过初始化、移动合并、随机生成数字和判断胜负实现。使用NumPy处理数组,命令行交互控制方向,每次移动后添加新数字,无法移动时结束游戏。 2048 是一个经典的滑动数字合并游戏,用 Python 实现它并不复杂。我们可以使用 NumPy 处理二维数组逻辑,…

    2025年12月14日
    000
  • pillow库的安装教程及步骤

    Pillow是一款Python图像处理库,它可以帮助我们进行各种图像处理操作。本文将详细介绍Pillow库的安装步骤和方法,并提供相应的代码示例。 一、安装Pillow库安装Pillow库非常简单,我们可以通过pip命令来进行安装。打开命令行终端,输入以下命令即可完成安装: pip install …

    2025年12月13日
    000
  • 使用pip安装whl文件的简单指南

    简明教程:利用pip安装whl文件的方法,需要具体代码示例 概述:在Python开发过程中,我们经常会用到各种第三方库。而pip是Python的官方包管理工具,它可以方便地下载、安装和管理各种Python包。通常情况下,我们可以使用pip install命令来安装第三方包,但当我们需要安装一个whl…

    2025年12月13日
    000
  • 分享NumPy库快捷有效的卸载技巧

    快速有效的NumPy库卸载方法分享,需要具体代码示例 NumPy是Python程序中广泛使用的一个科学计算库,它为Python提供了高性能的多维数组对象和相应的操作函数。然而,由于各种原因,有时候我们可能需要卸载NumPy库。本文将详细介绍如何快速有效地卸载NumPy库,并提供具体的代码示例。 首先…

    2025年12月13日
    000
  • 逐步指导如何卸载NumPy库

    一步步教你卸载NumPy库的方法,需要具体代码示例 NumPy是Python中非常流行和强大的数值计算库,广泛应用于科学计算、数据分析和机器学习等领域。然而,在某些情况下,我们可能需要卸载NumPy库,这可能是因为我们需要使用特定版本的库,或者需要清理系统中的旧版本。 本文将一步步教你如何卸载Num…

    2025年12月13日
    000
  • Python的dir()函数:查看对象的属性和方法

    Python的dir()函数:查看对象的属性和方法,需要具体代码示例 摘要:Python是一种强大而灵活的编程语言,其内置函数和工具为开发人员提供了许多方便的功能。其中一个非常有用的函数是dir()函数,它允许我们查看一个对象的属性和方法。本文将介绍dir()函数的用法,并通过具体的代码示例来演示其…

    2025年12月13日
    000
  • Python程序区分字符串的==运算符和__eq__()方法

    在 Python 中,比较运算符 (==) 和 equals() 方法在处理字符串时以不同的方式使用。为了区分 Python 中的 == 运算符和 equals 方法,我们必须将它们与字符串比较一起使用。当我们在数据分析和机器学习中使用字符串时,字符串比较广泛发生。在本文中,我们将了解在与字符串一起…

    2025年12月13日
    000
  • 快速祛除老年斑的有效方法(教你简单又快速消除老年斑的养肤秘诀)

    随着年龄的增长,老年斑通常出现在面部、颈部和手背等暴露部位,给人们的外貌带来困扰。它是一种常见的皮肤问题,让人看起来显老。为帮助您恢复年轻健康的肌肤,php小编子墨整理了一些有效祛除老年斑的方法。本文将分享快速简单的养肤秘诀,帮助您快速消除老年斑。 1.积极保护皮肤免受紫外线伤害的重要性 所以避免长…

    2025年12月5日
    000
  • 颈椎压迫神经的缓解方法(舒缓颈椎压迫神经的有效措施和建议)

    颈椎压迫神经是一种常见的健康问题,会导致颈部疼痛、麻木和肌肉无力。随着人们关注缓解颈椎压迫神经的方法,本文将提供一些经过验证的策略。php小编西瓜在这里将探讨这些缓解方法,帮助读者更好地应对这一问题。通过了解这些技巧,读者可以减轻颈部疼痛,改善神经功能,从而提高他们的整体健康和生活质量。 段落 1.…

    2025年12月5日
    000
  • 文件超过七天失效恢复方法(如何恢复超过七天失效的文件)

    在数字化时代,文件已成为我们不可或缺的一部分。 不幸的是,我们有时可能会丢失或删除宝贵的文件,而这些文件超过七天,无法通过回收站恢复。当这种情况发生时,您该如何恢复超过七天失效的文件?别担心,本文将为您提供一些实用的方法和技巧。php小编子墨将引导您了解如何找到专业的数据恢复软件、使用免费的数据恢复…

    2025年12月4日
    000
  • 如何选择手机膜,保护你的手机屏幕(选购手机膜的几大要点与技巧)

    随着智能手机的普及,手机膜已成为必不可少的配件,可以保护手机屏幕,延长其使用寿命。但市面上的手机膜琳琅满目,如何选择一款最适合自己的手机膜呢?php小编柚子将为您介绍选购手机膜的几大要点与技巧,帮助您避免踩坑,选出最适合的手机膜。 了解手机膜的材质及类型 PET膜,TPU等、手机膜有多种材质,包括钢…

    2025年12月3日
    000
  • 火影忍者手游须佐佐助口令兑换码

    火影忍者手游中,须佐佐助口令兑换码的获取与兑换%ignore_a_2%如下。 1、 火影忍者手游中,须佐佐助口令活动将在7月9日至7月23日进行。 2、 正确口令:忍界压路机(123456、须佐佐助辣条哥、须佐欧皇等)。 快剪辑 国内⼀体化视频⽣产平台 54 查看详情 以上就是火影忍者手游须佐佐助口…

    2025年12月3日 软件教程
    000
  • 四六级学籍照片上传方法

    如何上传四六级学籍照片 1、 首先,打开微信,进入城市服务公众号,如图所示。 2、 接着,在公众号的菜单栏底部找到便民服务,然后在弹出的窗口中点击微信版面,按照下图的操作步骤进行。 快剪辑 国内⼀体化视频⽣产平台 54 查看详情 3、 在办理业务的过程中选择学籍身份,随后上传学籍照片,具体位置如图所…

    2025年12月3日 软件教程
    000
  • mysql 常用几种密码恢复方法

    mysql 常用几种密码恢复方法/*一. MySQL密码的恢复方法之一 如果忘记了MySQL的root密码,可以用以下方法重新设置: 1. KILL掉系统里的MySQL进程;

    数据库 2025年12月2日
    000
  • mysql数据库备份方法

    mysql数据库备份方法mysql数据库备份方法有很多种,下面我们来一一介绍一下备份工具与直接在mysql.exe进行数据备份。

    数据库 2025年12月2日
    000
  • mysql 开启远程连接的三种方法

    本文章收藏了三种关于如何开启mysql 远程连接,第一款就是在mysql cmd命令提示符下给mysql开启远程连接的,方法三是修改mysql my.ini的文件配置来修改的哦。

    数据库 2025年12月2日
    000
  • Mysql删除重复的数据的方法

    这篇文章主要介绍了mysql删除重复的数据 mysql数据去重复,需要的朋友可以参考下 MySQL数据库中查询重复数据 select * from employee group by emp_name having count (*)>1; Mysql  查询可以删除的重复数据 启科网络PHP…

    2025年12月2日
    000

发表回复

登录后才能评论
关注微信