在搞数据库和C++进行连接的时候,遇到一个问题,就是如果前面用到了fflush(stdin)即清空缓冲区,就OK,如果不清空缓冲区就不能把记录加入到Mysql的数据库中,

但是即便如此,这个问题目前还是没有搞清楚。

为了搞清楚这个问题,查阅了buffer的相关资料。

51CTO的这篇博客写得不错,例子举的也很好,但是第一个例子如果能换个说法,或许效果会更好。本文将第一个例子改了一下,更加通俗易懂。

下面介绍缓冲区的知识。

一、什么是缓冲区

缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。

缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。

二、为什么要引入缓冲区

我们为什么要引入缓冲区呢?

比如我们从磁盘里取信息,我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,故应用缓冲区可大大提高计算机的运行速度。

又比如,我们使用打印机打印文档,由于打印机的打印速度相对较慢,我们先把文档输出到打印机相应的缓冲区,打印机再自行逐步打印,这时我们的CPU可以处理别的事情。

现在您基本明白了吧,缓冲区就是一块内存区,它用在输入输出设备和CPU之间,用来缓存数据。它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。

三、缓冲区的类型

缓冲区 分为三种类型:全缓冲、行缓冲和不带缓冲。

1、全缓冲

在这种情况下,当填满标准I/O缓存后才进行实际I/O操作。全缓冲的典型代表是对磁盘文件的读写。

2、行缓冲

在这种情况下,当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是键盘输入数据。

3、不带缓冲

也就是不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。

四、缓冲区的刷新

下列情况会引发缓冲区的刷新:

  • 缓冲区满时;
  • 执行flush语句;
  • 执行endl语句;
  • 关闭文件。

可见,缓冲区满或关闭文件时都会刷新缓冲区,进行真正的I/O操作。另外,在C++中,我们可以使用flush函数来刷新缓冲区(执行I/O操作并清空缓冲区),如:

  1. cout<<flush; //将显存的内容立即输出到显示器上进行显示
  2. endl控制符的作用是将光标移动到输出设备中下一行开头处,并且清空缓冲区。
  3. cout<<endl;

相当于

  1. cout<<”\n” <<flush;

五、实例演示

1、文件操作演示全缓冲

创建一个控制台工程,输入如下代码:

 #include <fstream>
using namespace std;
int main()
{
//创建文件test.txt并打开
ofstream outfile("test.txt");
//向test.txt文件中写入4096个字符’a’
for(int n=;n<;n++)
{
outfile<<'a';
}
outfile<<'b';
//暂停,按任意键继续
system("PAUSE");
//继续向test.txt文件中写入字符’b’,也就是说,第4097个字符是’b’
outfile<<'c';
//暂停,按任意键继续
system("PAUSE");
outfile('d');
return ;
}

上面这段代码很容易理解,已经在代码内部作了注释。

编写这段小代码的目的是验证Windows7下全缓冲的大小是4096个字节,并验证缓冲区满后会刷新缓冲区,执行真正的I/O操作。

编译并执行,运行结果如下:

此时打开工程所在文件夹下的test.txt文件,您会发现该文件不是空的,但是输出只有4096个“a”,并没有输出b,敲一下回车键,窗口变为如下:

此时再次敲一下回车键,发现bc还在缓冲区,并没有输出,窗口变为如下:

再敲一次回车键,所有的system("pause")执行完毕,最后再敲一次回车键,这个时候,bcd才一次性全部写入文件。这就是全缓冲区。

2、键盘操作演示行缓冲

先介绍getchar()函数。

函数原型:int getchar(void);

说明:当程序调用getchar()函数时,程序就等着用户按键,用户输入的字符被存放在键盘缓冲区中,直到用户按回车为止(回车字符也放在缓冲区中)。当用户键入回车之后,getchar()函数才开始从键盘缓冲区中每次读入一个字符。也就是说,后续的getchar()函数调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完后,才重新等待用户按键。

不知道您明白了没有,再通俗一点讲,当程序调用getchar()函数时,程序就等着用户按键,并等用户按下回车键返回。期间按下的字符存放在缓冲区,第一个字符作为函数返回值。继续调用getchar()函数,将不再等用户按键,而是返回您刚才输入的第2个字符;继续调用,返回第3个字符,直到缓冲区中的字符读完后,才等待用户按键。

如果您还没有明白,只能怨我表达能力有限,您可以结合以下实例体会。

创建一个控制台工程,输入如下代码:

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. char c;
  6. //第一次调用getchar()函数
  7. //程序执行时,您可以输入一串字符并按下回车键,按下回车键后该函数才返回
  8. c=getchar();
  9. //显示getchar()函数的返回值
  10. cout<<c<<endl;
  11. //暂停
  12. system("PAUSE");
  13. //循环多次调用getchar()函数
  14. //将每次调用getchar()函数的返回值显示出来
  15. //直到遇到回车符才结束
  16. while((c=getchar())!='\n')
  17. {
  18. printf("%c",c);
  19. }
  20. //暂停
  21. system("PAUSE");
  22. return 0;
  23. }

这段小代码也很简单,同样在代码内部都有注释。

getchar()函数的执行就是采用了行缓冲。第一次调用getchar()函数,会让程序使用者(用户)输入一行字符并直至按下回车键 函数才返回。此时用户输入的字符和回车符都存放在行缓冲区。再次调用getchar()函数,会逐步输出行缓冲区的内容。

好了,本人表达能力有限,还是编译运行程序,通过运行结果自己领会吧。

编译运行程序,会提示您输入字符,您可以交替按下一些字符,如下:

您一直按下去,您就会发现当您按到第4094个字符时,不允许您继续输入字符。这说明行缓冲区的大小也是4K。

此时您按下回车键,返回第一个字符’a’,如下图:

继续敲一下回车键,将缓冲区的其它的字符全部输出,如下图:

3、标准错误输出不带缓冲

如错误输出时使用:

  1. cerr<<”错误,请检查输入的参数!”;

这条语句等效于:

    1. fprintf(stderr, ”错误,请检查输入的参数!”);

最新文章

  1. git的详细说明文档
  2. Gray Code
  3. css三角形的实现
  4. 不连数据库List分页
  5. Java NIO原理和使用(转载一)
  6. jquery 图片放大
  7. Linux下归档与压缩工具笔记
  8. BarChart控件的使用
  9. Java 第一个程序案HelloWorld例记录
  10. 疑似CPU或者内存故障导致进程崩溃
  11. 小议webpack下的AOP式无侵入注入
  12. js 工厂模式、简单模式、抽象模式
  13. jieba库与词云的使用——以孙子兵法为例
  14. [IOI2018]组合动作——构造
  15. 全面解决.Net与Java互通时的RSA加解密问题,使用PEM格式的密钥文件
  16. TopK
  17. abap中结构体嵌套结构体。
  18. Big-endian/Little-endian, LSB/MSB
  19. 嵌入式C编程代码优化笔记
  20. postgresql-distinct on理解

热门文章

  1. (ssh整合web导出excel)在ssh框架中使用poi正确导出具有比较高级固定格式的excel 整体过程,查询导出前后台下载
  2. C# 调用c++报错可能性分析
  3. (转)C/C++中static关键字
  4. win7+IE11 中开发工具报错occurredJSLugin.3005解决办法
  5. JQuery动态表格
  6. iwebshop 改版页面
  7. HTML中发送方式(method)中get和post的比较
  8. Python 读取csv文件到excel
  9. Linux回归篇-基础恶补
  10. LogLog