getchar scanf以及緩衝區的概念

2022-08-21 13:48:13 字數 4713 閱讀 2588

1、getchar()是stdio.h中的庫函式,它的作用是從stdin流中讀入乙個字元,也就是說,如果stdin有資料的話不用輸入它就可以直接讀取了。

getch()和getche()是conio.h中的庫函式,它的作用是從鍵盤接收字元,getchar帶有回顯。

與前面兩個函式的區別在於: getchar()函式等待輸入直到按回車才結束(前提是緩衝區沒有資料),回車前的所有輸入字元都會逐個顯示在螢幕上。但只有第乙個字元作為函式的返回值。

1 #include "stdio.h"

2 #include "stdlib.h"

3 int main(void)

4 程式執行時,首先停下來,等你輸入一串字串,輸入完畢後,它把你輸入的整個字串都輸出來了,咦,你不是說getchar()只返回第乙個字元麼,這裡怎麼?

因為我們輸入的字串並不是取了第乙個字元就把剩下的字串丟掉了,它還在我們的記憶體中,好比,開閘放水,我們把水放到閘裡去以後,開一次閘就放掉一點,開一次就放掉一點,直到放光了為止,這裡開閘動作就相當於呼叫一次getchar()。我們輸入的字串也是這麼一回事,首先我們輸入的字串是放在記憶體的緩衝區中的,我們呼叫一次getchar()就把緩衝區中里出口最近的乙個字元輸出,也就是最前面的乙個字元輸出,輸出後,就把它釋放掉了,但後面還有字串,所以我們就用迴圈把最前面的乙個字元乙個個的在記憶體中釋放掉,直到滿足迴圈條件退出為止。

例子中迴圈條件裡的'\n '實際上就是你輸入字串後的回車符,所以意思就是說,直到遇到回車符才結束迴圈,而getchar()函式就是等待輸入(或緩衝區中的資料)直到按回車才結束,所以實現了整個字串的輸出。當然,我們也可以把迴圈條件改一下,比如while ((c=getchar())!='a'),什麼意思呢,意思就是遇到字元'a'就停止迴圈,當然意思是如果你輸入"12345a213123 "那麼只會輸出到a前面的那個字元,結果是12345。

再次注意:用getchar()它是從"流"中間去讀取,所以第乙個getchar()接受的是剛剛中斷的流佇列中即將出列的第乙個字元(不限於回車符,上面舉過例子了),如果流佇列不為空,執行getchar()就繼續放水,直到把回車符也放空為止,空了之後再在執行getchar()就停下等待你的輸入了;我們用getch()為什麼每次都是等待使用者的輸入呢?因為getch()是從鍵盤接收,即時的接收,並不是從stdin流中去讀取資料。

下面是我的討論:

先來一段code:

1 #include "stdio.h"

2 #include "stdlib.h"

3 4 int main(void)

5 輸入:  ssss回車

得到:   ssss

游標處(等待輸入)

說明:由於一直沒有輸入字元a,所以此時程式沒有結束,進入到for迴圈後一直沒有退出。鍵入回車後,執行c=getchar(),依次從緩衝區內取出(for迴圈):'s''s''s''s'' ' 包括回車的換行符,並將其全部列印了出來。。

如果我們輸入:ssssa回車

得到:ssss游標處(等待輸入)

說明:程式讀入到字元a的時候跳出了for迴圈,但是由於我們用getchar();清除了換行符'\n ',後面第7句c=getchar();需要你輸入乙個字元(因為ssssa後面並沒有新的字元),所以程式仍然沒有結束。如果我們注釋掉getchar();這一句,那麼c=getchar();這行**就可以讀取ssssa後面的回車符號了,就可以得到這樣的輸出:  

ssss

游標處(程式結束)

這個輸入ssssa中的回車中的換行符'\n '就被c=getchar();這一句讀取並輸出了。

總結:

鍵盤輸入的字元都存到緩衝區內,一旦鍵入回車,getchar就進入緩衝區讀取字元,一次只返回第乙個字元作為getchar函式的值,如果有迴圈或足夠多的getchar語句,就會依次讀出緩衝區內的所有字元直到'\n '。要理解這一點,之所以你輸入的一系列字元被依次讀出來,是因為迴圈的作用使得反覆利用getchar在緩衝區裡讀取字元,而不是getchar可以讀取多個字元,事實上getchar每次只能讀取乙個字元。如果需要取消' \n'的影響,可以用getchar();來清除,這裡getchar();只是取得了'\n '但是並沒有賦給任何字元變數,所以不會有影響,相當於清除了這個字元,還要注意的是這裡你在鍵盤上輸入ssss看到的回顯正是來自於getchar的作用,如果用getch就看不到你輸入了什麼。

2、scanf

scanf這個庫函式比較奇怪,而且存在一定的缺陷,所以很多人都不用了,這裡還是要簡單介紹一下。

scanf輸入字串、整型、實型等資料判斷的方式都一樣,回車、空格、tab鍵都認為是乙個資料的結束,當然字元的話,乙個字元就是結束了。回車、空格等都有對應的ascii碼,所以用scanf輸入字元時要小心這些東西被當成字元輸進去,而輸入字串和整型、實型等資料時這些都被當成分隔符而不會被輸入到字元陣列或變數裡。當然如果輸入格式不是"%s%s"而是"%s,%s"分隔符就是逗號了。

