日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

淺談getchar()和putchar()

 珊瑚海妖 2019-05-08

1.getchar()是標準I/O標準庫里的庫函數(shù)

原型是int getchar(void)-----------它沒有參數(shù),原因是因為它是從stdin標準輸入流中讀入一個字符的函數(shù),已經有了默認的流參數(shù)stdin了。其返回值是一個整型數(shù),是用來表示字符用的。

輸入輸出往往都是內存與外設之間的數(shù)據來往,但是,內存的運行效率比外設的運行效率那要大得多,比如,從內存寫一個字符到磁盤上,內存很快地傳出字符數(shù)據,供給磁盤存儲,磁盤花了很多的時間來存儲,在這段存儲的時間里,我們寶貴的內存只能干等著磁盤做完存儲操作來傳遞下一個字符,這樣的做法是非常浪費內存的。所以計算機牛人們就設計出了緩沖的概念,來緩和內存與外設之間速度不匹配的問題。這意味著程序的輸入輸出已經不是跟外設直接打交道了,而是從一塊被稱為緩沖區(qū)的內存區(qū)域來回復制數(shù)據。就C程序而言,所有的IO操作只是簡單地從程序移進移出字節(jié),這種字節(jié)流即為流。

回到getchar()函數(shù)中來,我們以下面一個程序為例。

#include<stdio.h>  
void main()
{
    char ch1 = getchar();  //從輸入流中讀取一個字符  
    char ch2 = getchar(); //從緩沖區(qū)中讀取第二個字符 
    printf("%c\n", ch1);
    printf("%c\n", ch2);
}


結果會顯示什么呢?如果是幾年前的我肯定會回答說:“當然從ch1是第一次輸入的字符,ch2是第二次輸入的字符唄!”真的是這樣子嗎?如果你實踐一下馬上就會出現(xiàn)問題:為啥控制臺界面只給我一次輸入的機會呢?

第一種情況:如果你的輸入只有一個字符,那么肯定的,ch1的值便是這個字符,那么ch2呢?在這里別忘了,你輸完前一個字符后是通過什么結束輸入的?是的,是Enter,Enter肯定會說:“人家可也是個正正經經的字符啊,不要不把無字幕的字符不當字符??!”是的,在這里是向緩沖區(qū)中輸入了兩個字符,而getchar()是做什么呢?前面提到了,程序可不是直接跟外設打交道的,而是跟緩沖區(qū)打交道的,所以,getchar()庫函數(shù)是從緩沖區(qū)中讀取字符而不是從鍵盤讀取字符的,所以,你已經向緩沖區(qū)中輸入了兩個字符夠上面程序中兩個getchar()讀的了。可以用下面的程序測試一下這種效果。

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

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

如果在第一次輸入的時候不是簡單的輸入一個字符和一個換行,而是輸入了一大堆字符,那么,這些字符將全部送往stdin流的緩沖區(qū)中,后面的所有包括getchar()的將從stdin流中讀入數(shù)據的庫函數(shù)將從這個緩沖區(qū)中讀入數(shù)據,直道緩沖區(qū)再次為空后,才提示輸入設備準備輸入數(shù)據。

一、getchar的兩點總結:
1.getchar是以行為單位進行存取的。
當用getchar進行輸入時,如果輸入的第一個字符為有效字符(即輸入是文件結束符EOF,Windows下為組合鍵Ctrl+Z, Unix/Linux下為組合鍵Ctrl+D),那么只有當最后一個輸入字符為換行符'\n'(也可以說是EOF)時, getchar才會停止執(zhí)行,整個程序將會往下執(zhí)行。譬如下面程序段: 可以清空緩沖區(qū)

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

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


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

對這個問題的一個解釋是,在大師編寫C的時候,當時并沒有所謂終端輸入的概念,所有的輸入實際上都是按照文件進行讀取的,文件中一般都是以行為單位的。因 此,只有遇到換行符,那么程序會認為輸入結束,然后采取執(zhí)行程序的其他部分。同時,輸入是按照文件的方式存取的,那么要結束一個文件的輸入就需用到EOF (Enf Of File). 這也就是為什么getchar結束輸入退出時要用EOF的原因。

2.getchar()的返回值一般情況下是字符,但也可能是負值,即返回EOF。

這里要強調的一點就是,getchar函數(shù)通常返回終端所輸入的字符,這些字符系統(tǒng)中對應的ASCII值都是非負的。因此,很多時候,我們會寫這樣的兩行代碼:
char c;
c = getchar();

這樣就很有可能出現(xiàn)問題。因為getchar函數(shù)除了返回終端輸入的字符外,在遇到Ctrl+D(Linux下)即文件結束符EOF時,getchar ()的返回EOF,這個EOF在函數(shù)庫里一般定義為-1。因此,在這種情況下,getchar函數(shù)返回一個負值,把一個負值賦給一個char型的變量是不 正確的。為了能夠讓所定義的變量能夠包含getchar函數(shù)返回的所有可能的值,正確的定義方法如下(K&R C中特別提到了這個問題):
int c;
c = getchar();

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

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

2.EOF作為行結束符時的情況,這時候輸入Ctrl+D并不能結束getchar(),而只能引發(fā)getchar()提示下一輪的輸入。

這種情況主要是在進行getchar()新的一行輸入時,當輸入了若干字符(不能包含換行符)之后,直接輸入Ctrl+D,此時的Ctrl+D并不是文件 結束符,而只是相當于換行符的功能,即結束當前的輸入。以上面的代碼段為例,如果執(zhí)行時輸入abc,然后Ctrl+D,程序輸出結果為:
abcabc

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

其中第一行為終端輸入,第二行為終端輸出,光標停在了第三行處,等待新一次的終端輸入。
從這里也可以看出Ctrl+D和換行符分別作為行結束符時,輸出的不同結果。
EOF的作用也可以總結為:當終端有字符輸入時,Ctrl+D產生的EOF相當于結束本行的輸入,將引起getchar()新一輪的輸入;當終端沒有字符 輸入或者可以說當getchar()讀取新的一次輸入時,輸入Ctrl+D,此時產生的EOF相當于文件結束符,程序將結束getchar()的執(zhí)行。

順便提一下輸出庫函數(shù)。輸出庫函數(shù)的效果也只是將程序中的內容輸出到緩沖區(qū)中,然后再刷新的時候輸出到外設上,如果在輸出的時候輸出輸出流stdout緩沖區(qū)中已經有了數(shù)據,那么輸出的是已經有的內容,而不一定是你輸出的內容。這是由緩沖區(qū)刷新的時間控制的,刷新的操作是根據具體的編譯器來決定的,一般調用fflush(stdout)來刷新一下stdout緩沖區(qū)。



    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點。請注意甄別內容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內容,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多