C語言中的getchar()使用詳解

前言

近期我在重新學習C語言時候,我發現瞭一個嚴重的問題,getchar我居然不會用瞭….也不是說不會用,我發現瞭一個非常讓我困惑想不明白的問題。可能我在第一次接觸C語言時候,就沒有把這個概念弄清楚吧,以至於現在會不明白。

getchar困惑的點

我利用getchar函數輸入瞭一串字符ABCD,然後把這串字符給到ch,然後緊接著我打印這個ch,然後我得到瞭一個字符A,看到這裡大傢沒有感覺有什麼問題對吧,當然沒有問題,因為getchar隻會讀一個字符,自然就隻讀到瞭A,然後打印時候也自然而然就隻打印瞭這個A出來。

好的我們接著往下看

看到這個我不知道大傢有沒有想到一個問題,反正我當時就是因為這個問題所困惑很久的。

首先通過第一個例子,我們知道瞭,getchar是隻會讀取一個字符

可是這個例子呢,我輸入瞭一串字符ABCDE,按理說他也隻是讀取到一個字符,那就是這串字符中的第一個字符A,然後讀取到瞭之後把它給瞭變量ch, 然後來判斷這個ch等不等於EOF。

EOF是文件結束標志,在鍵盤上也就是ctrl+z 大傢可以自己打印一下然後對照ASCII碼看一下

很顯然,當前這個裡面根本就沒有ctrl+z,所以條件為真,然後執行打印語句。

根據上面我們那段分析,然後應該打印一個字符A對嗎,疑惑的事情發生瞭,它打印瞭ABCDE!!!是的,完完整整打印出來瞭。

可能大傢經常見到這個類似程序,然後習以為常瞭,都覺得是應該完完整整打印出來

好的,講到這裡大傢是不是就覺得很困惑瞭,為什麼會這樣呢?

那我現在就好好給大傢講一下瞭,原來這裡面還涉及到瞭一個概念

緩沖區

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

那麼這個和我們的getchar又有什麼聯系呢?

當然有聯系,當我們調用瞭getchar函數時候,這個函數內部其實是這樣做的:

他此時會先從緩存區中讀一遍,此時讀完之後發現,緩存區中沒有數據,他就會等待外部輸入,光標此時就會一閃一閃的~ 

當我們外部輸入瞭字符之後,然後我們就會敲回車結束,這時候我們輸入的字符其實就直接全部存在瞭緩存區中。

假設我此時輸入瞭字符ABCD,然後回車結束,然後此時緩存區中就有瞭ABCD\n

註意,有意思的事情來瞭,還有\n ???哈哈哈哈接著往下看

緩沖區帶來的問題

大傢仔細看一下有沒有發現,為什麼我getchar沒有輸入字符呢 ?

其實不是我沒有輸入字符,隻是在我輸入完scanf的字符之後,回車結束這個scanf的輸入,然後奇怪的事情發生瞭,程序就直接結束瞭,是的,跳過瞭getchar輸入字符這個過程。

大傢有沒有覺得奇怪?

這就是我剛才上面給大傢提到的 \n

是這樣的,當我此時調用瞭scanf函數之後,我外部輸入瞭 ABCD,然後輸入完ABCD之後呢我要結束輸入,然後我們就會去敲回車,註意!!這個回車其實也是一個字符,然後他也會連同我前面輸入的ABCD一起放到緩存區,也就是說此時緩存區中就有瞭ABCD\n 

我們做一個小小的測試就知道瞭

看到這個打印的結果,大傢明白瞭吧

getchar工作原理

原來調用getchar函數的時候,它其實是直接從緩存區中讀,如果緩存區中有數據,他就會直接拿走第一個,然後他的使命也就結束瞭。其實這裡呢就是上面scanf在緩存區中拿走瞭ABCD,然後還剩下一個 10,這個10其實是\n ,是它在ASCII碼中的表示。於是這個剩下的\n就在緩存區中存下去瞭,然後他此時遇到瞭getchar函數,然後getchar在緩存區中讀,發現:誒,還剩一個\n,那麼我就直接拿走,然後他的使命也就便結束瞭,所以就出現瞭不會等待我們外部輸入的那種情況瞭。

那麼我們可以解決這個問題嗎?

解決緩沖區帶來的問題之清空緩存區

明白瞭緩沖區和getchar的聯系之後,其實我們想解決就很好辦瞭

我們隻需要在getchar讀取之前在插入一個getchar函數,也就是說讓他在下一次真正getchar讀取之前,我們先再用一個getchar函數讀一下那個緩存區剩下的\n,這樣下一次我們真正的getchar讀取時候,緩存區就空瞭。

好瞭getchar的工作原理我們徹底明白瞭,那麼我們在回到最初的那個疑惑上面。 

解決最初的困惑

第一次循環:首先緩存區為空,光標閃爍,然後等待我的輸入

我輸入瞭一個字符A,然後我繼續輸入瞭回車結束,那麼我此時其實輸入瞭兩個字符,一個字符A,一個字符 \n,此時他們都被存放在瞭緩存區。然後緩存區有瞭數據之後,光標此時不在閃爍,getchar函數便開始直接讀取,然後在這一次循環中,getchar函數讀取到瞭一個字符A,然後將它給到ch,然後條件表達式為真(不等於ctrl+z),所以執行打印ch,然後打印出瞭一個字符A。

第二次循環:這時候緩存區還殘留瞭一個\n,光標不閃爍,getchar也不會等待外部輸入

那麼此時getchar直接讀取到這個緩存區中的\n,繼續給到ch,然後表達式還是為真,所以繼續打印這個ch,此時因為ch已經是被換掉瞭\n,所以打印換行,光標位置發生改變。

第三次循環:緩存區為空,getchar讀取不到數據,光標閃爍,getchar等待外部輸入數據。

至此我們在接著往下看

 第一次循環:緩存區為空,getchar讀取不到緩存區的數據,於是光標閃爍,getchar等待外部輸入數據。

此時我輸入瞭一串ABC,然後回車結束輸入。此時緩存區中便有瞭字符ABCD\n,然後getchar讀取第一個字符A,然後將它給到ch,然後條件表達式為真,打印瞭ch,於是第一個A就出來瞭。

第二次循環:緩存區還剩餘BC\n,getchar直接讀取

此時getchar讀取到字符B,然後給到ch,條件表達式為真,繼續打印ch,此時便得到瞭AB。

第三次循環:緩存區還剩餘C\n,getchar直接讀取

然後還是一樣getchar讀取到C,然後給到ch,之後表達式為真,打印出來瞭ch,然後經過這一次循環就得到瞭ABC

第四次循環:緩存區還剩餘一個\n,最後打印這個\n,於是光標下一行。

最終結果就得到瞭ABC

然後我再次輸入 ctrl+Z

於是緩存區存在瞭ctrl+z(EOF),然後getchar去讀取,然後給到ch,然後表達式判斷,條件為假,ch==EOF,所以循環跳出,程序結束。

總結

getchar函數是直接從緩存區中讀取數據,如果緩存區中有數據,則直接讀取第一個數據,如果沒有數據,那麼就光標閃爍,等待外部輸入數據。

要非常註意的是,我們其他地方輸入的回車也會被存在緩存區當成一個字符,然後後面getchar也會將其直接讀出,在這個地方很容易出錯!!

到此這篇關於C語言中的getchar()使用詳解的文章就介紹到這瞭,更多相關C語言getchar()內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: