版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1第四章Java循環(huán)語句學(xué)習(xí)目標(biāo)·使用while循環(huán)編寫“重復(fù)執(zhí)行某些語句”的程序·實訓(xùn)一:編寫程序GuessNumber·遵循循環(huán)設(shè)計策略來開發(fā)循環(huán)·實訓(xùn)二:編寫程序SubstractionQuizLoop·使用標(biāo)志值控制循環(huán)·使用輸入重定向以獲取大量輸入數(shù)據(jù)·使用do-while語句編寫循環(huán)·使用使用for語句編寫循環(huán)·了解三種類型循環(huán)語句的相似處和不同點·編寫嵌套循環(huán)·從多種例子中學(xué)習(xí)循環(huán)·使用break和continue來實現(xiàn)程序的控制·使用確定對話框
控制循環(huán)24.1引言如果你想打印一個字符串
“WelcometoJava!”100次,就需要把下面的語句重復(fù)寫上100遍!
System.out.println("WelcometoJava!"); System.out.println("WelcometoJava!"); ...... System.out.println("WelcometoJava!");Java提供了一種稱為循環(huán)的結(jié)構(gòu),用來控制一個語句塊重復(fù)執(zhí)行的次數(shù)。下面的代碼就是使用循環(huán)語句
來告訴計算機打印上面這個字符串100次:
intcount=0; while(count<100) { System.out.println("WelcometoJava!"); count++; }其中的語句將被重復(fù)執(zhí)行100遍!34.2
while循環(huán)while語句的語法格式是:while(布爾表達式){
語句塊//“循環(huán)體”
}while語句的執(zhí)行流程如圖4-1所示。?循環(huán)結(jié)構(gòu)中包含的語句塊稱為循環(huán)體(即需要重復(fù)執(zhí)行的操作序列);?循環(huán)體的每一次執(zhí)行稱為一次循環(huán)迭代;?每個循環(huán)結(jié)構(gòu)都需要一個循環(huán)的繼續(xù)條件,它是一個布爾表達式;?每次循環(huán)迭代前,總是先計算這個循環(huán)繼續(xù)條件以決定是否執(zhí)行循環(huán)體。若為true,則執(zhí)行循環(huán)體;否則,終止整個循環(huán)并將程序的控制轉(zhuǎn)移到while語句之后的下一條語句。圖4-1while語句的流程說明truefalse布爾表達式語句塊下一條語句4圖4-2
打印字符串100次的流程說明truefalsecount<100System.out.println("WelcometoJava");count++;下一條語句count=0提示當(dāng)事先確切知道循環(huán)次數(shù)時,可以使用一個變量(例如,count)來對執(zhí)行次數(shù)進行計數(shù)。這種類型的循環(huán)稱為“計數(shù)器控制的循環(huán)”。5
下面是另外一個例子,有助于理解循環(huán)是如何工作的: intsum=0,i=1; while(i<100){ sum=sum+i; i++; } System.out.println("sum="+sum);
如果循環(huán)被錯誤的寫成如下所示,那會出現(xiàn)什么情況? intsum=0,i=1; while(i<100){ sum=sum+i; } System.out.println("sum="+sum);警告必須確保循環(huán)條件最終可以變?yōu)閒alse,以便循環(huán)能夠結(jié)束。一個常見的循環(huán)設(shè)計錯誤是無限循環(huán)(也叫做“死循環(huán)”)。也就是說,由于循環(huán)條件的不當(dāng)而使循環(huán)永遠不可能結(jié)束。其中變量sum被稱為“累加器”每次的重復(fù)都是從舊值的基礎(chǔ)上“迭代”出新值,并由新值替代舊值。6
另外,程序員經(jīng)常會犯的錯誤,就是使循環(huán)多迭代一次或少迭代一次,這種情況稱為“出一錯誤”(off-byoneerror)。
例如,下面的循環(huán)會將字符串“WelcometoJava!”打印101次: intcount=0; while(count<=100){ System.out.println("WelcometoJava!"); count++; }
這個錯誤出在什么地方呢?7注意1)只有當(dāng)循環(huán)體內(nèi)只包含一條語句或不包含語句時,循環(huán)體的花括號{}才可以省略;2)當(dāng)循環(huán)體不包含語句時,必須留一個分號“;”,以表示“空操作”或叫做“空語句”。System.out.print("開始計時......");finalintGAP=10;longstartTime=System.currentTimeMillis()/1000;while((System.currentTimeMillis()/1000-startTime)<GAP);System.out.println(GAP+"秒鐘時間到!");inti=0;while(i<100)System.out.println(++i);84.2.1
實例:猜數(shù)字下面是該程序要求的一次運行示例:
請你猜一個[0~100]的魔數(shù)請輸入你的猜測:50↙你的猜測大了!請輸入你的猜測:25↙你的猜測大了!請輸入你的猜測:12↙你的猜測大了!請輸入你的猜測:6↙你的猜測小了!請輸入你的猜測:9↙恭喜你猜對了!這個數(shù)是9.根據(jù)我們已有的經(jīng)驗,該程序首先需要產(chǎn)生一個0~100的隨機數(shù)(魔數(shù)),然后提示用戶輸入一個猜測數(shù),接著便可以將這個猜測數(shù)與隨機數(shù)進行比較了。
不要急于編程!編碼前的思考是非常重要的!尤其是涉及循環(huán)的程序設(shè)計。切記:一次增加一個步驟地“逐步編碼”是一個很好的習(xí)慣.9提示如果不知道如何立即編寫循環(huán),可以編寫循環(huán)只執(zhí)行一次的代碼,然后規(guī)劃如何在循環(huán)中重復(fù)執(zhí)行這些代碼——這是一種很好的辦法。10下面我們先為該程序打一個初稿——循環(huán)只執(zhí)行一次的代碼://源程序清單4-1(初稿)GuessNumber.javaimportjava.util.Scanner;publicclassGuessNumber{publicstaticvoidmain(String[]args){
//產(chǎn)生一個魔數(shù)(隨機數(shù))intnumber=(int)(Math.random()*101);Scannerinput=newScanner(System.in);System.out.println("請你猜一個0~100的魔數(shù)");System.out.print("請你輸入一個猜測數(shù):");intguess=input.nextInt(); //讀入用戶輸入的猜測數(shù)if(guess==number) System.out.println("恭喜你猜對了!這個數(shù)是" +number);elseif(guess>number) System.out.println("你的猜測大了!");else System.out.println("你的猜測小了!");
}}while(true)}
while(guess!=number)
}雖然這個循環(huán)可以重復(fù)提示用戶輸入猜測數(shù)并進行比較,但是它永遠都不會結(jié)束!正確的做法應(yīng)該是當(dāng)guess與number匹配時,該循環(huán)就應(yīng)該結(jié)束。所以應(yīng)該改寫循環(huán)繼續(xù)條件.11下面給出該程序的完整代碼://源程序清單4-1GuessNumber.javaimportjava.util.Scanner;publicclassGuessNumber{publicstaticvoidmain(String[]args){intnumber=(int)(Math.random()*101); Scannerinput=newScanner(System.in); System.out.println("請你猜一個0~100的魔數(shù)");
intguess=-1;//初始化guess while(guess!=number){ System.out.print("請你輸入一個猜測數(shù):"); guess=input.nextInt(); if(guess==number) System.out.println("恭喜你猜對了!這個數(shù)是" +number); elseif(guess>number) System.out.println("你的猜測大了!"); else System.out.println("你的猜測小了!"); }//循環(huán)結(jié)束}}注意這里的guess必須進行初始化,否則會出現(xiàn)編譯錯誤。這里將它初始化為-1。將它初始化為0~100之間的數(shù),就會影響程序的正確性。因為,它很可能就是要猜測的數(shù)。124.2.2
循環(huán)設(shè)計策略
編寫循環(huán)時,應(yīng)該考慮如下四個步驟:i)確定需要重復(fù)執(zhí)行的語句;ii)將這些語句放在一個循環(huán)中。iii)編寫循環(huán)條件,并為控制循環(huán)添加適當(dāng)?shù)恼Z句。intcount=0;while(){System.out.println("WelcometoJava!");count++;}iv)為循環(huán)變量(如,count)選擇適當(dāng)?shù)某跏贾怠R悦狻俺鲆诲e誤”。count<100
intsum=0,i=1;while(){sum=sum+i;i++;}//sum=1+2+...+99累加器變量sum初始化i<100
循環(huán)控制變量i初始化134.2.3
實例:高級數(shù)學(xué)學(xué)習(xí)工具
程序清單3-4中的數(shù)學(xué)減法學(xué)習(xí)工具只能產(chǎn)生一道題目?,F(xiàn)在我們使用循環(huán)來重復(fù)產(chǎn)生題目。如何編寫能產(chǎn)生5道題目的代碼呢?遵循循環(huán)設(shè)計策略:i)確定需要重復(fù)的語句:獲取兩個隨機數(shù),提示用戶對兩數(shù)做減法,然后打分;ii)將這些語句放入一個循環(huán)里。iii)增加一個循環(huán)變量和循環(huán)條件,并為控制循環(huán)添加適當(dāng)?shù)恼Z句。下面的程序清單4-2給出的程序可以產(chǎn)生5道題目,在學(xué)生回答完所有5道題目后,報告回答正確的題數(shù)。這個程序最后還顯示該測試所花的時間,并列出所有題目的回答情況。14//源程序清單4-2SubstractionQuizLoop.javaimportjava.util.Scanner;publicclassSubstractionQuizLoop{publicstaticvoidmain(String[]args){finalintNUMBER_OF_QUESTIONS=5;//聲明問題數(shù)量intcorrectCount=0; //“回答正確”計數(shù)器初始化intcount=0;//“問題數(shù)量”計數(shù)器初始化longstartTime=System.currentTimeMillis();//開始時間Stringoutput="";//“回答問題的情況匯總”字符串初始化Scannerinput=newScanner(System.in);while(count<NUMBER_OF_QUESTIONS){ intnumber1=(int)(Math.random()*10);
intnumber2=(int)(Math.random()*10); //確保number1不小于number2 if(number1<number2){ inttemp=number1; number1=number2; number2=temp; } 15 //出題 System.out.print(number1+"-"+number2+"=?"); intanswer=input.nextInt();//讀入鍵盤輸入的答案 if(number1-number2==answer){//顯示評語 System.out.println("正確"); correctCount++; } else System.out.println("你的回答是錯誤的。\n" +number1+"-"+number2 +"應(yīng)該是"+(number1-number2)); count++;//問題數(shù)量加1 output+="\n"+number1+"-"+number2+"="+answer +(number1-number2==answer)?"正確!":"錯誤!";}//循環(huán)結(jié)束(學(xué)生測試結(jié)束)//產(chǎn)生“結(jié)束”時間、測試用時和顯示匯總信息
longendTime=System.currentTimeMillis();longtestTime=endTime-startTime;//計算“測試用時”System.out.println("正確的次數(shù)為:"+correctCount+"\n用時為:"+testTime/1000+"秒\n情況匯總:\n"+output);}}16
下面我們來編寫這樣一個程序:讀取和計算個數(shù)不確定的整數(shù)之和。當(dāng)讀取的數(shù)為
0
時,表示輸入結(jié)束。現(xiàn)在需要解決的問題有:1)對于每次輸入的整數(shù)是否都需要聲明新變量?不需要!只需要使用一個變量(例如,data)來存儲輸入的值。2)如何求它們的和?使用累加器。(類似
sum=sum+data
來計算1+2+3+...+99)該程序的算法描述如下:(i)輸入一個整數(shù)給data;(ii)如果data不為0,則執(zhí)行(iii);否則執(zhí)行(v);(iii)sum=sum+data;(iv)再輸入一個整數(shù)給data;然后轉(zhuǎn)去執(zhí)行(ii);(v)輸出變量sum的值。4.2.4
使用標(biāo)志位控制循環(huán)另一種控制循環(huán)的常用技術(shù)是在讀取和處理一個集合的數(shù)據(jù)時指派一個特殊值。這個特殊的輸入值也稱為結(jié)束標(biāo)志——表明循環(huán)的結(jié)束。這種使用標(biāo)志值來控制的循環(huán)稱為標(biāo)志值控制的循環(huán)。17data=input.nextInt();while(data!=0){sum+=data;data=input.nextInt();}System.out.println(sum);該程序的算法描述如下:(i)輸入一個整數(shù)給
data;(ii)如果data不為0,則執(zhí)行(iii);
否則執(zhí)行(v);(iii)sum=sum+data;(iv)
再輸入一個整數(shù)給data;然后轉(zhuǎn)去執(zhí)行(ii);(v)
輸出變量sum的值。truefalsedata!=0sum+=data讀入data讀入data輸出sum18//源程序清單4-3SentinelValue.javaimportjava.util.Scanner;publicclassSentinelValue{publicstaticvoidmain(String[]args){ Scannerinput=newScanner(System.in); //提示用戶輸入System.out.print("請輸入若干個整數(shù)(0表示輸入結(jié)束):"); intdata=input.nextInt();//讀入用戶輸入的第一個整數(shù) //以下循環(huán)結(jié)構(gòu)循環(huán)讀入用戶輸入的整數(shù),直到遇0為止。 intsum=0;//累加器初始化 while(data!=0){ sum+=data; //讀入用戶輸入的下一個整數(shù) System.out.print("請輸入一個整數(shù)(0表示輸入結(jié)束):"); data=input.nextInt(); } System.out.println("它們的和是:"+sum);}}19警告在循環(huán)控制中,不要使用浮點數(shù)來比較值是否相等。因為浮點數(shù)都是某些值的近似值,使用它們可能導(dǎo)致不精確的循環(huán)次數(shù)和不準(zhǔn)確的結(jié)果。請觀察下面計算1+0.9+0.8+0.7+....+0.1的代碼: doublesum=0,item=1; while(
item!=0){ sum+=item; item=item-0.1; } System.out.println("它們的和是:"+sum);因為浮點數(shù)在算術(shù)上是近似值,所以,不能確保item會變成真正的0。從表面上看,這個循環(huán)似乎沒問題,但實際上它是一個無限循環(huán)!20我們可以改用下面方法來解決: doublesum=0,item=1; while(
Math.abs(item)>1e-6){ sum+=item; item=item-0.1; } System.out.println("它們的和是:"+sum);21另外,如果想要判斷兩個浮點數(shù)x1、x2是否相等,那么,你就應(yīng)該使用下面的方法來解決:
while(Math.abs(x1-x2)<1e-6){...}而不能使用下面的代碼: while(x1==x2){...}22*4.2.5
輸入輸出重定向如果你想避免在程序運行過程中輸入大量的數(shù)據(jù),可以將這些數(shù)據(jù)用空格隔開,保存在一個文本文件(例如,input.txt)中,然后使用下面這個命令來運行這個程序: javaSentinelValue<input.txt這個命令稱為輸入重定向。它會告訴程序中的讀入方法“input.nextInt();”從文件input.txt中去讀入數(shù)據(jù),而不是讓用戶在運行時從鍵盤輸入數(shù)據(jù)。假設(shè)input.txt文件的內(nèi)容是:23456789122332234567899212343531240那么,你用上面這個命令來運行這個程序的話,將得到sum的值為518。
類似地,輸出重定向可以將程序本來在屏幕上顯示的結(jié)果發(fā)送到文件中去。輸出重定向的命令是: javaSentinelValue>output.txt可以同一命令中同時使用輸入輸出重定向。例如,下面的命令會從文件input.txt中讀取數(shù)據(jù),并將輸出結(jié)果發(fā)送到文件output.txt中:javaSentinelValue<input.txt>output.txt
請使用這個命令來運行這個程序,查看一下output.txt中的內(nèi)容是什么。234.3
do-while循環(huán)
do-while語句是while語句的變體。其語法格式是:
do{ 語句塊
}while(布爾表達式);它的執(zhí)行流程如圖4-3所示:首先執(zhí)行循環(huán)體;然后計算并判斷循環(huán)條件:如果為true,則重復(fù)執(zhí)行循環(huán)體;否則,終止循環(huán),轉(zhuǎn)去執(zhí)行下一條語句。
do-while語句與while語句的差別在于:判斷循環(huán)條件和執(zhí)行循環(huán)體的順序不同。圖4-3do-while流程說明下一條語句truefalse布爾表達式語句塊24
do-while語句和while語句具有相同的表達能力。有時候,選擇其中一個會比另一個更方便。例如,可以使用do-while循環(huán)來改寫程序清單4-3中的while循環(huán)。如下面的程序清單4-4所示。//源程序清單4-4TestDoWhile.javaimportjava.util.Scanner;publicclassTestDoWhile{//讀取并計算個數(shù)不確定的整數(shù)之和。
publicstaticvoidmain(String[]args){ Scannerinput=newScanner(System.in); intdata,sum=0; do{//提示用戶輸入 System.out.print("請輸入一個整數(shù)(0表示輸入結(jié)束):"); data=input.nextInt(); sum+=data; }while(data!=0); System.out.println("它們的和是:"+sum);}}25提示
如果循環(huán)中的語句至少需要執(zhí)行一次,那么,建議使用do-while循環(huán)。因為,如果使用while循環(huán),這些語句就必須在循環(huán)前和循環(huán)內(nèi)都出現(xiàn)。(請對照程序清單4-3和程序清單4-4)26do-while語句應(yīng)用舉例求解 利用牛頓迭代法求平方根的迭代公式為:當(dāng)|xn+1?
xn
|<ε時,xn+1即為解的近似值。(提示:x0可以是任意猜測值。為方便起見,可以取a的值。)算法描述如下:(i) x0=a;(ii) x1=x0;(iii) x0=(x1+a/x1)/2;(iv) |x0?x1|<10-6?是,轉(zhuǎn)至(v);否則轉(zhuǎn)至(ii);(v) x0(或x1)就是最后的解。。其中a是常數(shù)(a≠0)27//源程序清單3-2SolvingEquationsWithIterative.javaimportjava.util.Scanner;publicclassSolvingEquationsWithIterative{publicstaticvoidmain(String[]args){ Scannerinput=newScanner(System.in); System.out.print("請輸入一個數(shù):"); doublea,x0,x1; a=input.nextDouble(); x0=a; do{ x1=x0; x0=(x1+a/x1)/2; }while(Math.abs(x1-x0)>1E-8); System.out.println(a+"的平方根是:"+x0);}}(i) x0=a;(ii) x1=x0;(iii) x0=(x1+a/x1)/2;(iv) |x0?x1|<10-6?是,轉(zhuǎn)至(v);否則轉(zhuǎn)至(ii);(v) x0(或x1)就是最后的解。28“迭代法”也叫做“遞推法”,其基本思想是:把一個復(fù)雜的計算過程轉(zhuǎn)化為簡單過程的多次重復(fù),每次重復(fù)都從舊值的基礎(chǔ)上遞推出新值,并由新值替代舊值。(最簡單的例子就是“累加器”)294.4
for循環(huán)經(jīng)常會用到下面的通用形式來編寫循環(huán):
i=初值;
while(i<終值){
......//循環(huán)體
i++;
//循環(huán)變量加1
}可以使用for語句來簡化這個循環(huán):
for(i=初值;i<終值;i++){
......//循環(huán)體 }
for語句的語法格式如下所示: for(初始操作;循環(huán)條件;每次迭代后的操作
){ ......//循環(huán)體 }它的執(zhí)行流程如右邊圖所示。truefalse循環(huán)條件語句塊下一條語句初始操作每次迭代后的操作30例如,下面的for循環(huán)打印字符串100次:inti;for(i=0;i<100;i++){System.out.print("Hello!");}其流程圖如右圖所示。循環(huán)控制變量可以在for語句中聲明和初始化:for(inti=0;i<100;i++){System.out.print("Hello!");}如果像這個例子一樣,循環(huán)體只有一條語句,那么,花括號也是可以省略的。truefalsei<100"Hello!"i=0i++提示如果循環(huán)控制變量只在for循環(huán)內(nèi)使用而不在其他地方使用,那么,在for語句內(nèi)聲明它是一個很好的習(xí)慣。但是,在循環(huán)外就不能使用它了。因為,它的作用范圍被限制于該for語句范圍內(nèi)!31又例如:求1+2+…+100。//SumWithFor.javapublicclassSumWithFor{
publicstaticvoidmain(String[]args){
intsum=0;
for(inti=1;i<=100;
i++)
sum+=i;
System.out.println("1+2+…+100="+
sum
);
}}truefalsei<100
sum+=ii=0i++sum=032在String類中,方法charAt(i)用于返回字符串中第i個字符;而方法length()則用于返回字符串的長度。下面是它們的使用示例: Stringline=input.nextLine(); intlengthOfline=line.length(); System.out.println("該行字符的長度為:"+lengthOfline); System.out.println("第"+0+"個字符是:"+line.charAt(0)); System.out.println("第"+1+"個字符是:"+line.charAt(1)); System.out.println("第"+5+"個字符是:"+line.charAt(5));
下面我們來編寫一個用來統(tǒng)計從鍵盤輸入的一行字符中英文字母和數(shù)字字符的個數(shù)。33importjava.util.Scanner;
publicclassCharactersCount{ publicstaticvoidmain(String[]args){ Scannerinput=newScanner(System.in); int
letterCounter
=
0,digitCounter
=
0; charch; System.out.print("請輸入一行字符(回車結(jié)束):"); String
line
=
input.nextLine(); int
lengthOfline=
line.length(); for(int
i
=
0;
i
<lengthOfline;
i++)
{ ch
=
line.charAt(i); if(ch>='A'&&ch<='Z'||ch>='a'&&ch<='z')
letterCounter++; else
if(ch>='0'&&ch<='9')
digitCounter++; } System.out.println("該行字符的長度為:"+lengthOfline); System.out.println("其中,英文字母的個數(shù)為:"+
letterCounter); System.out.println("其中,數(shù)字字符的個數(shù)為:"+
digitCounter); }}34注意
for循環(huán)中的初始操作以及每次迭代后的操作,都可以是用0個或多個用逗號隔開的表達式。例如: for(i=0,j=0;(i+j<10);i++,j++){ ...... }例子:判斷一個鍵盤輸入的字符串是否回文. Stringword=input.nextLine(); intlengthOfword=word.length(); for(i
=
0,j=lengthOfword-1;i<j;i++,
j--)
if(word.charAt(
i
)!=word.charAt(
j
))
break; if(i
<
j) System.out.println("該字符串不是回文!"); else System.out.println("該字符串是回文。");35
publicstaticbooleanisPalindrome(Stringstr){//判斷str是否為回文字符串
intlen=str.length();//返回字符串長度
for(intindex=0;index<len/2-1;index++){if(str.charAt(index)!=str.charAt(len-index-1)){//對稱的兩個字符比較
returnfalse;}}returntrue;}36注意如果省略
for循環(huán)中的循環(huán)條件,則被默認為是true。因此下面的語句是等價的: for(
;;){ ...... }等價與 for(
;true
;){ ...... }及 while(
true
){ ...... }374.5
采用哪種循環(huán)
while循環(huán)和for循環(huán)稱為預(yù)測試循環(huán),因為循環(huán)條件是在循環(huán)體執(zhí)行前被測試的,而do-while循環(huán)則稱為后測試循環(huán),因為其循環(huán)條件是在循環(huán)體執(zhí)行后測試的。
while循環(huán)總是可以轉(zhuǎn)化為for循環(huán)。如下所示:
while(循環(huán)條件){ // ...... } for(;循環(huán)條件;){ //循環(huán)體 ...... }38
除某種特殊情況外,for循環(huán)通常也都能轉(zhuǎn)化為while循環(huán): for(初始操作;循環(huán)條件;每次迭代后的操作){ //循環(huán)體 ...... }
初始操作; while(
循環(huán)條件
){ //循環(huán)體 ......
每次迭代后的操作; }
建議使用自己覺得最自然、最舒服的一種循環(huán)語句。通常,如果已經(jīng)提前知道重復(fù)次數(shù),那就使用for循環(huán)(就像打印字符串100次)。如果無法確定重復(fù)次數(shù),就使用while循環(huán)(就像讀入一些數(shù)直到讀入0為止)。如果在檢驗循環(huán)條件前需要執(zhí)行循環(huán)體,那就使用do-while循環(huán)。39警告在for子句(或者while)和循環(huán)體之間多寫分號是一個常見的錯誤。因為,這都將表示循環(huán)體是空語句塊。如下所示:
for(....;....;.....); for(....;....;.....){}; { { ...... ..... } }或者 while(....); while(....){}; { { ...... ..... } }
使用行尾塊風(fēng)格是避免這種錯誤的最好辦法: for(....;....;.....){ while(....){ ...... ..... } }40
但是,在do-while循環(huán)中,卻需要用分號來結(jié)束循環(huán): do{ ..... }while(.....);414.6
嵌套循環(huán)
在一個循環(huán)語句(while循環(huán)、for循環(huán)、do-while循環(huán))內(nèi)又包含另一個循環(huán)語句(while循環(huán)、for循環(huán)、do-while循環(huán))稱為循環(huán)語句嵌套。并且三種循環(huán)語句可以相互嵌套。程序清單4-5是使用嵌套for循環(huán)打印一個乘法表的程序。其運行示例如下圖。42//源程序清單4-5MultiplicationTable.javaimportjava.util.Scanner;publicclassMultiplicationTable{publicstaticvoidmain(String[]args){ System.out.println("\n 乘法表\n"); System.out.print(""); for(inti=1;i<=9;i++) System.out.print(""+i); System.out.println("\n----------------------------------------"); for(inti=1;i<=9;i++){ System.out.print(i+"|"); for(intj=1;j<=9;j++) System.out.printf("%4d",i*j); System.out.println(); }}}提示循環(huán)嵌套中的內(nèi)、外層循環(huán)控制變量(例如,i、j)不能同名。它們的意義以及它們之間的關(guān)系,好比手表的時針、分針和秒針:時針走一格,分針走一圈;分針走一格,秒針走一圈。43程序清單4-6是使用嵌套for循環(huán)打印右邊圖案的程序。//源程序清單4-6DigitalPattern.javaimportjava.util.Scanner;publicclassDigitalPattern{publicstaticvoidmain(String[]args){ for(inti=1;i<=6;i++){ for(intj=1;j<=i;j++) System.out.print(j+""); System.out.println(); }}}11212312341234512345612345612345123412312144程序清單4-6-1是使用嵌套while循環(huán)打印上述圖案的程序。//源程序清單4-6-2DigitalPattern2.javaimportjava.util.Scanner;publicclassDigitalPattern2{publicstaticvoidmain(String[]args){ inti=1,j; while(i<=6){ j=1; while(j<=i){ System.out.print(j+""); j++; } System.out.println(); i++; }}}顯然,對于計數(shù)型循環(huán),for語句更勝于while語句。454.7
實例學(xué)習(xí)循環(huán)語句是程序設(shè)計的基礎(chǔ),編寫循環(huán)語句的能力對于學(xué)習(xí)程序設(shè)計是非常必要的、也是非常重要的。如果能夠使用循環(huán)編寫程序,你就懂得如何編程了!正是由于這個原因,本節(jié)將提供三個實例,學(xué)習(xí)如何使用循環(huán)來解決問題。
值得再次提醒的是:在編寫解決問題的程序之前,不要立即就開始寫代碼,應(yīng)該首先考慮一下在不涉及怎樣編寫代碼的情況下,如何手工解決它的邏輯方案。一旦有了一個邏輯方案,再將它翻譯成Java語言的代碼。(當(dāng)然,翻譯方式不是唯一的。例如,可以選擇使用for語句,也可以選擇while語句。)464.7.1
求最大公約數(shù)其算法可以描述如下:(i)輸入兩個整數(shù)n1、n2。(ii)(由于1可能不是它們的最大公約數(shù),所以可以檢測
2、3、4......
≤
n1及n2的整數(shù))取
k=2;(iii)當(dāng)k是
≤
n1及n2的整數(shù)時,重復(fù)執(zhí)行下面兩步操作:
i)k是n1、n2的最大公約數(shù)嗎? 如果是的,則最大公約數(shù)gcd就是k;(即gcd=k)
ii)k加1;(iv)顯示“最大公約數(shù)是”gcd。上面算法中的(ii)、(iii)可以翻譯成下面的代碼:提示一個問題常常有多種解決方案。最大公約數(shù)問題就有許多解決方案。一個更有效的解決方案是使用經(jīng)典的“歐幾里得”算法(見習(xí)題)。47
上面算法中的(ii)、(iii)可以翻譯成下面的代碼:intgcd=1;//假定最大公約數(shù)為1for(intk=2;k<=n1&&k<=n2;k++)if(n1%k==0&&n2%k==0)gcd=k;}intgcd=1;//假定最大公約數(shù)為1intk=2;while(k<=n1&&k<=n2){if(n1%k==0&&n2%k==0)gcd=k;k++;}48下面是這個算法的運行示例:49程序清單4-7是完整的程序。//源程序清單4-7GCD.javaimportjava.util.Scanner;importjavax.swing.JOptionPane;publicclassGCD{publicstaticvoidmain(String[]args){ Scannerinput=newScanner(System.in); System.out.print("請輸入第一個數(shù):"); intn1=input.nextInt(); System.out.print("請輸入第二個數(shù):"); intn2=input.nextInt(); intgcd=1; for(intk=2;k<=n1&&k<=n2;k++) if(n1%k==0&&n2%k==0) gcd=k;System.out.println("最大公約數(shù)是:"+gcd);}}算法說明:由于在本算法的循環(huán)中,
if語句的作用是從每一個可能的k中篩選出最新的最大公約數(shù)。因此,這類循環(huán)體的算法也被稱為“篩選器”算法。504.7.2
預(yù)測未來學(xué)費
假設(shè)某大學(xué)今年的學(xué)費是10000美金,并以每年7%的速度增加。試問:多少年之后學(xué)費會翻倍?首先考慮如何手工解決它:第二年是第一年乘以1.07,.....未來的一年都是前一年乘以1.07。所以,每年的學(xué)費可以如下計算:doubletuition=10000;intyear=1;tuition=tuition*1.07;year++;tuition=tuition*1.07;year++;tuition=tuition*1.07;year++;......不斷地計算下去,直到學(xué)費tuition達到或者超過20000美金為止。51現(xiàn)在可以將這個邏輯翻譯成使用循環(huán)結(jié)構(gòu)實現(xiàn)的下面這段代碼: doubletuition=10000; intyear=1; while(tuition<=20000){ tuition=tuition*1.07; year++; }在本算法的循環(huán)體中,變量tuition的值也是由自身的舊值迭代而得的。而year則是一個計數(shù)器。52程序清單4-8是完整的程序。//源程序清單4-8FutureTuition.javapublicclassFutureTuition{publicstaticvoidmain(String[]args){ doubletuition=10000; intyear=1; while(tuition<=20000){ tuition=tuition*1.07; year++; } System.out.println(year+"后,學(xué)費將翻倍!");}}534.7.3
枚舉法
在某些問題中,需要對可能出現(xiàn)的大量情況進行一一測試,以判斷是否滿足某些(或某個)求解的條件。采用循環(huán)語句可以方便地來解決。例如,“百元買百雞”問題。假定小雞每只0.5元,公雞每只2元,母雞每只3元?,F(xiàn)在有100元錢,要求買100只雞。編程列出所有可能的買雞方案。設(shè),小雞、公雞和母雞分別為chickens、cocks、hens只。根據(jù)題意,列出方程組如下: chickens+cocks+hens=100 0.5*chickens+2*cocks+3*hens=10054
枚舉法的基本思想,就是在所有可能的chickens、cocks、hens值中,找出滿足方案的解。按照這個思想,chickens、cocks、hens可能的取值如下:
chickens:0~100、 cocks:0~100、 hens:0~100.
那么,接下來的問題就是:在上面這三個取值范圍中,哪些值是滿足解決方案的?55程序清單4-9是《算法一:三重嵌套》完整的程序。//源程序清單4-9HundredYuanToBuyHundredChickens1.javaimportjava.util.Scanner;publicclassHundredYuanToBuyHundredChickens1{publicstaticvoidmain(String[]args){ intchickens,cocks,hens; System.out.println("chickens\tcocks\thens"); for(chickens=0;chickens<100;chickens++) for(cocks=0;cocks<100;cocks++) for(hens=0;hens<100;hens++) if((chickens+cocks+hens==100) &&(0.5*chickens+2*cocks+3*hens==100)) System.out.println(chickens +"\t"+cocks+"\t"+hens);}}56程序清單4-10是《算法二:優(yōu)化為兩重嵌套》完整的程序。//源程序清單4-10//HundredYuanToBuyHundredChickens2.javaimportjava.util.Scanner;publicclassHundredYuanToBuyHundredChickens2{publicstaticvoidmain(String[]args){ intchickens,cocks,hens; System.out.println("chickens\tcocks\thens"); for(hens=0;hens<33;hens++) for(cocks=0;cocks<50;cocks++){ chickens=100-hens-cocks; if(0.5*chickens+2*cocks+3*hens==100) System.out.println(chickens+","+cocks+"," +hens); }}}57*4.7.4
蒙特卡洛模擬
為了更多地學(xué)習(xí)編程解決問題,本節(jié)給出使用蒙特卡洛方法來估算π的值。為了更好地理解這個方法,需要畫出一個圓的外接正方形。如下圖所示:1-1-11
假設(shè)這個圓的半徑是1,那么圓面積就是π而外接正方形的面積就是4。隨機產(chǎn)生正方形中的一個點,該點落在這個圓內(nèi)的概率是
圓面積/正方形面積:π/4。編寫程序,在正方形內(nèi)隨機產(chǎn)生1000000個點,用變量numberOfHits對落在圓內(nèi)的點進行計數(shù)。由于numberOfHits≈1000000*(π/4),所以,就可以利用式子 π=4*numberOfHits/1000000來估算π的近似值了。完整程序如程序清單4-9所示。(x,y)且有:x2+y2≤158程序清單4-11是蒙特卡洛模擬的完整程序。//源程序清單4-11MonteCaloSimulation.javaimportjava.util.Scanner;importjavax.swing.JOptionPane;publicclassMonteCaloSimulation{publicstaticvoidmain(String[]args){ finallongNUMBER_OF_TRIALS=10000000; intnumberOfHits=0; for(inti=0;i<NUMBER_OF_TRIALS;i++) { doublex=Math.random()*2.0-1; doubley=Math.random()*2.0-1; if(x*x+y*y<=1) numberOfHits++; } doublepi=4.0*numberOfHits/NUMBER_OF_TRIALS; System.out.println("π的值是:"+pi);}}說明
本算法也屬于“篩選器”算法。59注:蒙特卡洛模擬方法的原理是當(dāng)問題或?qū)ο蟾鶕?jù)抽樣計算統(tǒng)計量或者參數(shù)的值,隨著模擬次數(shù)的增多,可以通過對各次統(tǒng)計量或參數(shù)的估計值求平均的方法得到穩(wěn)定結(jié)論。(想要了解更多的有關(guān)知識,請自行上網(wǎng)檢索。)604.8
關(guān)鍵字break和continue
我們已在switch語句中使用過break語句,你也可以在一個循環(huán)中使用break來終止循環(huán)。下面的代碼是將1到20的整數(shù)加到sum中,直到sum的值大于或等于100為止。 intsum=0; intnumber=0; while(number<20){ number++; sum+=number; if(sum>=100) break; }
//結(jié)束循環(huán)61程序清單4-12中給出了完整的程序。//源程序清單4-12TestBreak.javaimportjava.util.Scanner;importjavax.swing.JOptionPane;publicclassTestBreak{publicstaticvoidmain(String[]args){ intsum=0; intnumber=0; while(number<20){ number++; sum+=number; if(sum>=100) break; } System.out.println("number的值是:"+number); System.out.println("sum的值是:"+sum);}}number的值是:14sum的值是:105如果沒有if語句,程序就會計算1到20的和。其運行結(jié)果是:number的值是:20sum的值是:21062
你也可以在循環(huán)中使用關(guān)鍵字continue。當(dāng)程序遇到continue時,它會結(jié)束當(dāng)前迭代,程序控制將轉(zhuǎn)向循環(huán)體的末尾。換句話說,continue只是跳出了一次迭代,而break則是跳出整個循環(huán)。下面的代碼是將1到20中除去10和11外的整數(shù)都加到sum中。 intsum=0; intnumber=0; while(number<20){ number++; if(number==10||number==11) continue; sum+=number; }63程序清單4-13中給出了完整的程序。//源程序清單4-13TestContinue.javaimportjava.util.Scanner;importjavax.swing.JOptionPane;publicclassTestContinue{publicstaticvoidmain(String[]args){ intsum=0; intnumber=0; while(number<20){ number++; if(number==10||number==11) continue; sum+=number; } System.out.println("sum的值是:"+sum);}}sum的值是:189如果沒有if語句,程序就會計算1到20的和。其運行結(jié)果是:sum的值是:21064注意雖說break和continue可以為循環(huán)提供額外的控制,并在某種情況下還可以簡化程序設(shè)計。但是,過度地使用或者不正確地使用會使得程序難以讀懂并難以測試。通常,總是可以編寫出在循環(huán)中不使用它們的程序。也就是說,只有在能夠簡化程序代碼并使程序更容易閱讀的情況下,才可以適當(dāng)?shù)厥褂盟鼈儭?/p>
下面使用break來改寫程序清單4-1猜數(shù)字的程序。程序請參見程序清單4-11。65//源程序清單4-11GuessNumberUsingBreak.javaimportjava.util.Scanner;publicclassGuessNumberUsingBreak{publicstaticvoidmain(String[]args){ intnumber=(int)(Math.random()*101); Scannerinput=newScanner(System.in); System.out.println("請你猜一個0~100的魔數(shù)"); intguess=-1; while(true){//重復(fù)執(zhí)行下面的循環(huán)體 System.out.print("請你輸入一個猜測數(shù):"); guess=input.nextInt(); //讀入用戶輸入的猜測數(shù) if(guess==number){ System.out.println("恭喜你猜對了!");
} elseif(guess>number) System.out.println("你猜大了!"); else System.out.println("你猜測了!"); }//循環(huán)結(jié)束}}
break;//跳出循環(huán)66注意:在while和do-while語句中,continue之后會馬上去計算并測試循環(huán)條件;而在for語句中,continue之后則先執(zhí)行每次迭代后的操作,然后做計算并測試循環(huán)條件。如下所示:inti=1;while(i<20){sum+=i;if(i%2==0) continue;i++;}inti=1;do{sum+=i;if(i%2==0) continue;i++;}while(i<20);for(i=1;i<20;i++){sum+=i;if(i%2==0) continue;}67問題:顯示前50個素數(shù)(每行10個)
大于1的整數(shù),如果它的正因子只有1和它自己,那么,該整數(shù)就是素數(shù)。例如,2、3、5、7都是素數(shù),而4、6、8、9不是。在該問題中,需要解決的主要問題有:?如何判斷一個給定數(shù)是否素數(shù)??如何統(tǒng)計素數(shù)的個數(shù)??如何打印每個素數(shù)并且每行打印10個?68該問題的初步算法可以用Java偽代碼來描述如下:count=0; //素數(shù)的計數(shù)器變量count初始化number=2;//第一個可能的素數(shù)從2開始(1不是質(zhì)數(shù))while(count<50){//素數(shù)個數(shù)不能超過50個 if(number是素數(shù)){ count++;
顯示number;//每行顯示10 } number++;}//如何判斷number是否素數(shù)?69
為了判斷
number是否素數(shù),需要檢測它是否能被2、3、4、...number/2的整數(shù)整除。如果能被整除,那它就不是素數(shù)。這個算法可以描述如下:booleanisPrime=true;//先假定number是素數(shù)for(intdiv=2;div<=number/2;div++)
if(number%div==0){
isPrime=false; break;
}顯然,當(dāng)上面這個循環(huán)結(jié)束后,isPrime若為true,則number是素數(shù)。因此,接下去就是那個if語句來處理是否顯示number了:if(isPrime){count++;
顯示number;
}70//源程序清單4-12PrimeNumber.javapublicclassPrimeNumber{publicstaticvoidmain(String[]args){ intcount=0;//素數(shù)計數(shù)器count初始化 intnumber=2; //第一個給定數(shù)number為2. System.out.println("前50個素數(shù)是:\n"); while(count<50){ booleanisPrime=true;//假設(shè)number是素數(shù) for(intdiv=2;div<=number/2;div++)
if(number%div==0){
isPrime=false;//number不是素數(shù)
break;//終止本for循環(huán)語句循環(huán)
}//for循環(huán)結(jié)束
if(isPrime){
count++; if(count%10==0)//顯示number后換行 System.out.println(number); else//顯示number后不換行 System.out.print(number+""); } number++;
}//while循環(huán)結(jié)束}
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 住房代銷代理合同范例
- 幼師師徒合同范例
- 山區(qū)木屋出租合同范例
- 私人購買公積金合同范例
- 付款合同范例單獨結(jié)款
- 車位私人轉(zhuǎn)讓合同范例
- 去頭蝦采購合同范例
- 藥店加盟經(jīng)營合同范例
- 廠房衛(wèi)生清掃合同范例
- 個體商戶勞務(wù)合同范例
- 上市公司投資報告分析報告
- 中醫(yī)診療設(shè)備種類目錄
- (完整)馬克思主義政治經(jīng)濟學(xué)習(xí)題及參考答案
- 中原文化介紹
- 醫(yī)院預(yù)防保健科工作制度及職責(zé)范本
- 分離工程課件
- 中國風(fēng)古詩詞詩歌朗讀比賽大會唐詩宋詞含內(nèi)容課件兩篇
- 計算機網(wǎng)絡(luò)技術(shù)基礎(chǔ)(第6版)全套教學(xué)課件
- 12、口腔科診療指南及技術(shù)操作規(guī)范
- 湖南省岳陽市2023年八年級上學(xué)期期末質(zhì)量檢測數(shù)學(xué)試題附答案
- 有限空間作業(yè)安全管理協(xié)議
評論
0/150
提交評論