小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

淺談getchar()和putchar()

 珊瑚海妖 2019-05-08

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>  
void main()
{
    char ch1 = getchar();  //從輸入流中讀取一個(gè)字符  
    char ch2 = getchar(); //從緩沖區(qū)中讀取第二個(gè)字符 
    printf("%c\n", ch1);
    printf("%c\n", ch2);
}


結(jié)果會(huì)顯示什么呢?如果是幾年前的我肯定會(huì)回答說(shuō):“當(dāng)然從ch1是第一次輸入的字符,ch2是第二次輸入的字符唄!”真的是這樣子嗎?如果你實(shí)踐一下馬上就會(huì)出現(xiàn)問(wèn)題:為啥控制臺(tái)界面只給我一次輸入的機(jī)會(huì)呢?

第一種情況:如果你的輸入只有一個(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è)試一下這種效果。

  1. #include<stdio.h>  
  2. void main()  
  3. {  
  4.     char ch1 = getchar();  //從緩沖區(qū)中讀取第一個(gè)字符  
  5.     char ch2 = getchar();  //從緩沖區(qū)中讀取第二個(gè)字符  
  6.     getchar();  //從緩沖區(qū)中讀取第三個(gè)字符  
  7.     printf("%c\n",ch1);  
  8.     printf("%c\n",ch2);  

在上面的程序中,有三次讀入,所以如果你的輸入是一個(gè)字符和一個(gè)換行,那么第三個(gè)getchar()在讀stdin的緩沖區(qū)的時(shí)候發(fā)現(xiàn)緩沖區(qū)是空的,會(huì)提示輸入設(shè)備輸入數(shù)據(jù),這里便可以再次輸入了。

如果在第一次輸入的時(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é):
1.getchar是以行為單位進(jìn)行存取的。
當(dāng)用getchar進(jìn)行輸入時(shí),如果輸入的第一個(gè)字符為有效字符(即輸入是文件結(jié)束符EOF,Windows下為組合鍵Ctrl+Z, Unix/Linux下為組合鍵Ctrl+D),那么只有當(dāng)最后一個(gè)輸入字符為換行符'\n'(也可以說(shuō)是EOF)時(shí), getchar才會(huì)停止執(zhí)行,整個(gè)程序?qū)?huì)往下執(zhí)行。譬如下面程序段: 可以清空緩沖區(qū)

while((c = getchar()) != EOF){
    putchar(c);
}

執(zhí)行程序,輸入:abc,然后回車(chē)。則程序就會(huì)去執(zhí)行puchar(c),然后輸出abc,這個(gè)地方不要忘了,系統(tǒng)輸出的還有一個(gè)回車(chē)。然后可以繼續(xù)輸入,再次遇到換行符的時(shí)候,程序又會(huì)把那一行的輸入的字符輸出在終端上。


對(duì)于getchar,肯定很多初學(xué)的朋友會(huì)問(wèn),getchar不是以字符為單位讀取的嗎?那么,既然我輸入了第一個(gè)字符a,肯定滿足while循環(huán)(c = getchar()) != EOF的條件阿,那么應(yīng)該執(zhí)行putchar(c)在終端輸出一個(gè)字符a。不錯(cuò),我在用getchar的時(shí)候也是一直這么想的,但是程序就偏偏不著樣執(zhí) 行,而是必需讀到一個(gè)換行符或者文件結(jié)束符EOF才進(jìn)行一次輸出。

對(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ě)這樣的兩行代碼:
char c;
c = getchar();

這樣就很有可能出現(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)題):
int c;
c = getchar();

二、EOF的兩點(diǎn)總結(jié)(主要指普通終端中的EOF)
1.EOF作為文件結(jié)束符時(shí)的情況:

EOF雖然是文件結(jié)束符,但并不是在任何情況下輸入Ctrl+D(Windows下Ctrl+Z)都能夠?qū)崿F(xiàn)文件結(jié)束的功能,只有在下列的條件下,才作為文件結(jié)束符。
(1)遇到getcahr函數(shù)執(zhí)行時(shí),要輸入第一個(gè)字符時(shí)就直接輸入Ctrl+D,就可以跳出getchar(),去執(zhí)行程序的其他部分;
(2)在前面輸入的字符為換行符時(shí),接著輸入Ctrl+D;
(3)在前面有字符輸入且不為換行符時(shí),要連著輸入兩次Ctrl+D,這時(shí)第二次輸入的Ctrl+D起到文件結(jié)束符的功能,至于第一次的Ctrl+D的作用將在下面介紹。
其實(shí),這三種情況都可以總結(jié)為只有在getchar()提示新的一次輸入時(shí),直接輸入Ctrl+D才相當(dāng)于文件結(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é)果為:
abcabc

注意:第一組abc為從終端輸入的,然后輸入Ctrl+D,就輸出第二組abc,同時(shí)光標(biāo)停在第二組字符的c后面,然后可以進(jìn)行新一次的輸入。這時(shí)如果再次輸入Ctrl+D,則起到了文件結(jié)束符的作用,結(jié)束getchar()。
如果輸入abc之后,然后回車(chē),輸入換行符的話,則終端顯示為:
abc //第一行,帶回車(chē)
abc //第二行
//第三行

其中第一行為終端輸入,第二行為終端輸出,光標(biāo)停在了第三行處,等待新一次的終端輸入。
從這里也可以看出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ū)。



    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多