標籤:putchar ima 讀寫 .cpp src target str blocks 方式
緩衝區的概念
在電腦運行過程中,CPU負責對資料的加工和處理,而硬體裝置則負責對資料的傳輸、表示或儲存,如列印、輸入\輸出等。在這一過程中,不同裝置的處理速度有較大差別,從而造成一定程度的效率問題。如在印表機輸出過程中,若CPU直接將計算結果交由印表機輸出,由於列印輸出速度較慢,CPU將需要等待上一個結果輸出完成後才能繼續輸出下一個結果。同樣,在輸入過程中,CPU需要一直等待直到裝置I\O將讀取的資料交由其處理。在這個過程中,由於CPU速度較I\O裝置快,CPU在大部分時間處於等待狀態,從而使得CPU利用率很低,造成系統昂貴資源的浪費。
為瞭解決CPU與外圍硬體裝置速度不匹配的問題,提高CPU的利用率,提高系統的並行效率,在系統中引入了緩衝區(buffer)的概念。
緩衝區是在實體記憶體中獨立分配的用於資料移動過程中臨時儲存資料的記憶體地區。(Wiki Data Buffer)
在使用Buffer之後,資料的傳輸過程中,可以將資料先放置在緩衝區中,再交由其他裝置處理。以上面操作過程為例,CPU可以先將計算結果存放在緩衝區中,再由印表機從其中讀取資料,在印表機輸出的過程中,CPU可以處理其他資料而無需等待。在輸入過程中,CPU不等待輸入完成,I\O裝置將使用者輸入存放在緩衝區中,再去請求CPU資源,CPU則可直接從緩衝區中讀取資料進行處理,從而大大提高了CPU的利用率和運行效率。
標準I\O的緩衝
標準I\O根據不同的應用需求,提供了全緩衝、行緩衝、無緩衝三種緩衝方式。
全緩衝:只有當劃定的緩衝區被填滿或者資料讀取至末尾時,才開始執行I\O操作(執行系統提供的read\write操作)。磁碟檔案的讀寫一般採用這種方式。
行緩衝:當輸入輸出過程遇到分行符號‘‘\n"或者當分配緩衝區已滿時,才開始執行I\O操作。一般涉及終端的讀寫操作如stdio與stdout使用這種緩衝方式。
無緩衝:當有資料產生時,馬上由相應的裝置進行處理。一般來說stderr(standard error)使用這種緩衝方式,使得有錯誤資訊時馬上能夠得到響應。需要注意的是,標準庫不緩衝並不意味著作業系統或者裝置驅動不緩衝。
注意,以上關於stdio/stdout的緩衝方式並不是直接規定死的。一些語言的語言規範會對緩衝實現給出一定的限制,但並不具體,只是許多標準I/O是以上述方式實現的而已。可以參考關於流和緩衝區。
I\O函數——getchar
getchar()是用於字元輸入的C庫函數,其函數的聲明包含在標頭檔stdio.h,函數定義 int getchar(void).
getchar()的功能是讀取標準輸入stdin中的一個字元。getchar從標準輸入中讀取資料,而stdin是採用行緩衝的方式記錄使用者輸入,也就是只有當使用者鍵入斷行符號鍵或輸入至緩衝區末尾時,才會開始I\O操作,亦即讀取一個字元。這樣使用者可以一次輸入不止一個字元,讀取過後緩衝區可能不為空白。當再次調用getchar()時,若緩衝區不為空白,getchar()就會直接讀取在緩衝區中字元,而不是等待使用者輸入。可以認為是getchar()等待的是行緩衝的完成,而不是使用者輸入的完成,在行緩衝完成後,只要緩衝區不為空白,getchar()就可以讀取字元,而不需要等待使用者輸入。
/*codeblocks13.12*/#include <stdio.h>int main(void){ char ch = ‘\0‘; while(ch != ‘\n‘) { printf("輸入一個字元:"); ch = getchar(); printf("\n"); putchar(ch); printf("\n"); } return 0;}
程式的運行結果如下:
可以明顯看到,後續執行中並不要求使用者輸入,getchar()會直接讀取緩衝區中的資料。而且對於字元的讀取操作而言,分行符號‘\n‘也被視為一個字元,而不是單純的結束標誌。
等待使用者輸入的字元輸入
getchar()可以直接從緩衝區中讀取字元,而不等待使用者輸入,但這種方式也有可能帶來潛在的錯誤。這裡給出兩種等待使用者輸入的字元傳入方式。
1.使用getche()與getch()函數。都從鍵盤上讀入一個位元組,其中後者不將字元回顯到螢幕上。以這兩個函數讀取字元時,都是通過調用函數讀取一個鍵盤輸入且只有一個。如調用getche(),鍵盤敲擊‘abc‘時,只有一個字元‘a‘會被讀取。其他字元為無效輸入。
2.在每次getchar()之後,手動對緩衝區進行清除操作。可以使用fflush()函數清理緩衝區。C標準規定 fflush()函數可用來重新整理輸出(stdout)緩衝區(一般是將緩衝區資料寫回存放裝置)。但對於標準輸入(stdin)則沒有明確定義。部分編譯器定義了 fflush( stdin )的實現,如微軟的VC。也就是不同的編譯器對於 fflush( stdin )的支援可能不同。GCC編譯器沒有定義它的實現,所以不能使用 fflush( stdin )來重新整理輸入緩衝區。
C語言緩衝區問題——getchar描述