C語(yǔ)言中輸入輸出流與緩沖區(qū)的深入講解
前言
緩沖區(qū) 又稱為緩存,它是內(nèi)存空間的一部分。也就是說(shuō),在內(nèi)存空間中預(yù)留了一定的存儲(chǔ)空間,這些存儲(chǔ)空間用來(lái)緩沖輸入或輸出的數(shù)據(jù),這部分預(yù)留的空間就叫做緩沖區(qū)。
緩沖區(qū)根據(jù)其對(duì)應(yīng)的是輸入設(shè)備還是輸出設(shè)備,分為輸入緩沖區(qū)和輸出緩沖區(qū)。
原理介紹:
- 當(dāng)調(diào)用輸入函數(shù)scanf()時(shí),輸入函數(shù)會(huì)將我們輸入的數(shù)字輸入到輸入緩沖區(qū),
- 而當(dāng)我們的輸入緩沖區(qū)有內(nèi)容時(shí),再次輸入將不會(huì)被執(zhí)行,
- 而是直接跳過(guò)執(zhí)行,將輸入緩沖區(qū)的內(nèi)容賦給變量;
1、為什么要引入緩沖區(qū)
例如,我們從磁盤(pán)里取信息,我們先把讀出的數(shù)據(jù)放在緩沖區(qū),計(jì)算機(jī)再直接從緩沖區(qū)中取數(shù)據(jù),等緩沖區(qū)的數(shù)據(jù)取完后再去磁盤(pán)中讀取,這樣就可以減少磁盤(pán)的讀寫(xiě)次數(shù),再加上計(jì)算機(jī)對(duì)緩沖區(qū)的操作大大快于對(duì)磁盤(pán)的操作,故應(yīng)用緩沖區(qū)可大大提高計(jì)算機(jī)的運(yùn)行速度。
又比如,我們使用打印機(jī)打印文檔,由于打印機(jī)的打印速度相對(duì)較慢,我們先把文檔輸出到打印機(jī)相應(yīng)的緩沖區(qū),打印機(jī)再自行逐步打印,這時(shí)我們的CPU可以處理別的事情。
現(xiàn)在您基本明白了吧,緩沖區(qū)就是一塊內(nèi)存區(qū), 它用在輸入輸出設(shè)備和CPU之間,用來(lái)緩存數(shù)據(jù) 。它 使得低速的輸入輸出設(shè)備和高速的CPU能夠協(xié)調(diào)工作 ,避免低速的輸入輸出設(shè)備占用CPU,解放出CPU,使其能夠高效率工作。
2、緩沖區(qū)的類型
緩沖區(qū)分為三種類型:全緩沖、行緩沖和不帶緩沖。
1) 全緩沖
在這種情況下,當(dāng) 填滿 標(biāo)準(zhǔn)I/O緩存后才進(jìn)行實(shí)際I/O操作。全緩沖的典型代表是 對(duì)磁盤(pán)文件的讀寫(xiě) 。
2) 行緩沖
在這種情況下,當(dāng)在輸入和輸出中遇到 換行符 時(shí),執(zhí)行真正的I/O操作。這時(shí),我們輸入的字符先存放在緩沖區(qū),等 按下回車鍵換行 時(shí)才進(jìn)行實(shí)際的I/O操作。典型代表是 標(biāo)準(zhǔn)輸入(stdin) 和 標(biāo)準(zhǔn)輸出(stdout) 。
3) 不帶緩沖
也就是不進(jìn)行緩沖,標(biāo)準(zhǔn)出錯(cuò)情況stderr是典型代表,這使得出錯(cuò)信息可以直接盡快地顯示出來(lái)。
3、緩沖區(qū)的大小
如果我們沒(méi)有自己設(shè)置緩沖區(qū)的話,系統(tǒng)會(huì)默認(rèn)為標(biāo)準(zhǔn)輸入輸出設(shè)置一個(gè)緩沖區(qū),這個(gè)緩沖區(qū)的大小通常是 512個(gè)字節(jié) 的大小。
緩沖區(qū)大小由 stdio.h 頭文件中的宏 BUFSIZ 定義,如果希望查看它的大小,包含頭文件,直接輸出它的值即可:printf("%d", BUFSIZ);
緩沖區(qū)的大小是可以改變的,也可以將文件關(guān)聯(lián)到自定義的緩沖區(qū),詳情可以查看 setvbuf()
和 setbuf()
函數(shù)。
4、緩沖區(qū)的刷新(清空)
下列情況會(huì)引發(fā)緩沖區(qū)的刷新: 緩沖區(qū)滿時(shí) ; 行緩沖區(qū)遇到回車時(shí) ; 關(guān)閉文件 ; 使用特定函數(shù)刷新緩沖區(qū) 。
5、結(jié)合緩沖區(qū)談?wù)凜語(yǔ)言getchar()、getche()、getch()的區(qū)別
先來(lái)看一下 getchar()
,其原型為: int getchar(void);
當(dāng)程序調(diào)用getchar()函數(shù)時(shí),程序就等著用戶按鍵, 用戶輸入的字符被存放在鍵盤(pán)緩沖區(qū)中,直到用戶按回車為止(回車字符也放在緩沖區(qū)中) 。當(dāng)用戶鍵入回車之后,getchar()函數(shù) 才開(kāi)始從鍵盤(pán)緩沖區(qū)中每次讀入一個(gè)字符 。也就是說(shuō), 后續(xù)的getchar()
函數(shù)調(diào)用不會(huì)等待用戶按鍵,而直接讀取緩沖區(qū)中的字符,直到緩沖區(qū)中的字符讀完后,才重新等待用戶按鍵 。打個(gè)比方,鍵盤(pán)緩沖區(qū)就像是一條水管連著你的程序,程序調(diào)用getchar()
函數(shù)用戶輸入字符就相當(dāng)于往水管里注水,這個(gè)水注多少取決于你輸入多少,當(dāng)你按回車停止注水時(shí),getchar()
函數(shù)才會(huì)開(kāi)始從鍵盤(pán)緩沖區(qū),也就是我們的水管里取水,那每次只會(huì)讀一個(gè)字符也就是每次取一定量的水,當(dāng)你在這之后繼續(xù)調(diào)用getchar()
函數(shù)時(shí),會(huì)接著在水管里取上次沒(méi)用完的水,因?yàn)槟愕乃軟](méi)清空(緩沖區(qū)的刷新),那這個(gè)階段就不用你再輸入了,因?yàn)橐徽{(diào)用getchar()函數(shù)就有水可取嘛,直到水管里沒(méi)水了,你還調(diào)用getchar()函數(shù),那這個(gè)時(shí)候你就得注水了也就是程序會(huì)等你按鍵。
通俗一點(diǎn)說(shuō),當(dāng)程序調(diào)用getchar()函數(shù)時(shí),程序就等著用戶按鍵,并等用戶按下回車鍵返回。期間按下的字符存放在緩沖區(qū),第一個(gè)字符作為函數(shù)返回值。繼續(xù)調(diào)用getchar()函數(shù),將不再等用戶按鍵,而是返回您剛才輸入的第2個(gè)字符;繼續(xù)調(diào)用,返回第3個(gè)字符,直到緩沖區(qū)中的字符讀完后,才等待用戶按鍵。
getchar()
函數(shù)的執(zhí)行就是采用了行緩沖。第一次調(diào)用getchar()函數(shù),會(huì)讓程序使用者(用戶)輸入一行字符并直至按下回車鍵 函數(shù)才返回。此時(shí)用戶輸入的字符和回車符都存放在行緩沖區(qū)。再次調(diào)用getchar()
函數(shù),會(huì)逐步輸出行緩沖區(qū)的內(nèi)容。
請(qǐng)看下面一個(gè)例子:
運(yùn)行結(jié)果如下:
再把程序做微小改變,你再看看,加深理解:
運(yùn)行結(jié)果:
上面第二次打印時(shí)不是2而是空格,你應(yīng)該想到為什么了吧?
好,我們?cè)賮?lái)看一個(gè)例子:
運(yùn)行結(jié)果:
getchar()
函數(shù)是從 輸入流緩沖區(qū) 中讀取數(shù)據(jù)的,而不是從 鍵盤(pán)(終端)緩沖區(qū) 讀取。當(dāng)讀取遇到回車(\n)結(jié)束時(shí),這個(gè)'\n'會(huì)一起讀入到輸入流緩沖區(qū)的, 所以第一次接收輸入時(shí)取走字符后會(huì)留下字符\n,這樣第二次getchar()
直接從緩沖區(qū)中把\n取走了 ,顯然讀取成功了,所以不會(huì)再?gòu)慕K端讀??!其實(shí)這里的 10恰好是回車符 !這就是為什么這個(gè)程序只執(zhí)行了一次輸入操作就結(jié)束的原因!
getch()和getche()函數(shù)
在TC2.0時(shí)代,C程序員總是喜歡在程序末尾加上getch()
,來(lái)實(shí)現(xiàn)程序運(yùn)行完了暫停不退出的效果。如果不這樣做,在TC2.0的環(huán)境中Ctrl+F9編譯并運(yùn)行后會(huì)立即退出程序,根本來(lái)不及看到結(jié)果。這時(shí)如果要看結(jié)果,就要按Alt+F5回到DOS環(huán)境中去,很麻煩。而如果在程序的結(jié)尾加上一行getch();
語(yǔ)句,就可以省掉回DOS看結(jié)果這個(gè)步驟,因?yàn)槌绦蜻\(yùn)行完了并不退出,而是在程序最后把屏幕停住了,按任意鍵才退出程序。
實(shí)際上, getch()
的作用是從鍵盤(pán) 接收一個(gè)字符,且不帶回顯 。就是說(shuō), 你按了一個(gè)鍵后它并不在屏幕上顯示你按的什么,而繼續(xù)運(yùn)行后面的代碼 ,所以在C語(yǔ)言中可以用它來(lái)實(shí)現(xiàn)“按任意鍵繼續(xù)”的效果,即程序中遇到getch();
語(yǔ)句,就會(huì)停下來(lái),等你按任意鍵,它接收了這個(gè)字符鍵后再繼續(xù)執(zhí)行后面的代碼。這跟上面在Windows下用的system(“PAUSE")功能一樣,但卻不會(huì)在屏幕上顯示(即不會(huì)有”按任意鍵繼續(xù)“的提示),這樣,利用getch()
無(wú)回顯的特性,不管你按什么鍵,都不會(huì)在屏幕上留下痕跡,使你的界面達(dá)到美觀效果。。
getche()
和getch()
很相似,它也需要引入頭文件conio.h,它們之間的區(qū)別就在于:getch()
無(wú)回顯,getche()
有回顯。
下面看一個(gè)例子:
首先這是個(gè)連續(xù)5次的循環(huán)來(lái)實(shí)現(xiàn)5次停頓,等待你輸入。編譯并運(yùn)行這個(gè)程序,假設(shè)輸入的是abcde,那么屏幕上顯示的結(jié)果也是abcde,這個(gè)abcde并不是在ch=getch();中輸出的。把printf("%c",ch);
這行語(yǔ)句去掉,就會(huì)發(fā)現(xiàn)按5次任意鍵程序就結(jié)束了,但屏幕上什么都沒(méi)有顯示。
你可以把代碼中的getch()
換成getche()
看看有什么不同。如果還是輸入abcde,那么屏幕上顯示的結(jié)果是aabbccddee,我們把printf("%c",ch);
這行語(yǔ)句再去掉,顯示的結(jié)果就是abcde了,說(shuō)明程序在執(zhí)行ch=getche();
這條語(yǔ)句的時(shí)候就把我們輸入的鍵返回顯示在屏幕上, 有無(wú)回顯就是它們的唯一區(qū)別 。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)我們的支持。
欄 目:C語(yǔ)言
下一篇:c/c++ 標(biāo)準(zhǔn)庫(kù) bind 函數(shù)詳解
本文標(biāo)題:C語(yǔ)言中輸入輸出流與緩沖區(qū)的深入講解
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/675.html
您可能感興趣的文章
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用函數(shù)刪除字符
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)式函數(shù)庫(kù)
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)數(shù)怎么表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫(xiě)分段 用c語(yǔ)言表示分段函數(shù)
- 04-02c語(yǔ)言編寫(xiě)函數(shù)冒泡排序 c語(yǔ)言冒泡排序法函數(shù)
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段函數(shù)
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎么打出三角函數(shù)的值
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求階乘


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 04-02c語(yǔ)言函數(shù)調(diào)用后清空內(nèi)存 c語(yǔ)言調(diào)用
- 04-02func函數(shù)+在C語(yǔ)言 func函數(shù)在c語(yǔ)言中
- 04-02c語(yǔ)言的正則匹配函數(shù) c語(yǔ)言正則表達(dá)
- 04-02c語(yǔ)言用函數(shù)寫(xiě)分段 用c語(yǔ)言表示分段
- 04-02c語(yǔ)言中對(duì)數(shù)函數(shù)的表達(dá)式 c語(yǔ)言中對(duì)
- 04-02c語(yǔ)言編寫(xiě)函數(shù)冒泡排序 c語(yǔ)言冒泡排
- 04-02c語(yǔ)言沒(méi)有round函數(shù) round c語(yǔ)言
- 04-02c語(yǔ)言分段函數(shù)怎么求 用c語(yǔ)言求分段
- 04-02C語(yǔ)言中怎么打出三角函數(shù) c語(yǔ)言中怎
- 04-02c語(yǔ)言調(diào)用函數(shù)求fibo C語(yǔ)言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置
- 01-10delphi制作wav文件的方法
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 04-02jquery與jsp,用jquery
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 01-11Mac OSX 打開(kāi)原生自帶讀寫(xiě)NTFS功能(圖文