關於while(cin)回車結束 和 while(cin)與cin.get()結合時發現的問題

MuxBlossom發表於2020-12-14

C++初學者筆記(一)

最近想寫一個程式碼,將未知數量的整形數儲存在空間足夠大的陣列中,然後排序後由小到大輸出

寫程式碼時用了這樣一段程式碼:

    int k = 0;

	while(cin>>arr[k])
	{ 
		if(cin.get() == '\n') break;
		
		k++; 
		
     	for(int i=0;i<k;i++)
	{
		cout<<arr[i]<<" ";
	}

順便提一句,執行程式時發現光是靠敲回車結束不能結束此條件下的while迴圈。故加上了一個判斷語句,引入cin.get()函式,方能實現通過敲回車結束while(cin)迴圈。

然後發現 k++與if判斷語句互換位置之後輸出,總是少了一個數,由此產生了題目所述的問題。

最初的想法

當時的想法是這樣的:輸入一串數後,k的值應該比陣列中最後一個值的下標大1,故輸出時用的判斷條件是 i<k。

結果k的值卻等於陣列中最後一個值的下標,k++與判斷語句互換條件後才符合最初的設想。

cin與cin.get()的原理(搬運)

從這看到的: https://blog.csdn.net/dianboliao0344/article/details/102235893

從中摘錄了個人認為與本文相關的部分,見下文。

輸入原理:

程式的輸入都建有一個緩衝區,即輸入緩衝區。一次輸入過程是這樣的,當一次鍵盤輸入結束時會將輸入的資料存入輸入緩衝區,而cin函式直接從輸入緩衝區中取資料。正因為cin函式是直接從緩衝區取資料的,所以有時候當緩衝區中有殘留資料時,cin函式會直接取得這些殘留資料而不會請求鍵盤輸入

一. cin>>

該操作符是根據後面變數的型別讀取資料。

輸入結束條件 :遇到Enter、Space、Tab鍵。

對結束符的處理 :丟棄緩衝區中使得輸入結束的結束符(Enter、Space、Tab)

二.cin.get(陣列名,長度,結束符)

其中結束符為可選引數,讀入的字元個數最多為(長度-1)個,結束符規定結束字串讀取的字元,預設為ENTER

若要讀取字元,直接cin.get(char ch)或ch=cin.get()即可

讀取字元的情況:

輸入結束條件:Enter鍵

對結束符處理:不丟棄緩衝區中的Enter

cin.get() 與 cin.get(char ch)用於讀取字元,他們的使用是相似的,

即:ch=cin.get() 與 cin.get(ch)是等價的。

個人理解

當你敲回車,空格,TAB鍵的時候,這些特殊字元也會儲存在輸入緩衝區
**
(至於輸入緩衝區的儲存原理還不太明朗,有了更深的理解後再來補充)**

以輸入 3(空格)2(回車) 和文章開頭的程式碼段為例。

①輸入3和空格之後,cin部分判斷輸入結束,忽略空格這一特殊符號。向前發現快取區中有整形數3,將3賦給arr[0],while判斷為真,執行迴圈體中的if語句。
②此時cin.get()讀到的卻不是3,而是空格,不滿足條件,執行k++。

當再輸入2與回車的時候,①部分同理,arr[1]=2。 但是在②中,cin.get()讀到的卻是儲存在緩衝區中的回車(’\n’),跳出迴圈,不執行k++,故k比預想中的要小1。但慶幸的是,第二個值也存進了陣列中。

個人總結與反思

cin與cin.get()的區別在於是否保留緩衝區中的特殊字元,讀取緩衝區內的資料時只能讀取到當前緩衝區中留存的最後一個資料。

要想學好C++這門上下相容的語言,相對底層的工作原理不能忽略。

相關文章