c語言輸入輸出緩衝區

1.getchar

getchar()是stdio.h中的庫函數,它的作用是從stdin流中讀入一個字符,也就是說,如果stdin有數據的話不用輸入它就可以直接讀取 了。而getch()和getche()是conio.h中的庫函數,它的作用是從鍵盤接收字符。getchar帶有顯示。

與前面兩個函數的區別在於: getchar()函數等待輸入直到按回車才結束(前提是緩衝區沒有數據),回車前的所有輸入字符都會逐個顯示在屏幕上。但只有第一個字符作爲函數的返回值。

#include<stdio.h>
#include<conio.h>
void main()
{
char c;
c=getchar();
//getchar()在這裏它只返回你輸入字符串的第一個字符,並把返回值賦值給c
putchar(c);
printf("\n\n");
}



 


這個程序你運行一下,相信你又會有疑問了。這個就是從緩衝區中讀取了例子。第一次getchar()時,確實需要人工的輸入,但是如果你輸了多個字符,以後的getchar()再執行時就會直接從緩衝區中讀取了。

#include<stdio.h>

#include<conio.h>

void main()

{

char c;

while ((c=getchar())!='\n')

printf("%c",c);

printf("\n\n");

}





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

因爲我們輸入的字符串並不是取了第一個字符就把剩下的字符串丟掉了,它還在我們的內存中,就好比,開閘放水,我們把水放到閘裏去以後,開一次閘就放掉一點,開一次就放掉一點,直到放光了爲止,這裏開閘動作就相當於調用一次getchar()。我們輸入的字符串也是這麼一回事,首先我們輸入的字符串是放在內存的緩衝區中的,我們調用一次getchar()就把緩衝區中裏出口最近的一個字符輸出,也就是最前面的一個字符輸出,輸出後,就把它釋放掉了,但後面還有字符串,所以我們就用循環把最前面的一個字符一個個的在內存中釋放掉,直到不滿足循環條件退出爲止。

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

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

補充:按鍵盤上的回車產生了2個字符:回車符('\r')和換行符('\n')。回車符'\r'(CR:carriage return:倒車)使光標回到這行的首部,換行符('\n')(new line)然後再換行。

所以當輸入字符'w',並按下回車鍵以後。首先得到回車符。那個getchar函數結束了。 但是還存在一個換行符。所以如果用getchar()來做判斷的時候。最好再寫一次getchar()清除緩衝區的'\n'.

3.如何清空輸入緩衝區的內容?

如果我想讓getchar()每次都能夠等待用戶輸入的話就要清空緩衝區,下面就介紹方法(不同平臺)

C標準規定 fflush()函數是用來刷新輸出(stdout)緩存的。對於輸入(stdin),它是沒有定義的。但是有些編譯器也定義了 fflush( stdin )的實現,比如微軟的VC。其它編譯器是否也定義了 fflush( stdin )的實現應當查找它的手冊。GCC編譯器沒有定義它的實現,所以不能使用 fflush( stdin )來刷新輸入緩存。

對於沒有定義 fflush( stdin )的編譯器,可以使用 fgets()函數來代替它(比用 getchar()、scanf()等函數通用性好)。可以這樣忽略輸入流中留下的回車等其它輸入,從而使下一次的輸入總保持一個“乾淨”的狀態。(這個是任何平臺下都可以的)


char sbuf[1024];
// ...

fgets( sbuf, 1024, stdin );
// ...


在windows的vc下面就可以這樣了:

for(int i=0;i<10;++i)

{

char ch=getchar();

fflush(stdin); //每次都會有等待狀態了


}

這裏說到gcc編譯器沒有定義fflush的實現,我們一般用getchar();來清除緩衝區.

下面是我的討論:
先來一段code:

#include <stdio.h>
main()
{
char c;
for(;(c=getchar())!='a';)
printf("%c",c);
getchar();
c=getchar();
printf("%c",c);
}


輸入:
ssss
回車
得到:
ssss
光標處(等待輸入)

說明:此時程序沒有結束,進行到for循環,因爲並沒有字符a出現,所以還沒跳出for循環.鍵入回車後,getchar
依次從緩衝區內取出(for循環):'s''s''s''s''\n'

如果我們輸入:
ssssa
回車
得到:
ssss光標處(等待輸入)

說明:程序已經跳出for循環,但是由於我們用getchar();清除了換行'\n',後面第7句c=getchar();需要你輸入一個字符(因爲ssssa後面並沒有新的字符),所以程序仍然沒有結束.如果我們註釋掉getchar();這一句,那麼得到:

