C语言之清空缓存区
感谢大佬:https://blog.csdn.net/qq_26768741/article/details/50933598
在C语言中,我们常常需要去清空缓存区,对于缓存区清空的重要性,接下来我们进行具体的说明。
首先我们先解释一下缓存区。
1.缓存区
C语言中的缓冲区又称为缓存,它是内存空间的一部分。
也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。
C语缓冲区分为三种类型:1、全缓冲 2、行缓冲 3、不带缓冲。
缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。
例如,在我们平时要在磁盘中读取信息的情况下,先会把数据放到缓存区中,读取完后,再次从磁盘中读取信息。
缓存区,他的意义就是在高速CPU与低速的设备之间的一个区域,这个区域让CPU工作效率更高。
全缓冲
当填满标准I/O缓存后才进行实际I/O操作。全缓冲的典型代表是对磁盘文件的读写。行缓冲
当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是标准输入(stdin)和标准输出(stdout)。不带缓冲
也就是不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。
大部分系统默认使用下列类型的缓存:
标准出错是不带缓存的。
如果是涉及终端设备的流,则它们是行缓存的,否则是全缓存的。
我们经常用到的输入输出流,在目前的ANSI C 中缓存的特征是:stdin和stdout是行缓存;而stderr是无缓存的。
了解了这些,接下来我们进入正题,接下来我们要清楚为什么要清空缓存区,
这是因为在你有的时候在输入一个字符后,在输入一个字符,如果你不清空缓冲区,那上一个字符还在你的缓冲区内!这样就造成错误了!
2.清空缓存区
所以我们要对缓存区清空是很重要的,在这里我们给出了下面三种办法来实现:
- 使用fflush()函数
fflush()函数冲洗流中的信息,该函数通常用于处理磁盘文件。清除读写缓冲区,需要立即把输出缓冲区的数据进行物理写入时。fflush()函数包含在stdio.h头文件中。
函数原:int fflush(FILE *stream),在这里的stream就是所要清除缓存区的文件。
函数的返回值:当进行刷新成功返回0,失败返回EOF。没有缓冲区或者只读打开时也返回0值。还有需要注意的是:如果fflush返回EOF,数据可能由于写错误已经丢失。
用法示例:fflush(stdin)刷新标准输入缓冲区,fflush(stdout)刷新标准输出缓冲区。 printf(“。。。。。。。。。。。”);后面加fflush(stdout);可提高打印效率
代码示例:
#include<stdio.h>
#include<stdlib.h>
int main()
{
int num;
char a;
scanf("%d", &num);
a = getchar();
printf("num=%d,a=%c\n", num, a);
system("pause");
return 0;
}

在执行这个程序的时候我们会发现,在我们输入第一个字符后敲击‘\n’之后,程序就结束了,这是因为我们没有清空缓存区,getchar()函数接收的是‘\n’,最后造成了程序的停止。
接下来我们来使用fflush()函数。
#include<stdio.h>
#include<stdlib.h>
int main()
{
int num;
char a;
scanf("%d", &num);
fflush(stdin);
a = getchar();
printf("num=%d,a=%c\n", num, a);
system("pause");
return 0;
}

我们在这里可以看到,当使用了fflush()函数对输入流进行清空缓存区以后,就可以正常让getchar函数接收字符。
接下来是第二种方法。
- 使用while((ch = getchar()) != ‘\n’ && ch != EOF);语句
这种方法是最好的方法,可以称为万能清空缓存区御语句。
代码示例:
#include <stdio.h>
#include<stdlib.h>
int main()
{
char c1 = 0;
char c2 = 0;
scanf("%c", &c1);
c2 = getchar();
printf("c1=%d,c2=%c", c1, c2);
system("pause");
return 0;
}

在这里我们依然没有清空缓存区,得到的效果是这样的,getchar()函数依然接收了’\n’,造成程序停止。
接下来,我们使用while((ch = getchar()) != ‘\n’ && ch != EOF);语句
#include <stdio.h>
#include<stdlib.h>
int main()
{
char c1 = 0;
char c2 = 0;
int ch;
scanf("%d", &c1);
while ((ch = getchar()) != EOF && ch != '\n')
{
;
}
c2 = getchar();
printf("c1=%d,c2=%c", c1, c2);
system("pause");
return 0;
}

加入了while ((ch = getchar()) != EOF && ch != ‘\n’);语句,完成了清空缓存区
事实上有时我们会将这个语句封装在一个函数中,这样会让程序的可移植性更强。
#define CLEAR_BUF \
{\
int ch; \
while ((ch = getchar()) != EOF && ch != '\n')\
{\
; \
}\
}
#include <stdio.h>
#include<stdlib.h>
int main()
{
char c1 = 0;
char c2 = 0;
scanf("%d", &c1);
CLEAR_BUF
c2 = getchar();
printf("c1=%d,c2=%c", c1, c2);
system("pause");
return 0;
}

依然可以达到我们要的效果。
- setbuf()函数关闭缓存区
接下来我们要说另外一种清空缓存区的方法,与其说是清空缓存区,不如说他是关闭缓存区。
setbuf()函数
是linux中的C函数,主要用于打开和关闭缓冲机制。包含在头文件stdio.h中。
setbuf函数具有打开和关闭缓冲机制。为了带缓冲进行I/O,参数buf必须指向一个长度为BUFSIZ的缓冲区。通常在此之后该流就是全缓冲的,但是如果该流与一个终端设备相关,那么某些系统也可以将其设置为行缓冲。为了关闭缓冲,可以将buf参数设置为NULL。
函数原型:void setbuf(FILE *stream,char *buf);一个参数是文件流,一个参数是buf指向的缓冲区长度,这个长度就是在stdio.h中定义的宏BUFSIZ所决定的。当定义buf为空时,setbuf函数将使的文件I/O不带缓冲。
#include <stdio.h>
#include<stdlib.h>
char outbuf[50];
int main(void)
{
/* 将outbuf与stdout输出流相连接 */
setbuf(stdout, outbuf);
/* 向stdout中放入一些字符串 */
puts("This is a test of buffered output.");
puts("This output will go into outbuf");
puts("and won't appear until the buffer");
puts("fills up or we flush the stream.\n");
/* 以下是outbuf中的内容 */
puts(outbuf);
/*刷新流*/
fflush(stdout);
system("pause");
return 0;
}

