C語言中輸入輸出流與緩衝區的深入講解

一般情況下,由鍵盤輸入的字符並沒有直接送入程序,而是被存儲在一個緩衝區當中。下面這篇文章主要給大家介紹了關於C語言中輸入輸出流與緩衝區的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下

前言

緩衝區 又稱爲緩存,它是內存空間的一部分。也就是說,在內存空間中預留了一定的存儲空間,這些存儲空間用來緩衝輸入或輸出的數據,這部分預留的空間就叫做緩衝區。

緩衝區根據其對應的是輸入設備還是輸出設備,分爲輸入緩衝區和輸出緩衝區。

原理介紹:

  • 當調用輸入函數scanf()時,輸入函數會將我們輸入的數字輸入到輸入緩衝區,
  • 而當我們的輸入緩衝區有內容時,再次輸入將不會被執行,
  • 而是直接跳過執行,將輸入緩衝區的內容賦給變量;

1、爲什麼要引入緩衝區

例如,我們從磁盤裏取信息,我們先把讀出的數據放在緩衝區,計算機再直接從緩衝區中取數據,等緩衝區的數據取完後再去磁盤中讀取,這樣就可以減少磁盤的讀寫次數,再加上計算機對緩衝區的操作大大快於對磁盤的操作,故應用緩衝區可大大提高計算機的運行速度。

又比如,我們使用打印機打印文檔,由於打印機的打印速度相對較慢,我們先把文檔輸出到打印機相應的緩衝區,打印機再自行逐步打印,這時我們的CPU可以處理別的事情。

現在您基本明白了吧,緩衝區就是一塊內存區, 它用在輸入輸出設備和CPU之間,用來緩存數據 。它 使得低速的輸入輸出設備和高速的CPU能夠協調工作 ,避免低速的輸入輸出設備佔用CPU,解放出CPU,使其能夠高效率工作。

2、緩衝區的類型

緩衝區分爲三種類型:全緩衝、行緩衝和不帶緩衝。

1) 全緩衝

在這種情況下,當 填滿 標準I/O緩存後才進行實際I/O操作。全緩衝的典型代表是 對磁盤文件的讀寫 。

2) 行緩衝

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

3) 不帶緩衝

也就是不進行緩衝,標準出錯情況stderr是典型代表,這使得出錯信息可以直接儘快地顯示出來。

3、緩衝區的大小

如果我們沒有自己設置緩衝區的話,系統會默認爲標準輸入輸出設置一個緩衝區,這個緩衝區的大小通常是 512個字節 的大小。

緩衝區大小由 stdio.h 頭文件中的宏 BUFSIZ 定義,如果希望查看它的大小,包含頭文件,直接輸出它的值即可:printf("%d", BUFSIZ);

緩衝區的大小是可以改變的,也可以將文件關聯到自定義的緩衝區,詳情可以查看 setvbuf() setbuf() 函數。

4、緩衝區的刷新(清空)

下列情況會引發緩衝區的刷新: 緩衝區滿時 ; 行緩衝區遇到回車時 ; 關閉文件 ; 使用特定函數刷新緩衝區 。

5、結合緩衝區談談C語言getchar()、getche()、getch()的區別

先來看一下 getchar() ,其原型爲: int getchar(void);

當程序調用getchar()函數時,程序就等着用戶按鍵, 用戶輸入的字符被存放在鍵盤緩衝區中,直到用戶按回車爲止(回車字符也放在緩衝區中) 。當用戶鍵入回車之後,getchar()函數 纔開始從鍵盤緩衝區中每次讀入一個字符 。也就是說, 後續的getchar()函數調用不會等待用戶按鍵,而直接讀取緩衝區中的字符,直到緩衝區中的字符讀完後,才重新等待用戶按鍵 。打個比方,鍵盤緩衝區就像是一條水管連着你的程序,程序調用getchar()函數用戶輸入字符就相當於往水管裏注水,這個水注多少取決於你輸入多少,當你按回車停止注水時,getchar()函數纔會開始從鍵盤緩衝區,也就是我們的水管裏取水,那每次只會讀一個字符也就是每次取一定量的水,當你在這之後繼續調用getchar()函數時,會接着在水管裏取上次沒用完的水,因爲你的水管沒清空(緩衝區的刷新),那這個階段就不用你再輸入了,因爲一調用getchar()函數就有水可取嘛,直到水管裏沒水了,你還調用getchar()函數,那這個時候你就得注水了也就是程序會等你按鍵。

通俗一點說,當程序調用getchar()函數時,程序就等着用戶按鍵,並等用戶按下回車鍵返回。期間按下的字符存放在緩衝區,第一個字符作爲函數返回值。繼續調用getchar()函數,將不再等用戶按鍵,而是返回您剛纔輸入的第2個字符;繼續調用,返回第3個字符,直到緩衝區中的字符讀完後,纔等待用戶按鍵。

getchar()函數的執行就是採用了行緩衝。第一次調用getchar()函數,會讓程序使用者(用戶)輸入一行字符並直至按下回車鍵 函數才返回。此時用戶輸入的字符和回車符都存放在行緩衝區。再次調用getchar()函數,會逐步輸出行緩衝區的內容。

請看下面一個例子:


運行結果如下:


再把程序做微小改變,你再看看,加深理解:


運行結果:


上面第二次打印時不是2而是空格,你應該想到爲什麼了吧?

好,我們再來看一個例子:


運行結果:


getchar()函數是從 輸入流緩衝區 中讀取數據的,而不是從 鍵盤(終端)緩衝區 讀取。當讀取遇到回車(\n)結束時,這個'\n'會一起讀入到輸入流緩衝區的, 所以第一次接收輸入時取走字符後會留下字符\n,這樣第二次getchar()直接從緩衝區中把\n取走了 ,顯然讀取成功了,所以不會再從終端讀取!其實這裏的 10恰好是回車符 !這就是爲什麼這個程序只執行了一次輸入操作就結束的原因!

getch()和getche()函數

在TC2.0時代,C程序員總是喜歡在程序末尾加上getch() ,來實現程序運行完了暫停不退出的效果。如果不這樣做,在TC2.0的環境中Ctrl+F9編譯並運行後會立即退出程序,根本來不及看到結果。這時如果要看結果,就要按Alt+F5回到DOS環境中去,很麻煩。而如果在程序的結尾加上一行getch();語句,就可以省掉回DOS看結果這個步驟,因爲程序運行完了並不退出,而是在程序最後把屏幕停住了,按任意鍵才退出程序。

實際上, getch() 的作用是從鍵盤 接收一個字符,且不帶回顯 。就是說, 你按了一個鍵後它並不在屏幕上顯示你按的什麼,而繼續運行後面的代碼 ,所以在C語言中可以用它來實現“按任意鍵繼續”的效果,即程序中遇到getch();語句,就會停下來,等你按任意鍵,它接收了這個字符鍵後再繼續執行後面的代碼。這跟上面在Windows下用的system(“PAUSE")功能一樣,但卻不會在屏幕上顯示(即不會有”按任意鍵繼續“的提示),這樣,利用getch()無回顯的特性,不管你按什麼鍵,都不會在屏幕上留下痕跡,使你的界面達到美觀效果。。

getche()getch()很相似,它也需要引入頭文件conio.h,它們之間的區別就在於:getch()無回顯,getche()有回顯。

下面看一個例子:


首先這是個連續5次的循環來實現5次停頓,等待你輸入。編譯並運行這個程序,假設輸入的是abcde,那麼屏幕上顯示的結果也是abcde,這個abcde並不是在ch=getch();中輸出的。把printf("%c",ch);這行語句去掉,就會發現按5次任意鍵程序就結束了,但屏幕上什麼都沒有顯示。

你可以把代碼中的getch()換成getche()看看有什麼不同。如果還是輸入abcde,那麼屏幕上顯示的結果是aabbccddee,我們把printf("%c",ch);這行語句再去掉,顯示的結果就是abcde了,說明程序在執行ch=getche();這條語句的時候就把我們輸入的鍵返回顯示在屏幕上, 有無回顯就是它們的唯一區別 。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對神馬文庫的支持。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章