|
1.getchar()是標(biāo)準(zhǔn)I/O標(biāo)準(zhǔn)庫(kù)里的庫(kù)函數(shù) 原型是int getchar(void)-----------它沒(méi)有參數(shù),原因是因?yàn)樗菑膕tdin標(biāo)準(zhǔn)輸入流中讀入一個(gè)字符的函數(shù),已經(jīng)有了默認(rèn)的流參數(shù)stdin了。其返回值是一個(gè)整型數(shù),是用來(lái)表示字符用的。 輸入輸出往往都是內(nèi)存與外設(shè)之間的數(shù)據(jù)來(lái)往,但是,內(nèi)存的運(yùn)行效率比外設(shè)的運(yùn)行效率那要大得多,比如,從內(nèi)存寫(xiě)一個(gè)字符到磁盤(pán)上,內(nèi)存很快地傳出字符數(shù)據(jù),供給磁盤(pán)存儲(chǔ),磁盤(pán)花了很多的時(shí)間來(lái)存儲(chǔ),在這段存儲(chǔ)的時(shí)間里,我們寶貴的內(nèi)存只能干等著磁盤(pán)做完存儲(chǔ)操作來(lái)傳遞下一個(gè)字符,這樣的做法是非常浪費(fèi)內(nèi)存的。所以計(jì)算機(jī)牛人們就設(shè)計(jì)出了緩沖的概念,來(lái)緩和內(nèi)存與外設(shè)之間速度不匹配的問(wèn)題。這意味著程序的輸入輸出已經(jīng)不是跟外設(shè)直接打交道了,而是從一塊被稱(chēng)為緩沖區(qū)的內(nèi)存區(qū)域來(lái)回復(fù)制數(shù)據(jù)。就C程序而言,所有的IO操作只是簡(jiǎn)單地從程序移進(jìn)移出字節(jié),這種字節(jié)流即為流。 回到getchar()函數(shù)中來(lái),我們以下面一個(gè)程序?yàn)槔?/span> #include<stdio.h> 第一種情況:如果你的輸入只有一個(gè)字符,那么肯定的,ch1的值便是這個(gè)字符,那么ch2呢?在這里別忘了,你輸完前一個(gè)字符后是通過(guò)什么結(jié)束輸入的?是的,是Enter,Enter肯定會(huì)說(shuō):“人家可也是個(gè)正正經(jīng)經(jīng)的字符啊,不要不把無(wú)字幕的字符不當(dāng)字符啊!”是的,在這里是向緩沖區(qū)中輸入了兩個(gè)字符,而getchar()是做什么呢?前面提到了,程序可不是直接跟外設(shè)打交道的,而是跟緩沖區(qū)打交道的,所以,getchar()庫(kù)函數(shù)是從緩沖區(qū)中讀取字符而不是從鍵盤(pán)讀取字符的,所以,你已經(jīng)向緩沖區(qū)中輸入了兩個(gè)字符夠上面程序中兩個(gè)getchar()讀的了。可以用下面的程序測(cè)試一下這種效果。
如果在第一次輸入的時(shí)候不是簡(jiǎn)單的輸入一個(gè)字符和一個(gè)換行,而是輸入了一大堆字符,那么,這些字符將全部送往stdin流的緩沖區(qū)中,后面的所有包括getchar()的將從stdin流中讀入數(shù)據(jù)的庫(kù)函數(shù)將從這個(gè)緩沖區(qū)中讀入數(shù)據(jù),直道緩沖區(qū)再次為空后,才提示輸入設(shè)備準(zhǔn)備輸入數(shù)據(jù)。 一、getchar的兩點(diǎn)總結(jié): while((c = getchar()) != EOF){ 執(zhí)行程序,輸入:abc,然后回車(chē)。則程序就會(huì)去執(zhí)行puchar(c),然后輸出abc,這個(gè)地方不要忘了,系統(tǒng)輸出的還有一個(gè)回車(chē)。然后可以繼續(xù)輸入,再次遇到換行符的時(shí)候,程序又會(huì)把那一行的輸入的字符輸出在終端上。
對(duì)這個(gè)問(wèn)題的一個(gè)解釋是,在大師編寫(xiě)C的時(shí)候,當(dāng)時(shí)并沒(méi)有所謂終端輸入的概念,所有的輸入實(shí)際上都是按照文件進(jìn)行讀取的,文件中一般都是以行為單位的。因 此,只有遇到換行符,那么程序會(huì)認(rèn)為輸入結(jié)束,然后采取執(zhí)行程序的其他部分。同時(shí),輸入是按照文件的方式存取的,那么要結(jié)束一個(gè)文件的輸入就需用到EOF (Enf Of File). 這也就是為什么getchar結(jié)束輸入退出時(shí)要用EOF的原因。 2.getchar()的返回值一般情況下是字符,但也可能是負(fù)值,即返回EOF。 這里要強(qiáng)調(diào)的一點(diǎn)就是,getchar函數(shù)通常返回終端所輸入的字符,這些字符系統(tǒng)中對(duì)應(yīng)的ASCII值都是非負(fù)的。因此,很多時(shí)候,我們會(huì)寫(xiě)這樣的兩行代碼: 這樣就很有可能出現(xiàn)問(wèn)題。因?yàn)間etchar函數(shù)除了返回終端輸入的字符外,在遇到Ctrl+D(Linux下)即文件結(jié)束符EOF時(shí),getchar ()的返回EOF,這個(gè)EOF在函數(shù)庫(kù)里一般定義為-1。因此,在這種情況下,getchar函數(shù)返回一個(gè)負(fù)值,把一個(gè)負(fù)值賦給一個(gè)char型的變量是不 正確的。為了能夠讓所定義的變量能夠包含getchar函數(shù)返回的所有可能的值,正確的定義方法如下(K&R C中特別提到了這個(gè)問(wèn)題): 二、EOF的兩點(diǎn)總結(jié)(主要指普通終端中的EOF) EOF雖然是文件結(jié)束符,但并不是在任何情況下輸入Ctrl+D(Windows下Ctrl+Z)都能夠?qū)崿F(xiàn)文件結(jié)束的功能,只有在下列的條件下,才作為文件結(jié)束符。 2.EOF作為行結(jié)束符時(shí)的情況,這時(shí)候輸入Ctrl+D并不能結(jié)束getchar(),而只能引發(fā)getchar()提示下一輪的輸入。 這種情況主要是在進(jìn)行g(shù)etchar()新的一行輸入時(shí),當(dāng)輸入了若干字符(不能包含換行符)之后,直接輸入Ctrl+D,此時(shí)的Ctrl+D并不是文件 結(jié)束符,而只是相當(dāng)于換行符的功能,即結(jié)束當(dāng)前的輸入。以上面的代碼段為例,如果執(zhí)行時(shí)輸入abc,然后Ctrl+D,程序輸出結(jié)果為: 注意:第一組abc為從終端輸入的,然后輸入Ctrl+D,就輸出第二組abc,同時(shí)光標(biāo)停在第二組字符的c后面,然后可以進(jìn)行新一次的輸入。這時(shí)如果再次輸入Ctrl+D,則起到了文件結(jié)束符的作用,結(jié)束getchar()。 從這里也可以看出Ctrl+D和換行符分別作為行結(jié)束符時(shí),輸出的不同結(jié)果。 EOF的作用也可以總結(jié)為:當(dāng)終端有字符輸入時(shí),Ctrl+D產(chǎn)生的EOF相當(dāng)于結(jié)束本行的輸入,將引起getchar()新一輪的輸入;當(dāng)終端沒(méi)有字符 輸入或者可以說(shuō)當(dāng)getchar()讀取新的一次輸入時(shí),輸入Ctrl+D,此時(shí)產(chǎn)生的EOF相當(dāng)于文件結(jié)束符,程序?qū)⒔Y(jié)束getchar()的執(zhí)行。 順便提一下輸出庫(kù)函數(shù)。輸出庫(kù)函數(shù)的效果也只是將程序中的內(nèi)容輸出到緩沖區(qū)中,然后再刷新的時(shí)候輸出到外設(shè)上,如果在輸出的時(shí)候輸出輸出流stdout緩沖區(qū)中已經(jīng)有了數(shù)據(jù),那么輸出的是已經(jīng)有的內(nèi)容,而不一定是你輸出的內(nèi)容。這是由緩沖區(qū)刷新的時(shí)間控制的,刷新的操作是根據(jù)具體的編譯器來(lái)決定的,一般調(diào)用fflush(stdout)來(lái)刷新一下stdout緩沖區(qū)。 |
|
|
來(lái)自: 珊瑚海妖 > 《待分類(lèi)》