說了這麼多舉幾個例子:

1 #include "stdio.h"23

int main(void)

4 輸入:

hello回車

world回車

得到如下的輸出:

n1=hello,n2=wolrd游標處(程式結束)

這裡hello後面就是輸入再多個回車、空格也不會被賦值到n2中的,因為使用scanf函式輸入字串的時候他們只是被當做分隔符。另外就是輸入n2的時候,n2後面的那個回車也被當做了分隔符,所以輸出的時候,只是簡單的輸出了n1和n2的內容,而沒有輸出回車換行符。

如果輸入:

hello回車

游標處(等待輸入)

說明回車被認成分隔符,所以程式還要你輸入乙個字串來賦給n2。

其實這時緩衝區裡是有乙個'\n '被留下來的,程式改成這樣:

1 #include "stdio.h"23

int main(void)

4 輸入:

hello回車

world回車

得到:  

n1=hello,n2=wolrd

游標處(程式結束)

如果取消最後兩行的注釋,同樣的輸入得到:

n1=hello,n2=wolrd

游標處(等待輸入)

說明此時緩衝區內只有乙個'\n ',第二個getchar就需要你再輸入乙個字元了,緩衝區內已經沒有字元了。

scanf不會把回車、空格賦給字串但是會賦給字元,就如同getchar一樣,這時就要考慮'\n '的存在了。

比如: 

1 #include "stdio.h"

2 3 int main(void)

4 輸入:

hello回車

得到:n1=hello,n2=10游標處(程式結束)    //10是'\n '的ascii碼.

如果輸入:

hello 空格回車(一定要有回車,因為scanf也是要等回車,準確說是' \n'才會去讀緩衝區的。)

得到:n1=hello,n2=32游標處(程式結束)    //32是空格的ascii碼。

再羅嗦一下,如果最後一句輸出n2=%d改成n2=%c,則輸入:

hello回車

得到:n1=hello,n2=

游標處(程式結束)

是不是和getchar一樣可以把'\n '讀出來呢,呵呵。

總結一下就是:

如果scanf輸入的不是字元,那麼分隔符為回車,空格、tab鍵時,兩個資料之間的分隔符只是起區別兩個資料的作用,把分隔好的兩個資料分別賦值到各自定義好的變數或陣列中去,兩個資料之間的分隔符被從緩衝區讀出但是不起任何作用,當然最後乙個'\n '會被留在緩衝區內,除非用getchar();或scanf("%c",&c);把它讀出來。

回車是一定要有的,不管getchar還是scanf只要是通過緩衝區輸入資料的函式都是等待回車鍵'\n '出現才進入緩衝區的。再來個整型資料、字串、字元的混合例子:

1 #include "stdio.h"

2 3 int main(void)

4 輸入:

12(若干空格或回車都不影響結果,這裡用了回車)

34(這裡還要求輸入,因為scanf只得到了乙個整型資料,而緩衝區內沒有整型資料了。要有回車或空格表示這個資料結束了,留下來的空格或回車被下個%c接受,這裡用了回車,可以試一下空格)

45 jfdkjfa(回車)

得到:a=12,b=34,n2=

,c=45,n1=jfdkjfa,n3=

游標處(程式結束)

這裡說明一下過程:在前兩個整型資料輸入時,兩個資料之間無論是回車還是若干空格都被scanf當做分隔符,好了,scanf讀到分隔符(回車或空格)時,把第乙個整型資料送到變數a中,緩衝區中留下分隔符和下面的整型資料,這時scanf再讀當然先讀分隔符,但是要求輸入的還是整型資料(%d),所以分隔符被忽略,如果這時要求輸入字元%c(不是字串%s),那麼分隔符將以乙個位元組的形式送到字元變數裡,就如同這裡的n2。同理可以知道c和n1的儲存過程,最後的n3正是接收了輸入時的最後乙個回車。

好了如果看到這裡你都理解了那麼看最後乙個例子:

1 #include "stdio.h"

2 3 int main(void)

4 輸入:

95回車

得到:95,

游標處(程式結束)

很明顯這是由於分隔符(回車)被getchar讀取並輸出了,如果加入一句:getchar();

1 #include "stdio.h"

2 3 int main(void)

4 輸入:

95回車

c回車得到:

95,c游標處(程式結束)

exoplayer控制快取大小以及修改快取條件

在建立player的時候,加入loadcontrol類。來控制快取大小以及決定是否快取,我們可以建立乙個類,完全複製defaultloadcontrol 裡的內容 定義defaultloadcontrol loadcontrol new defaultloadcontrol 可以看到 然後修改部分引...

python的xlwt不能正確寫入以及緩衝區問題

最近在使用python的xlwt模組,它和xlrd xlutil顯然從名字上看得出是一套體系。然後在寫入的時候發生了一些故事。我不能正確的將很多資料寫到乙個檔案裡面。這個檔案儘管對於excel來說還不是很大,總共1.5m左右,幾萬個資料。但是並不像很多人說的那樣,4096個位元組的緩衝區,如果接近此...

js緩動演算法以及應用場景 vue

store mapcontainer.js state largepassengerflow null,大客流的定時器 largepassengerdata 大客流的定時器 動態 10假資料 largepassengerslowdata 大客流緩動5 5s後的資料 largepassengerslo...