C語言之清空緩存區


感謝大佬:https://blog.csdn.net/qq_26768741/article/details/50933598

在C語言中,我們常常需要去清空緩存區,對於緩存區清空的重要性,接下來我們進行具體的說明。
首先我們先解釋一下緩存區。

1.緩存區

C語言中的緩沖區又稱為緩存,它是內存空間的一部分。
  也就是說,在內存空間中預留了一定的存儲空間,這些存儲空間用來緩沖輸入或輸出的數據,這部分預留的空間就叫做緩沖區。
    C語緩沖區分為三種類型:1、全緩沖 2、行緩沖 3、不帶緩沖。
  緩沖區根據其對應的是輸入設備還是輸出設備,分為輸入緩沖區和輸出緩沖區。

例如,在我們平時要在磁盤中讀取信息的情況下,先會把數據放到緩存區中,讀取完后,再次從磁盤中讀取信息。
緩存區,他的意義就是在高速CPU與低速的設備之間的一個區域,這個區域讓CPU工作效率更高。

  1. 全緩沖
    當填滿標准I/O緩存后才進行實際I/O操作。全緩沖的典型代表是對磁盤文件的讀寫。

  2. 行緩沖
    當在輸入和輸出中遇到換行符時,執行真正的I/O操作。這時,我們輸入的字符先存放在緩沖區,等按下回車鍵換行時才進行實際的I/O操作。典型代表是標准輸入(stdin)和標准輸出(stdout)。

  3. 不帶緩沖
    也就是不進行緩沖,標准出錯情況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;
}

在這里插入圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM