1、getchar()是stdio.h中的庫函數,它的作用是從stdin流中讀入一個字元,也就是說,如果stdin有資料的話不用輸入它就可以直接讀取了。
getch()和getche()是conio.h中的庫函數,它的作用是從鍵盤接收字元,getchar帶有回顯。
與前面兩個函數的區別在於: getchar()函數等待輸入直到按斷行符號才結束(前提是緩衝區沒有資料),斷行符號前的所有輸入字元都會逐個顯示在螢幕上。但只有第一個字元作為函數的傳回值。
#include "stdio.h"#include "stdlib.h"int main(void){char c;while((c=getchar())!='\n') //每個getchar()依次讀入一個字元printf("%c",c); //按照原樣輸出printf("\n");system("pause");return 0;}
程式運行時,首先停下來,等你輸入一串字串,輸入完畢後,它把你輸入的整個字串都輸出來了,咦,你不是說getchar()只返回第一個字元麼,這裡怎嗎?
因為我們輸入的字串並不是取了第一個字元就把剩下的字串丟掉了,它還在我們的記憶體中,好比,開閘放水,我們把水放到閘裡去以後,開一次閘就放掉一點,開一次就放掉一點,直到放光了為止,這裡開閘動作就相當於調用一次getchar()。我們輸入的字串也是這麼一回事,首先我們輸入的字串是放在記憶體的緩衝區中的,我們調用一次getchar()就把緩衝區中裡出口最近的一個字元輸出,也就是最前面的一個字元輸出,輸出後,就把它釋放掉了,但後面還有字串,所以我們就用迴圈把最前面的一個字元一個個的在記憶體中釋放掉,直到滿足迴圈條件退出為止。
例子中迴圈條件裡的'\n '實際上就是你輸入字串後的斷行符號符,所以意思就是說,直到遇到斷行符號符才結束迴圈,而getchar()函數就是等待輸入(或緩衝區中的資料)直到按斷行符號才結束,所以實現了整個字串的輸出。當然,我們也可以把迴圈條件改一下,比如while ((c=getchar())!='a'),什麼意思呢,意思就是遇到字元'a'就停止迴圈,當然意思是如果你輸入“12345a213123 ”那麼只會輸出到a前面的那個字元,結果是12345。
再次注意:用getchar()它是從“流”中間去讀取,所以第一個getchar()接受的是剛剛中斷的流隊列中即將出列的第一個字元(不限於斷行符號符,上面舉過例子了),如果流隊列不為空白,執行getchar()就繼續放水,直到把斷行符號符也放空為止,空了之後再在執行getchar()就停下等待你的輸入了;我們用getch()為什麼每次都是等待使用者的輸入呢?因為getch()是從鍵盤接收,即時的接收,並不是從stdin流中去讀取資料。
下面是我的討論:
先來一段code:
#include "stdio.h"#include "stdlib.h"int main(void){char c;for(;(c=getchar())!='a';)printf("%c",c);getchar();c=getchar();printf("%c",c);system("pause");return 0;}
輸入: 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"分隔字元就是逗號了。
說了這麼多舉幾個例子:
#include "stdio.h"int main(void){char n1[10];char n2[10];scanf("%s",n1);scanf("%s",n2);printf("n1=%s,n2=%s",n1,n2);return 0;}
輸入:
hello斷行符號
world斷行符號
得到如下的輸出:
n1=hello,n2=wolrd游標處(程式結束)
這裡hello後面就是輸入再多個斷行符號、空格也不會被賦值到n2中的,因為使用scanf函數輸入字串的時候他們只是被當做分隔字元。另外就是輸入n2的時候,n2後面的那個斷行符號也被當做了分隔字元,所以輸出的時候,只是簡單的輸出了n1和n2的內容,而沒有輸出斷行符號分行符號。
如果輸入:
hello斷行符號
游標處(等待輸入)
說明斷行符號被認成分隔字元,所以程式還要你輸入一個字串來賦給n2。
其實這時緩衝區裡是有一個'\n '被留下來的,程式改成這樣:
#include "stdio.h"int main(void) {char n1[10]; char n2[10];char n3,n4; scanf("%s",n1); scanf("%s",n2); printf("n1=%s,n2=%s",n1,n2);n3=getchar(); //n3讀取了n2後面的那個斷行符號字元並輸出printf("%c",n3);//n4=getchar();//printf("%c",n4); return 0;}
輸入:
hello斷行符號
world斷行符號
得到:
n1=hello,n2=wolrd
游標處(程式結束)
如果取消最後兩行的注釋,同樣的輸入得到:
n1=hello,n2=wolrd
游標處(等待輸入)
說明此時緩衝區內只有一個'\n ',第二個getchar就需要你再輸入一個字元了,緩衝區內已經沒有字元了。
scanf不會把斷行符號、空格賦給字串但是會賦給字元,就如同getchar一樣,這時就要考慮'\n '的存在了。
比如:
#include "stdio.h"int main(void) {char n1[10];char n2;scanf("%s",n1);scanf("%c",&n2);printf("n1=%s,n2=%d",n1,n2);return 0;}
輸入:
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 '出現才進入緩衝區的。再來個整型資料、字串、字元的混合例子:
#include "stdio.h"int main(void) {int a,b,c;char n1[10];char n2,n3;scanf("%d%d",&a,&b);scanf("%c",&n2);scanf("%d",&c);scanf("%s",n1);scanf("%c",&n3);printf("a=%d,b=%d,n2=%c,c=%d,n1=%s,n3=%c",a,b,n2,c,n1,n3);return 0;}
輸入:
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正是接收了輸入時的最後一個斷行符號。
好了如果看到這裡你都理解了那麼看最後一個例子:
#include "stdio.h"int main(void){int a;char ch;scanf("%d",&a);ch=getchar();printf("%d,%c",a,ch);return 0;}
輸入:
95斷行符號
得到:
95,
游標處(程式結束)
很明顯這是由於分隔字元(斷行符號)被getchar讀取並輸出了,如果加入一句:getchar();
#include "stdio.h"int main(void){int a;char ch;scanf("%d",&a);getchar();ch=getchar();printf("%d,%c",a,ch);return 0;}
輸入:
95斷行符號
c斷行符號
得到:
95,c游標處(程式結束)