許多C語(yǔ)言初學(xué)者常常對(duì)scanf函數(shù)、表達(dá)式scanf("%d", &num) != EOF的含義與其使用情況有些疑惑。
本文通過(guò)一道??途W(wǎng)例題,對(duì)該表達(dá)式進(jìn)行說(shuō)明和適當(dāng)拓展;不需要引例的朋友可以直接跳轉(zhuǎn)到講解部分。
希望對(duì)諸位讀者有所幫助。
目錄
一、引例 - ??途W(wǎng)OJ題
二、EOF 與 scanf 函數(shù)的關(guān)系
1. EOF (End Of File)? ?
2. scanf 函數(shù)? ??
scanf 演示?
三、while(scanf("%d", &num) != EOF)的使用
四、總結(jié)
一、引例 - 牛客網(wǎng)OJ題
為了更好地說(shuō)明這個(gè)表達(dá)式,我們以一道??途W(wǎng)的題目作引例。題目鏈接貼在這里:??途W(wǎng)習(xí)題-BC49 判斷兩個(gè)數(shù)的大小關(guān)系https://www.nowcoder.com/practice/f05358b9e8164b27871c87d3097f4dab?tpId=107&&tqId=33330&rp=1&ru=/ta/beginner-programmers&qru=/ta/beginner-programmers/question-ranking
題干如下
這道題的題意非常簡(jiǎn)單,思路也非常明確,程序大體僅需簡(jiǎn)單的?if 分支即可實(shí)現(xiàn)。經(jīng)過(guò)一番思考咱們自信地寫(xiě)下如下代碼:
/*Wrong!*/
#include<stdio.h>
int main(){
int x,y;
scanf("%d %d",&x,&y);
if(x > y)
printf("%d>%d",x,y);
else if (x = y)
printf("%d=%d",x,y);
else
printf("%d<%d",x,y);
return 0;
}
然而將該代碼提交給??途W(wǎng)OJ,卻無(wú)法通過(guò)所有用例:
說(shuō)明告訴我們,當(dāng)用例連續(xù)輸入多組(3組)時(shí),上面的代碼沒(méi)法做到一口氣輸出這3組用例相應(yīng)的答案,而僅僅是輸出了第一個(gè)用例(1 1)的答案。顯然,上面的程序 scanf 在讀取了一組輸入用例后就跑路了,無(wú)法做到題干要求的能輸入 “多組輸入數(shù)據(jù)” 。我們的答案程序被斃了。
也許循環(huán)可以解決上面的bug,于是咱們嘗試以下代碼:
/*Wrong!*/
#include<stdio.h>
int main(){
int x,y;
for(int i=0; i<3; i++){
scanf("%d %d",&x,&y);
if(x > y)
printf("%d>%d\n",x,y);
else if (x == y)
printf("%d=%d\n",x,y);
else
printf("%d<%d\n",x,y);
}
return 0;
}
試圖用 for 循環(huán)來(lái)達(dá)到?“輸入多組用例” 的要求。?事實(shí)上也不可行,該程序的邏輯是:輸入一組用例,執(zhí)行這一組用例,再通過(guò) for 循環(huán)再輸入一組用例,再執(zhí)行……并不是一次性輸入多組用例且同時(shí)打印多組答案。
因而,本題能被??途W(wǎng)OJ通過(guò)的關(guān)鍵是能做到多組輸入。如何實(shí)現(xiàn),用到的就是我們今天要講解的重點(diǎn):while(scanf("%d", &num) != EOF)
如下是該題的一個(gè)正確答案(事實(shí)上所有的正確答案都大同小異,且EOF這句表達(dá)式是必不可少的)
#include<stdio.h>
int main(){
int a,b;
while((scanf("%d%d",&a,&b)) != EOF){ //重點(diǎn)在此!
if(a == b)
printf("%d=%d\n",a,b);
else if(a > b)
printf("%d>%d\n",a,b);
else
printf("%d<%d\n",a,b);
}
return 0;
}
?二、EOF 與 scanf 函數(shù)的關(guān)系
1. EOF (End Of File)? ?
名稱(chēng)是文件結(jié)束標(biāo)志,定義為?-1(不是ASCII碼值為-1),可以通過(guò) Ctrl+Z 直接鍵入。
2. scanf 函數(shù)? ??
scanf函數(shù)是有返回值的。
一般來(lái)說(shuō),它的返回值是成功讀取的元素個(gè)數(shù)。但當(dāng)遭遇讀取失敗時(shí),它的返回值便是 -1 (也就是它自己返回一個(gè)EOF) 。
而若是一個(gè)元素都還沒(méi)成功讀入的時(shí)候就遇到了讀取失敗或EOF,那它直接就會(huì)返回-1,不管后面再輸入了什么。
Cplusplus官網(wǎng)對(duì) scanf 函數(shù)的說(shuō)明如下:
by the way,? getchar()函數(shù)讀取失敗時(shí),也會(huì)返回EOF。
下面這個(gè)網(wǎng)站建議大家收藏,C語(yǔ)言中各種函數(shù)、關(guān)鍵字等等的用法都可以在其中查詢(xún)到。
Cplusplus官網(wǎng)https://cplusplus.com/
scanf 演示?
代碼
int main(){
int a = 0;
int b = 0; //輸入a和b
int ret = scanf("%d %d",&a,&b); //用ret接受scanf的返回值
printf("ret = %d\n",ret);
printf("a = %d\n",a);
printf("b = %d\n",b);
return 0;
}
運(yùn)行結(jié)果
(1) 輸入 a 為7,b 為8,二者被scanf成功讀取,ret為2(成功讀取的元素個(gè)數(shù))。??
(2) 輸入 a 為7,b為EOF(先鍵盤(pán)敲Ctrl+Z后再enter),ret變成了1,因?yàn)橹挥衋是成功被讀取的,b并沒(méi)有被成功讀入。
(3)輸入a為EOF,b為8,ret變成了-1(即EOF).因?yàn)閟canf在一個(gè)元素也沒(méi)有讀取的時(shí)候就遇到了EOF(就是我們輸入的a,我們?nèi)藶榈妮斎肓薊OF),scanf直接返回-1,程序結(jié)束。
(4) 輸入a或b為非數(shù)字,屬于元素類(lèi)型不匹配的情況。
第一個(gè)元素'A'并沒(méi)有被讀入,scanf()會(huì)停留在那,并把字符'A'放回緩沖區(qū)再又繼續(xù)讀取。下一次讀取的時(shí)候,仍然是從'A'開(kāi)始。事實(shí)上,scanf()一直無(wú)法越過(guò)'A'讀到下一個(gè)字符,一直反復(fù)讀入,并陷入了死循環(huán)。在如下程序中,scanf會(huì)直接認(rèn)為讀取結(jié)束了,跳出函數(shù)。
因而該程序終止后,一個(gè)元素也沒(méi)有被讀進(jìn)去,但又不屬于C語(yǔ)言定義下的讀取失敗,ret為0.
若將語(yǔ)句寫(xiě)成while(scanf("%d", &num) != EOF)這樣,效果就是一直死循環(huán)。
(其實(shí)輸完'A'按enter程序就會(huì)直接結(jié)束,而正常情況下敲enter僅僅是輸入下一個(gè)數(shù)而已,這也是二者的一個(gè)差別。)
(5) 輸入a為7,b為'A',a在b之前成功讀取了,因而ret為1.?
?三、while(scanf("%d", &num) != EOF)的使用
當(dāng)需要多組輸入時(shí),可以用該表達(dá)式控制循環(huán)入口。當(dāng)人為的輸入EOF時(shí),結(jié)束循環(huán)。
代碼演示
此時(shí)我一次鍵入第一行的6個(gè)數(shù)字:5 6 10 10 2 3,敲enter,同時(shí)顯示這三組用例的運(yùn)行結(jié)果。注意:此時(shí)我的程序并沒(méi)有結(jié)束!末行光標(biāo)仍然在跳動(dòng),事實(shí)上我還能再接著鍵入幾組數(shù)字!
再又一次輸入三組數(shù)并顯示運(yùn)行結(jié)果后,我敲下Ctrl+Z,此時(shí)控制臺(tái)上顯示了一個(gè) ^Z ,說(shuō)明成功輸入了EOF,再按下enter,出現(xiàn)最下面的橫線與小字,程序結(jié)束!!
我使用的IDE是小熊貓版的devc++,如果在vs 2019中,要輸入三次Ctrl Z才行。這其實(shí)是vs的一個(gè)小bug?。
換成如下代碼,也是可以的:
int main(){
int a,b;
while((scanf("%d%d",&a,&b)) == 2){
if(a == b)
printf("%d=%d\n",a,b);
else if(a > b)
printf("%d>%d\n",a,b);
else
printf("%d<%d\n",a,b);
}
return 0;
}
while((scanf("%d%d",&a,&b)) == 2) 與??while(scanf("%d", &num) != EOF) 本質(zhì)上等價(jià)。
四、總結(jié)
本文詳細(xì)介紹了scanf 與 EOF 的含義與使用。
1. 當(dāng)需要多組輸入時(shí),使用while(scanf("%d", &num) != EOF)控制循環(huán)入口。
2. 初學(xué)階段了解如何使用即可:可以將EOF直接理解為一個(gè)簡(jiǎn)單的標(biāo)記。當(dāng)我們?cè)趕canf函數(shù)中輸入CTRL + Z時(shí),就能“召喚”出這個(gè)標(biāo)記,從而結(jié)束 scanf 函數(shù),達(dá)到控制循環(huán)的目的。
3.?while((scanf("%d%d",&a,&b)) == 2) 與??while(scanf("%d", &num) != EOF)效果完全相同。
4. 感謝大家支持!如果表述不當(dāng)之處,歡迎各位斧正!
2023年更新:
現(xiàn)在的??途W(wǎng)改版升級(jí)后,默認(rèn)模板中已經(jīng)自帶多組輸入代碼了~文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-714765.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-714765.html
到了這里,關(guān)于超詳解 - 如何理解C語(yǔ)言中while(scanf(“%d“, &num) != EOF)這一表達(dá)式?的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!