C++字符串輸入緩沖區機制詳解

一、緩沖定義

1.緩沖定義

緩沖是在兩種不同速度設備之間傳輸信息時平滑傳輸過程的常用手段。

2.為什麼引入緩沖區

操作系統這門課有明確的說明緩沖的作用,是為瞭解決高速設備和低速設備之間速度不匹配的問題,直接舉個書上的CPU和打印機的例子:

首先我們要用打印機打印一篇文章肯定要經過CPU處理然後給到打印機打印文章,但是CPU處理1000個字節的文字一眨眼的事情,但是打印機可能需要若幹秒,總不可能讓CPU處理一個數據給打印機一個數據這樣子等著運行,這就引入瞭緩沖區,CPU處理完數據存入緩沖區,打印機直接從緩沖區提取已經處理好的數據,這樣子就解決瞭高速設備(CPU)和低速設備(打印機)處理速度不匹配的問題。

二、scanf,cin輸入緩沖區

1.scanf和cin的緩沖類型

scanf和cin的緩沖類型為行緩沖,行緩沖的的特點是在輸入數據隻要沒有碰到換行符(回車)就將數據存入輸入緩沖區,當碰到換行符之後就將緩沖區中的數據取出使用。

2.scanf和cin的緩沖機制

scanf和cin輸入數據緩沖機制基本一致,在讀入一個數據時直到回車之前他都會存儲在輸入緩沖區中,直到碰到回車才會將數據從輸入緩沖區中取出供變量使用,但是緩沖區中的換行符會被留在輸入緩沖區中。

3.cin.getline和cin.get

cin.get讀取字符串直到讀取到回車為止,但是也會將回車留在緩沖區。

cin.getline讀取字符串直到讀取到回車為止,但是不會講回車留在緩沖區。

4.scanf和cin輸入

①cin和scanf讀取一個字符的區別

	char c;
	cin>>c;//cin讀取字符的時候不會讀入空格、回車以及制表符,如果緩沖區開頭是換行符或者制表符會被忽略並清除
	scanf("%c",&c);//scanf讀取字符的時候不會管你是什麼字符直接讀進來

②cin和scanf在讀取緩沖區中的數字、字符串、浮點型的時候不會將開頭的空格、換行符或者制表符當作數據讀入,如果碰到瞭他們會將它們忽略並清除。需要註意cin.get和cin.getline不會將開頭的空格、換行符或者制表符忽略並刪除。

5.可能遇到的問題

①在用cin或者scanf讀取一個字符串之後scanf再讀取一個字符,發現讀取的字符沒辦法輸入而且輸出瞭一個回車。看如下代碼:

	char name[20];
    char c;
    cin>>name;
    cout<<name<<endl;
    scanf("%c",&c);
    cout<<"---"<<int(c)<<endl;

結果如下截圖:

在這裡插入圖片描述

當我們輸入name為123的時候程序就結束瞭輸出c的值為10,在ASCII碼編碼中10對應的是換行符,為什麼會出現上述這種情況呢?因為cin輸入完之後將回車保留在瞭緩沖區中,而scanf(“%c”,&c)輸入字符並不會判斷是空格還是回車,直接將緩沖區中的回車拿瞭出來給瞭字符變量c。

②用cin.getline輸入字符串之後再用scanf讀取一個字符就和上面不一樣瞭。看如下代碼:

	char name[20];
    char c;
    cin.getline(name,20);
    cout<<name<<endl;
    scanf("%c",&c);
    cout<<"---"<<int(c)<<endl;

結果如下截圖:

在這裡插入圖片描述

結果不同的原因是因為scanf,cin,cin.get在行緩沖取出數據之後會將換行符留在緩沖區中,然後再用scanf讀入一個字符發現緩沖區並不為空就從緩沖區中將數據拿出來,而cin.getline會將緩沖區中的換行符也清除,所以不會有①這種情況出現。

③讀入一個字符串之後後面的cin.get()一直無法讀取數據,看如下代碼:

	char name[20];
    cin.get(name,20);
    cout<<"--"<<name<<endl;
    cin.get(name,20);
    cout<<"--"<<name<<endl;
    cin.get(name,20);
    cout<<"--"<<name<<endl;
    cin.get(name,20);
    cout<<"--"<<name<<endl;
    cin.get(name,20);
    cout<<"--"<<name<<endl;

結果如下截圖:

在這裡插入圖片描述

可以看到用第一個cin.get輸入瞭數據之後後面的cin.get都無效瞭,這是因為cin.get從緩沖區中讀取到換行符就結束並將換行符保留在緩沖區中,接下來的cin.get一直在緩沖區中碰到換行符就一直沒有實際數據輸入。

④整形和字符串混合輸入

當先輸入一個整形再用cin.getline輸入字符串會發現沒有經歷輸入字符串的過程,測試如下代碼:

	char name[20];
    int a;
    cin>>a;
    cout<<a<<endl;
    cin.getline(name,20);
    cout<<"---"<<name<<endl;
    cout<<"end"<<endl;

結果如下:

在這裡插入圖片描述

根據上面的緩沖原理比較容易理解,cin輸入一個整形後會在緩沖區中留下一個換行符,因為緩沖區中有換行符剩餘,cin.getline從緩沖區中取出數據發現正好是換行符,那麼就默認字符串輸入完瞭,並將換行符從緩沖區中去掉,所以造成瞭上面的局面。

清除緩沖區

上面講的問題基本上都是因為緩沖區中剩餘的數據造成的,那麼隻需要有方法清除緩沖區就行瞭,可以用getchar(),cin.get()讀取緩沖區中多的換行符。

總結

本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!

推薦閱讀: