zoukankan      html  css  js  c++  java
  • C++编程对缓冲区的理解

    什么是缓冲区
    缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。
    缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。
    为什么要引入缓冲区
    我们为什么要引入缓冲区呢?
    比如我们从磁盘里取信息,我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,故应用缓冲区可大大提高计算机的运行速度。
    又比如,我们使用打印机打印文档,由于打印机的打印速度相对较慢,我们先把文档输出到打印机相应的缓冲区,打印机再自行逐步打印,这时我们的CPU可以处理别的事情。
    现在您基本明白了吧,缓冲区就是一块内存区,它用在输入输出设备和CPU之间,用来缓存数据。它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。
    缓冲区的类型
    缓冲区 分为三种类型:全缓冲、行缓冲和不带缓冲。
    1、全缓冲
    在这种情况下,当填满标准I/O缓存后才进行实际I/O操作。全缓冲的典型代表是对磁盘文件的读写。
    2、行缓冲
    在这种情况下,当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是键盘输入数据。
    3、不带缓冲
    也就是不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。

    缓冲区的刷新
    下列情况会引发缓冲区的刷新:
    1、缓冲区满时;
    2、执行flush语句;
    3、执行endl语句;
    4、关闭文件。
    可见,缓冲区满或关闭文件时都会刷新缓冲区,进行真正的I/O操作。另外,在C++中,我们可以使用flush函数来刷新缓冲区(执行I/O操作并清空缓冲区),如:

    cout<<flush; //将显存的内容立即输出到显示器上进行显示

    endl控制符的作用是将光标移动到输出设备中下一行开头处,并且清空缓冲区。

    cout<<endl;

    相当于

    cout<<”
    ” <<flush;

    通过实例演示说明

    1、文件操作演示全缓冲
    创建一个控制台工程,输入如下代码:

    #include <iostream>
    #include <fstream>
    using namespace std;
    
    int main()
    {
        ofstream stream("e:\a.txt");
    
        // 当为4097时,直接输出到文件了,证明缓冲区大小为4096→4KB
        //
        for (int i = 0; i < 4096; i++)
        {
            stream<<'a';
        }
    
        // dos命令:暂停,按任意键继续
         system("pause");
    
        stream<<'b';
    
        system("pause");
    
        return 0;
    }

    上面这段代码很容易理解,已经在代码内部作了注释。
    编写这段小代码的目的是验证WindowsXP下全缓冲的大小是4096个字节,并验证缓冲区满后会刷新缓冲区,执行真正的I/O操作。

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

    clip_image001

    此时打开工程所在文件夹下的a.txt文件,您会发现该文件是空的,这说明4096个字符“a”还在缓冲区,并没有真正执行I/O操作。敲一下回车键,窗口变为如下:

    clip_image001[4]

    此时再打开a.txt文件,您就会发下该文件中已经有了4096个字符“a”。这说明全缓冲区的大小是4K(4096),缓冲区满后执行了I/O操作,而字符“b”还在缓冲区。
    再次敲一下回车键,窗口变为如下:

    clip_image001[6]

    此时再打开test.txt文件,您就会发现字符“b”也在其中了。这一步验证了文件关闭时刷新了缓冲区。

    2、键盘操作演示行缓冲
    先介绍getchar()函数。
    函数原型:int getchar(void);
    说明:当程序调用getchar()函数时,程序就等着用户按键,用户输入的字符被存放在键盘缓冲区中,直到用户按回车为止(回车字符也放在缓冲区中)。当用户键入回车之后,getchar()函数才开始从键盘缓冲区中每次读入一个字符。也就是说,后续的getchar()函数调用不会等待用户按键,而直接读取缓冲区中的字符,直到缓冲区中的字符读完后,才重新等待用户按键。
    不知道您明白了没有,再通俗一点讲,当程序调用getchar()函数时,程序就等着用户按键,并等用户按下回车键返回。期间按下的字符存放在缓冲区,第一个字符作为函数返回值。继续调用getchar()函数,将不再等用户按键,而是返回您刚才输入的第2个字符;继续调用,返回第3个字符,直到缓冲区中的字符读完后,才等待用户按键。
    如果您还没有明白,只能怨我表达能力有限,您可以结合以下实例体会。

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

    #include <iostream> 
    using namespace std; 
    
    int main() 
    { 
        char c; 
    
        c = getchar(); 
    
        cout << c << endl; 
    
        system("pause"); 
    
        while((c = getchar()) != '
    ') 
        { 
            printf("%c", c); 
        } 
    
        system("pause"); 
    
        return 0; 
    }

    getchar()函数的执行就是采用了行缓冲。第一次调用getchar()函数,会让程序使用者(用户)输入一行字符并直至按下回车键 函数才返回。此时用户输入的字符和回车符都存放在行缓冲区。
    再次调用getchar()函数,会逐步输出行缓冲区的内容。
    好了,本人表达能力有限,还是编译运行程序,通过运行结果自己领会吧。

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

    clip_image001[8]
    您一直按下去,您就会发现当您按到第4094个字符时,不允许您继续输入字符。这说明行缓冲区的大小也是4K。
    此时您按下回车键,返回第一个字符’a’,如下图:
    clip_image002
    继续敲一下回车键,将缓冲区的其它的字符全部输出,如下图:
    clip_image003

    3、标准错误输出不带缓冲
    如错误输出时使用:

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

    这条语句等效于:
    fprintf(stderr, ”错误,请检查输入的参数!”);

  • 相关阅读:
    numpy 基础 —— np.linalg
    图像旋转后显示不完全
    opencv ---getRotationMatrix2D函数
    PS1--cannot be loaded because the execution of scripts is disabled on this system
    打开jnlp Faild to validate certificate, the application will not be executed.
    BATCH(BAT批处理命令语法)
    oracle vm virtualbox 如何让虚拟机可以上网
    merge 实现
    Windows batch,echo到文件不成功,只打印出ECHO is on.
    python2.7.6 , setuptools pip install, 报错:UnicodeDecodeError:'ascii' codec can't decode byte
  • 原文地址:https://www.cnblogs.com/qijicxl/p/3399374.html
Copyright © 2011-2022 走看看