C语言之清空缓存区的更多相关文章
- 基础 - 字符读取函数scanf、getchar、gets、cin(清空缓存区解决单字符回车问题)
0x01 scanf.getchar.cin读取单字符: 如下: //scanf读取字符 回车问题 void Sub_1_1() { char v1,v2; scanf("%c", ...
- C语言 标准输入 清空缓存
- sed原理及sed命令格式 ,缓存区,模式空间
4.1 Sed工作原理 sed是一个非交互式的流编辑器.所谓非交互式,是指使用sed只能在命令行下输入编辑命令来编辑文本,然后在屏幕上查看输出:而所谓流编辑器,是指sed每次只从 ...
- 【MINA】缓存区ByteBuffer和IOBuffer你要了解的常用知识
mina中IOBuffer是Nio中ByteBuffer的衍生类,主要是解决Bytebuffer的两个不足 1.没有提供足够灵活的get/putXXX方法 2.它容量固定,难以写入可变长度的数据 特点 ...
- JAVA之旅(十七)——StringBuffer的概述,存储,删除,获取,修改,反转,将缓存区的数据存储到数组中,StringBuilder
JAVA之旅(十七)--StringBuffer的概述,存储,删除,获取,修改,反转,将缓存区的数据存储到数组中,StringBuilder 讲完String,我们来聊聊他的小兄弟 一.StringB ...
- 关于cin的缓存区影响效果
1. 当缓冲区中有残留数据时,cin函数会直接去读取这些残留数据而不会请求键盘输入.而且,回车符也会被存入输入缓冲区中. int num{}; while(cin>>num) cout&l ...
- 一个fork的面试题——fork + 缓存区
update : 20140512 题目:请问下面的程序一共输出多少个“-”? #include <stdio.h> #include <sys/types.h> #inclu ...
- 进程通过内核缓存区请求设备I/O的一些事情
请求进程,内核缓存区,设备I/O 请求进程无法直接访问设备I/O,而是通过内核缓冲区提交请求数据,等数据就绪后,数据从设备缓冲区提交至进程空间 请求进程把数据提交给内核缓存空间需要等待,内核把数据复制 ...
- node(Buffer缓存区)
// 创建buffer类 var buf=new buffer(10); var buf=new buffer([10,20,30,40]); var buf=new buffer("www ...
随机推荐
- CS5212Capstone|DP转VGA方案设计芯片|CS5212设计资料
CS5212是台湾CAPSTONE最新开发出一款用于DP转VGA方案设计芯片,其周围器件较少,设计简单,整体BOM成本低,市场性价比较高. CS5212内置MCU是工业标准8051核心单片机处理器.C ...
- Vue.js高效前端开发 • 【Vue组件】
全部章节 >>>> 文章目录 一.Vue组件介绍 1.组件概述 2.组件使用步骤 3.实践练习 一.Vue组件使用 1.组件注册 2.组件注册语法糖 3.使用script或te ...
- mysql 语句中 sum函数求和 null 变 0
https://blog.csdn.net/Z_passionate/article/details/83821039
- html基础 表单相关属性综合实战案例 附有注释
html结构代码: <form > <!-- form 为了让重置按钮生效--> <h1>青春不常在,抓紧谈恋爱</h1> <hr> 昵称: ...
- python 安装包时提示“unsupport command install”
为什么提示找不到? 电脑安装了LoadRunnder,LoadRunner也有pip.exe,导致找不到python的exe 解决方法: 切换到python pip的路径进行安装,进到这个路径下,进行 ...
- RPC框架下实现文件上传到linux服务器
一.前端使用element -ui 的upload组件 :data 表示额外传递的参数, :header 表示设置请求头参数,如,token等, action表示后台api接口的地址 二. conto ...
- NIO【同步非阻塞io模型】关于 NIO socket 的详细总结【Java客户端+Java服务端 + 业务层】【可以客户端间发消息】
1.前言 以前使用 websocket来实现双向通信,如今深入了解了 NIO 同步非阻塞io模型 , 优势是 处理效率很高,吞吐量巨大,能很快处理大文件,不仅可以 做 文件io操作, 还可以做sock ...
- JUC之读写锁问题
读写锁 读写锁在同一时刻可以允许多个读线程访问,但是在写线程访问时,所有的读线程和其他写线程均被阻塞.读写锁维护了一对锁,一个读锁和一个写锁,通过分离读锁和写锁,使得并发性相比一般的排他锁有了很大提升 ...
- 干掉 Postman?测试接口直接生成API文档,ApiPost真香!
实不相瞒我的收藏夹里躺着很多优质的开发工具,我有个爱好平时遇到感兴趣的开发工具都会记录下来,然后有时间在慢慢研究.前几天刚给同事分享一款非常好用的API文档工具,真的被惊艳到了,粉丝朋友们也感受一下吧 ...
- 介绍一下主流的浏览器的开发者工具(js调试和查看网络请求)
1.打开开发者工具:右键-->检查 (快捷键 f12) 2.开发者工具介绍: (1): 选择页面的dom进行查看 (2):设备适配 (3)元素: ① 可以查找到界面对应的dom: ② 通过计算样 ...