ssss
光標處(程序結束)
這個輸入ssssa是的回車中的換行符'\n'就被c=getchar();這一句讀取並輸出了。

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

http://www.cnblogs.com/biser/archive/2004/09/23/45704.aspx

1.機理

你鍵盤輸入了東西,而此時你又沒有用程序去getchar她,請問這個時候你按的鍵的狀態保存在何處?爲什麼你一會兒去getchar的時候能得到呢
(例子好舉,你先做一個1分鐘延遲,然後再getchar,會發現一分鐘前按的東西會顯示出來)
實際上是 輸入設備->內存緩衝區->程序
getchar
你按的鍵是放進緩衝區了,然後供程序
getchar
你有沒有試過按住很多鍵然後等一會兒會滴滴滴滴響,就是緩衝區滿了,你後頭按的鍵沒有存進緩衝區.

2.getchar()和getch()

然後就可以給你講了
getchar
是回車以後才進緩衝區
getch是每次都進緩衝區
用你的程序來說(我怎麼覺得應該是\n不是/n)


其實你輸入computer,沒按回車之前, 運行都停止在
getchar()裏頭,根本沒有進入循環,自然也沒有運行printf
當你一按回車,才從getchar出來,然後以後因爲鍵盤緩衝區裏頭有東西,就一個一個字符getchar出來了

想立刻回顯,用getch就好了

2.scanf

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

scanf輸入字符串,整型,實型等數據判斷的方式都一樣,回車,空格,tab鍵都認爲是一個數據的結束,當然字符的話,一個字符就是結束了,回車,空格 等都有對應的ascii碼,所以用scanf輸入字符時要小心這些東東被當成字符輸進去,而輸入字符串和整型,實型等數據時這些都被當成分隔符而不會被輸 入到字符數組或變量裏.當然如果輸入格式不是"%s%s"而是"%s,%s"分隔符就是逗號了,這個講到輸入輸出函數時再說.
說了這麼多舉幾個例子:

#include <stdio.h>
int main()
{
char n1[10];
char n2[10];
scanf("%s",n1);
scanf("%s",n2);
printf("n1=%s,n2=%s",n1,n2);
}



 

輸入:
hello
回車
world回車
得到:
n1=hello,n2=wolrd光標處(程序結束
)
這裏hello後面就是輸入再多個回車,空格也不會被賦值到n2中的,因爲他們只是分隔符.

如果輸入:
hello
回車
光標處(等待輸入)
說明回車被認成分隔符,所以程序還要你輸入一個字符串來賦給n2.

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

#include <stdio.h>
int main()
{
char n1[10];
char n2[10];
char n3,n4;
scanf("%s",n1);
scanf("%s",n2);
printf("n1=%s,n2=%s",n1,n2);
n3=getchar();
printf("%c",n3);
//n4=getchar();
//printf("%c",n4);
}



 

輸入:
hello
回車
world回車
得到:
hello
world
n1=hello,n2=wolrd
光標處(程序結束
)
如果取消最後兩行的註釋,同樣的輸入得到
:
hello
world
n1=hello,n2=wolrd
光標處(等待輸入
)
說明此時緩衝區內只有一個'\n',第二個getchar就需要你再輸入一個字符了,緩衝區內已經沒有字符了.

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

#include <stdio.h>
int main()
{
char n1[10];
char n2;
scanf("%s",n1);
scanf("%c",&n2);
printf("n1=%s,n2=%d",n1,n2);
}



 

輸入:
hello
回車
得到:
n1=hello,n2=10光標處(程序結束) //10是'\n'的ascii碼
.
如果輸入
:
hello 空格回車(一定要有回車,因爲scanf也是要等回車,準確說是'\r'纔會去讀緩衝區的
.)
得到
:
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只要是通過緩衝區輸入數據的函數都是等待回車鍵'\r'出現才進入緩衝區的.再來個整型數據,字符串,字符的混合例子:


#include <stdio.h>
int main()
{
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);
}




輸入:
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>
main(){
int a;
char ch;
scanf("%d",&a);
ch=getchar();
printf("%d,%c",a,ch);
}



輸入:
95
回車
得到:
95,
光標處(程序結束
)
很明顯這是由於分隔符(回車)被getchar讀取並輸出了,如果加入一句:getchar();

#include <stdio.h>
main(){
int a;
char ch;
scanf("%d",&a);
getchar();
ch=getchar();
printf("%d,%c",a,ch);
}


 


輸入:
95
回車
c回車
得到:
95,c光標處(程序結束)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章