分類:C++教學(xué) |
你肯定會奇怪為什么一開始先說這個,一開始不都是數(shù)據(jù)類型什么的嘛,這個寫在最前面因為后面的程序即使最簡單的code都會用到輸入輸出,輸出比較簡單,可以放在后面再說,但是輸入就不同了,如果不先了解一下,可能會得到和你預(yù)想不同的結(jié)果哦^_^.也正是由于和一般的c語言介紹方式不同,為了看起來正規(guī)一些,我就把這章叫做chapter0了,完全可以先跳過去,直接看chapter1.
1.getchar
先引用一下前人的成果(有修改)^_^:http://blog.csdn.net/cxyol/archive/2006/03/18/628324.aspx
getchar()是stdio.h中的庫函數(shù),它的作用是從stdin流中讀入一個字符,也就是說,如果stdin有數(shù)據(jù)的話不用輸入它就可以直接讀取了。而getch()和getche()是conio.h中的庫函數(shù),它的作用是從鍵盤接收字符。getchar帶有顯示。
#include<stdio.h>
#include<conio.h>
void main()
{
}
這個程序你運行一下,相信你又會有疑問了。這個就是從緩沖區(qū)中讀取了例子。第一次getchar()時,確實需要人工的輸入,但是如果你輸了多個字符,以后的getchar()再執(zhí)行時就會直接從緩沖區(qū)中讀取了。
#include<stdio.h>
#include<conio.h>
void main()
{
}
程序運行時,首先停下來,等你輸入一串字符串,輸入完畢后,它把你輸入的整個字符串都輸出來了,咦,你不是說getchar()只返回第一個字符么,這里怎么?
因為我們輸入的字符串并不是取了第一個字符就把剩下的字符串丟掉了,它還在我們的內(nèi)存中,就好比,開閘放水,我們把水放到閘里去以后,開一次閘就放掉一點,開一次就放掉一點,直到放光了為止,這里開閘動作就相當(dāng)于調(diào)用一次getchar()。我們輸入的字符串也是這么一回事,首先我們輸入的字符串是放在內(nèi)存的緩沖區(qū)中的,我們調(diào)用一次getchar()就把緩沖區(qū)中里出口最近的一個字符輸出,也就是最前面的一個字符輸出,輸出后,就把它釋放掉了,但后面還有字符串,所以我們就用循環(huán)把最前面的一個字符一個個的在內(nèi)存中釋放掉,直到不滿足循環(huán)條件退出為止。
例子中循環(huán)條件里的'\n'實際上就是你輸入字符串后的回車符,所以意思就是說,直到遇到回車符才結(jié)束循環(huán),而getchar()函數(shù)就是等待輸入(或緩沖區(qū)中的數(shù)據(jù))直到按回車才結(jié)束,所以實現(xiàn)了整個字符串的輸出。當(dāng)然,我們也可以把循環(huán)條件改一下,比如while ((c=getchar())!='a'),什么意思呢,意思就是遇到字符'a'就停止循環(huán),當(dāng)然意思是如果你輸入“12345a213123\n”那么只會輸出到a,結(jié)果是12345a。
再次注意:用getchar()它是從“流”中間去讀取,所以第一個getchar()接受的是剛剛中斷的流隊列中即將出列的第一個字符(不限于回車符,上面舉過例子了),如果流隊列不為空,執(zhí)行g(shù)etchar()就繼續(xù)放水,直到把回車符也放空為止,空了之后再在執(zhí)行g(shù)etchar()就停下等待你的輸入了;我們用getch()為什么每次都是等待用戶的輸入呢?因為getch()是從鍵盤接收,即時的接收,并不是從stdin流中去讀取數(shù)據(jù)。
3.如何清空輸入緩沖區(qū)的內(nèi)容?
char sbuf[1024];
// ...
fgets( sbuf, 1024, stdin );
// ...
在windows 的vc下面就可以這樣了:
for(int i=0;i<10;++i)
{
}
這里說到gcc編譯器沒有定義fflush的實現(xiàn),我們一般用getchar();來清除緩沖區(qū).
下面是我的討論:
先來一段code:
#include <stdio.h>
main()
{
}
輸入:
ssss回車
得到:
ssss
光標(biāo)處(等待輸入)
說明:此時程序沒有結(jié)束,進行到for循環(huán),因為并沒有字符a出現(xiàn),所以還沒跳出for循環(huán).鍵入回車后,getchar
依次從緩沖區(qū)內(nèi)取出(for循環(huán)):'s''s''s''s''\n'
如果我們輸入:
ssssa回車
得到:
ssss光標(biāo)處(等待輸入)
說明:程序已經(jīng)跳出for循環(huán),但是由于我們用getchar();清除了換行'\n',后面第7句c=getchar();需要你輸入一個字符(因為ssssa后面并沒有新的字符),所以程序仍然沒有結(jié)束.如果我們注釋掉getchar();這一句,那么得到:
ssss
光標(biāo)處(程序結(jié)束)
這個輸入ssssa是的回車中的換行符'\n'就被c=getchar();這一句讀取并輸出了。
總結(jié):
鍵盤輸入的字符都存到緩沖區(qū)內(nèi),一旦鍵入回車,getchar就進入緩沖區(qū)讀取字符,一次只返回第一個字符作為getchar函數(shù)的值,如果有循環(huán)或足夠多的getchar語句,就會依次讀出緩沖區(qū)內(nèi)的所有字符直到'\n'.要理解這一點,之所以你輸入的一系列字符被依次讀出來,是因為循環(huán)的作用使得反復(fù)利用getchar在緩沖區(qū)里讀取字符,而不是getchar可以讀取多個字符,事實上getchar每次只能讀取一個字符.如果需要取消'\n'的影響,可以用getchar();來清除,這里getchar();只是取得了'\n'但是并沒有賦給任何字符變量,所以不會有影響,相當(dāng)于清除了這個字符.還要注意的是這里你在鍵盤上輸入ssss看到的回顯正是來自于getchar的作用,如果用getch就看不到你輸入了什么.再引一篇文章:
http://www.cnblogs.com/biser/archive/2004/09/23/45704.aspx
1.機理
你鍵盤輸入了東西,而此時你又沒有用程序去getchar她,請問這個時候你按的鍵的狀態(tài)保存在何處?為什么你一會兒去getchar的時候能得到呢
(例子好舉,你先做一個1分鐘延遲,然后再getchar,會發(fā)現(xiàn)一分鐘前按的東西會顯示出來)
實際上是輸入設(shè)備->內(nèi)存緩沖區(qū)->程序getchar
你按的鍵是放進緩沖區(qū)了,然后供程序getchar
你有沒有試過按住很多鍵然后等一會兒會滴滴滴滴響,就是緩沖區(qū)滿了,你后頭按的鍵沒有存進緩沖區(qū).
2.getchar()和getch()
然后就可以給你講了
getchar是回車以后才進緩沖區(qū)
getch是每次都進緩沖區(qū)
用你的程序來說(我怎么覺得應(yīng)該是\n不是/n)
其實你輸入computer,沒按回車之前, 運行都停止在
getchar()里頭,根本沒有進入循環(huán),自然也沒有運行printf
當(dāng)你一按回車,才從getchar出來,然后以后因為鍵盤緩沖區(qū)里頭有東西,就一個一個字符getchar出來了
想立刻回顯,用getch就好了
2.scanf
scanf這個庫函數(shù)比較奇怪,而且存在一定的缺陷,所以很多人都不用了,這里還是要簡單介紹一下.
scanf輸入字符串,整型,實型等數(shù)據(jù)判斷的方式都一樣,回車,空格,tab鍵都認(rèn)為是一個數(shù)據(jù)的結(jié)束,當(dāng)然字符的話,一個字符就是結(jié)束了,回車,空格等都有對應(yīng)的ascii碼,所以用scanf輸入字符時要小心這些東東被當(dāng)成字符輸進去,而輸入字符串和整型,實型等數(shù)據(jù)時這些都被當(dāng)成分隔符而不會被輸入到字符數(shù)組或變量里.當(dāng)然如果輸入格式不是"%s%s"而是"%s,%s"分隔符就是逗號了,這個講到輸入輸出函數(shù)時再說.
說了這么多舉幾個例子:
#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光標(biāo)處(程序結(jié)束)
這里hello后面就是輸入再多個回車,空格也不會被賦值到n2中的,因為他們只是分隔符.
如果輸入:
hello回車
光標(biāo)處(等待輸入)
說明回車被認(rèn)成分隔符,所以程序還要你輸入一個字符串來賦給n2.
其實這時緩沖區(qū)里是有一個'\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
光標(biāo)處(程序結(jié)束)
如果取消最后兩行的注釋,同樣的輸入得到:
hello
world
n1=hello,n2=wolrd
光標(biāo)處(等待輸入)
說明此時緩沖區(qū)內(nèi)只有一個'\n',第二個getchar就需要你再輸入一個字符了,緩沖區(qū)內(nèi)已經(jīng)沒有字符了.
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光標(biāo)處(程序結(jié)束) //10是'\n'的ascii碼.
如果輸入:
hello 空格回車(一定要有回車,因為scanf也是要等回車,準(zhǔn)確說是'\r'才會去讀緩沖區(qū)的.)
得到:
n1=hello,n2=32光標(biāo)處(程序結(jié)束) //32是空格的ascii碼.
再羅嗦一下,如果最后一句輸入n2=%d改成n2=%c,則輸入:
hello回車
得到:
n1=hello,n2=
光標(biāo)處(程序結(jié)束)
是不是和getchar一樣可以把'\n'讀出來呢,呵呵.
總結(jié)一下就是:
如果scanf輸入的不是字符,那么分隔符為回車,空格,tab鍵時,兩個數(shù)據(jù)之間的分隔符只是起區(qū)別兩個數(shù)據(jù)的作用,把分隔好的兩個數(shù)據(jù)分別賦值到各自定義好的變量或數(shù)組中去,兩個數(shù)據(jù)之間的分隔符被從緩沖區(qū)讀出但是不起任何作用,當(dāng)然最后一個'\n'會被留在緩沖區(qū)內(nèi),除非用getchar();或scanf("%c",&c);把它讀出來.
回車是一定要有的,不管getchar還是scanf只要是通過緩沖區(qū)輸入數(shù)據(jù)的函數(shù)都是等待回車鍵'\r'出現(xiàn)才進入緩沖區(qū)的.再來個整型數(shù)據(jù),字符串,字符的混合例子:
#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(若干空格或回車就不影響結(jié)果,這里用了回車)
34(這里還要求輸入,因為scanf只得到了一個整型數(shù)據(jù),而緩沖區(qū)內(nèi)沒有整型數(shù)據(jù)了。要有回車或空格表示這個數(shù)據(jù)結(jié)束了,留下來的空格或回車被下個%c接受,這里用了回車,可以試一下空格)
45 jfdkjfa(回車)
得到:
a=12,b=34,n2=
,c=45,n1=jfdkjfa,n3=
光標(biāo)處(程序結(jié)束)
這里說明一下過程:在前兩個整型數(shù)據(jù)輸入時,兩個數(shù)據(jù)之間無論是回車還是若干空格都被scanf當(dāng)做分隔符,好了,scanf讀到分隔符(回車或空格)時,把第一個整型數(shù)據(jù)送到變量a中,緩沖區(qū)中留下分隔符和下面的整型數(shù)據(jù),這時scanf再讀當(dāng)然先讀分隔符,但是要求輸入的還是整型數(shù)據(jù)(%d),所以分隔符被忽略,如果這時要求輸入字符%c(不是字符串%s),那么分隔符將以一個字節(jié)的形式送到字符變量里,就如同這里的n2.同理可以知道c和n1的保存過程,最后的n3正是接收了輸入時的最后一個回車.
好了如果看到這里你都理解了那么看最后一個例子:
#include <stdio.h>
main(){
int a;
char ch;
scanf("%d",&a);
ch=getchar();
printf("%d,%c",a,ch);
}
輸入:
95回車
得到:
95,
光標(biāo)處(程序結(jié)束)
很明顯這是由于分隔符(回車)被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光標(biāo)處(程序結(jié)束)
轉(zhuǎn)載于 http://blog.sina.com.cn/s/blog_51409e8f01009han.html