第4章Java循環(huán)語句副本_第1頁
第4章Java循環(huán)語句副本_第2頁
第4章Java循環(huán)語句副本_第3頁
第4章Java循環(huán)語句副本_第4頁
第4章Java循環(huán)語句副本_第5頁
已閱讀5頁,還剩79頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1第四章Java循環(huán)語句學習目標·使用while循環(huán)編寫“重復執(zhí)行某些語句”的程序·實訓一:編寫程序GuessNumber·遵循循環(huán)設計策略來開發(fā)循環(huán)·實訓二:編寫程序SubstractionQuizLoop·使用標志值控制循環(huán)·使用輸入重定向以獲取大量輸入數(shù)據·使用do-while語句編寫循環(huán)·使用使用for語句編寫循環(huán)·了解三種類型循環(huán)語句的相似處和不同點·編寫嵌套循環(huán)·從多種例子中學習循環(huán)·使用break和continue來實現(xiàn)程序的控制·使用確定對話框

控制循環(huán)24.1引言如果你想打印一個字符串

“WelcometoJava!”100次,就需要把下面的語句重復寫上100遍!

System.out.println("WelcometoJava!"); System.out.println("WelcometoJava!"); ...... System.out.println("WelcometoJava!");Java提供了一種稱為循環(huán)的結構,用來控制一個語句塊重復執(zhí)行的次數(shù)。下面的代碼就是使用循環(huán)語句

來告訴計算機打印上面這個字符串100次:

intcount=0; while(count<100) { System.out.println("WelcometoJava!"); count++; }其中的語句將被重復執(zhí)行100遍!34.2

while循環(huán)while語句的語法格式是:while(布爾表達式){

語句塊//“循環(huán)體”

}while語句的執(zhí)行流程如圖4-1所示。?循環(huán)結構中包含的語句塊稱為循環(huán)體(即需要重復執(zhí)行的操作序列);?循環(huán)體的每一次執(zhí)行稱為一次循環(huán)迭代;?每個循環(huán)結構都需要一個循環(huán)的繼續(xù)條件,它是一個布爾表達式;?每次循環(huán)迭代前,總是先計算這個循環(huán)繼續(xù)條件以決定是否執(zhí)行循環(huán)體。若為true,則執(zhí)行循環(huán)體;否則,終止整個循環(huán)并將程序的控制轉移到while語句之后的下一條語句。圖4-1while語句的流程說明truefalse布爾表達式語句塊下一條語句4圖4-2

打印字符串100次的流程說明truefalsecount<100System.out.println("WelcometoJava");count++;下一條語句count=0提示當事先確切知道循環(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)能夠結束。一個常見的循環(huán)設計錯誤是無限循環(huán)(也叫做“死循環(huán)”)。也就是說,由于循環(huán)條件的不當而使循環(huán)永遠不可能結束。其中變量sum被稱為“累加器”每次的重復都是從舊值的基礎上“迭代”出新值,并由新值替代舊值。6

另外,程序員經常會犯的錯誤,就是使循環(huán)多迭代一次或少迭代一次,這種情況稱為“出一錯誤”(off-byoneerror)。

例如,下面的循環(huán)會將字符串“WelcometoJava!”打印101次: intcount=0; while(count<=100){ System.out.println("WelcometoJava!"); count++; }

這個錯誤出在什么地方呢?7注意1)只有當循環(huán)體內只包含一條語句或不包含語句時,循環(huán)體的花括號{}才可以省略;2)當循環(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.根據我們已有的經驗,該程序首先需要產生一個0~100的隨機數(shù)(魔數(shù)),然后提示用戶輸入一個猜測數(shù),接著便可以將這個猜測數(shù)與隨機數(shù)進行比較了。

不要急于編程!編碼前的思考是非常重要的!尤其是涉及循環(huán)的程序設計。切記:一次增加一個步驟地“逐步編碼”是一個很好的習慣.9提示如果不知道如何立即編寫循環(huán),可以編寫循環(huán)只執(zhí)行一次的代碼,然后規(guī)劃如何在循環(huán)中重復執(zhí)行這些代碼——這是一種很好的辦法。10下面我們先為該程序打一個初稿——循環(huán)只執(zhí)行一次的代碼://源程序清單4-1(初稿)GuessNumber.javaimportjava.util.Scanner;publicclassGuessNumber{publicstaticvoidmain(String[]args){

//產生一個魔數(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)可以重復提示用戶輸入猜測數(shù)并進行比較,但是它永遠都不會結束!正確的做法應該是當guess與number匹配時,該循環(huán)就應該結束。所以應該改寫循環(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)結束}}注意這里的guess必須進行初始化,否則會出現(xiàn)編譯錯誤。這里將它初始化為-1。將它初始化為0~100之間的數(shù),就會影響程序的正確性。因為,它很可能就是要猜測的數(shù)。124.2.2

循環(huán)設計策略

編寫循環(huán)時,應該考慮如下四個步驟:i)確定需要重復執(zhí)行的語句;ii)將這些語句放在一個循環(huán)中。iii)編寫循環(huán)條件,并為控制循環(huán)添加適當?shù)恼Z句。intcount=0;while(){System.out.println("WelcometoJava!");count++;}iv)為循環(huán)變量(如,count)選擇適當?shù)某跏贾?。以免“出一錯誤”。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ù)學學習工具

程序清單3-4中的數(shù)學減法學習工具只能產生一道題目?,F(xiàn)在我們使用循環(huán)來重復產生題目。如何編寫能產生5道題目的代碼呢?遵循循環(huán)設計策略:i)確定需要重復的語句:獲取兩個隨機數(shù),提示用戶對兩數(shù)做減法,然后打分;ii)將這些語句放入一個循環(huán)里。iii)增加一個循環(huán)變量和循環(huán)條件,并為控制循環(huán)添加適當?shù)恼Z句。下面的程序清單4-2給出的程序可以產生5道題目,在學生回答完所有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 +"應該是"+(number1-number2)); count++;//問題數(shù)量加1 output+="\n"+number1+"-"+number2+"="+answer +(number1-number2==answer)?"正確!":"錯誤!";}//循環(huán)結束(學生測試結束)//產生“結束”時間、測試用時和顯示匯總信息

longendTime=System.currentTimeMillis();longtestTime=endTime-startTime;//計算“測試用時”System.out.println("正確的次數(shù)為:"+correctCount+"\n用時為:"+testTime/1000+"秒\n情況匯總:\n"+output);}}16

下面我們來編寫這樣一個程序:讀取和計算個數(shù)不確定的整數(shù)之和。當讀取的數(shù)為

0

時,表示輸入結束。現(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;然后轉去執(zhí)行(ii);(v)輸出變量sum的值。4.2.4

使用標志位控制循環(huán)另一種控制循環(huán)的常用技術是在讀取和處理一個集合的數(shù)據時指派一個特殊值。這個特殊的輸入值也稱為結束標志——表明循環(huán)的結束。這種使用標志值來控制的循環(huán)稱為標志值控制的循環(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;然后轉去執(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表示輸入結束):"); intdata=input.nextInt();//讀入用戶輸入的第一個整數(shù) //以下循環(huán)結構循環(huán)讀入用戶輸入的整數(shù),直到遇0為止。 intsum=0;//累加器初始化 while(data!=0){ sum+=data; //讀入用戶輸入的下一個整數(shù) System.out.print("請輸入一個整數(shù)(0表示輸入結束):"); data=input.nextInt(); } System.out.println("它們的和是:"+sum);}}19警告在循環(huán)控制中,不要使用浮點數(shù)來比較值是否相等。因為浮點數(shù)都是某些值的近似值,使用它們可能導致不精確的循環(huán)次數(shù)和不準確的結果。請觀察下面計算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ù)在算術上是近似值,所以,不能確保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是否相等,那么,你就應該使用下面的方法來解決:

while(Math.abs(x1-x2)<1e-6){...}而不能使用下面的代碼: while(x1==x2){...}22*4.2.5

輸入輸出重定向如果你想避免在程序運行過程中輸入大量的數(shù)據,可以將這些數(shù)據用空格隔開,保存在一個文本文件(例如,input.txt)中,然后使用下面這個命令來運行這個程序: javaSentinelValue<input.txt這個命令稱為輸入重定向。它會告訴程序中的讀入方法“input.nextInt();”從文件input.txt中去讀入數(shù)據,而不是讓用戶在運行時從鍵盤輸入數(shù)據。假設input.txt文件的內容是:23456789122332234567899212343531240那么,你用上面這個命令來運行這個程序的話,將得到sum的值為518。

類似地,輸出重定向可以將程序本來在屏幕上顯示的結果發(fā)送到文件中去。輸出重定向的命令是: javaSentinelValue>output.txt可以同一命令中同時使用輸入輸出重定向。例如,下面的命令會從文件input.txt中讀取數(shù)據,并將輸出結果發(fā)送到文件output.txt中:javaSentinelValue<input.txt>output.txt

請使用這個命令來運行這個程序,查看一下output.txt中的內容是什么。234.3

do-while循環(huán)

do-while語句是while語句的變體。其語法格式是:

do{ 語句塊

}while(布爾表達式);它的執(zhí)行流程如圖4-3所示:首先執(zhí)行循環(huán)體;然后計算并判斷循環(huán)條件:如果為true,則重復執(zhí)行循環(huán)體;否則,終止循環(huá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表示輸入結束):"); 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)內都出現(xiàn)。(請對照程序清單4-3和程序清單4-4)26do-while語句應用舉例求解 利用牛頓迭代法求平方根的迭代公式為:當|xn+1?

xn

|<ε時,xn+1即為解的近似值。(提示:x0可以是任意猜測值。為方便起見,可以取a的值。)算法描述如下:(i) x0=a;(ii) x1=x0;(iii) x0=(x1+a/x1)/2;(iv) |x0?x1|<10-6?是,轉至(v);否則轉至(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?是,轉至(v);否則轉至(ii);(v) x0(或x1)就是最后的解。28“迭代法”也叫做“遞推法”,其基本思想是:把一個復雜的計算過程轉化為簡單過程的多次重復,每次重復都從舊值的基礎上遞推出新值,并由新值替代舊值。(最簡單的例子就是“累加器”)294.4

for循環(huán)經常會用到下面的通用形式來編寫循環(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)內使用而不在其他地方使用,那么,在for語句內聲明它是一個很好的習慣。但是,在循環(huán)外就不能使用它了。因為,它的作用范圍被限制于該for語句范圍內!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("請輸入一行字符(回車結束):"); 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)稱為預測試循環(huán),因為循環(huán)條件是在循環(huán)體執(zhí)行前被測試的,而do-while循環(huán)則稱為后測試循環(huán),因為其循環(huán)條件是在循環(huán)體執(zhí)行后測試的。

while循環(huán)總是可以轉化為for循環(huán)。如下所示:

while(循環(huán)條件){ // ...... } for(;循環(huán)條件;){ //循環(huán)體 ...... }38

除某種特殊情況外,for循環(huán)通常也都能轉化為while循環(huán): for(初始操作;循環(huán)條件;每次迭代后的操作){ //循環(huán)體 ...... }

初始操作; while(

循環(huán)條件

){ //循環(huán)體 ......

每次迭代后的操作; }

建議使用自己覺得最自然、最舒服的一種循環(huán)語句。通常,如果已經提前知道重復次數(shù),那就使用for循環(huán)(就像打印字符串100次)。如果無法確定重復次數(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(....){}; { { ...... ..... } }

使用行尾塊風格是避免這種錯誤的最好辦法: for(....;....;.....){ while(....){ ...... ..... } }40

但是,在do-while循環(huán)中,卻需要用分號來結束循環(huán): do{ ..... }while(.....);414.6

嵌套循環(huán)

在一個循環(huán)語句(while循環(huán)、for循環(huán)、do-while循環(huán))內又包含另一個循環(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)嵌套中的內、外層循環(huán)控制變量(例如,i、j)不能同名。它們的意義以及它們之間的關系,好比手表的時針、分針和秒針:時針走一格,分針走一圈;分針走一格,秒針走一圈。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

實例學習循環(huán)語句是程序設計的基礎,編寫循環(huán)語句的能力對于學習程序設計是非常必要的、也是非常重要的。如果能夠使用循環(huán)編寫程序,你就懂得如何編程了!正是由于這個原因,本節(jié)將提供三個實例,學習如何使用循環(huán)來解決問題。

值得再次提醒的是:在編寫解決問題的程序之前,不要立即就開始寫代碼,應該首先考慮一下在不涉及怎樣編寫代碼的情況下,如何手工解決它的邏輯方案。一旦有了一個邏輯方案,再將它翻譯成Java語言的代碼。(當然,翻譯方式不是唯一的。例如,可以選擇使用for語句,也可以選擇while語句。)464.7.1

求最大公約數(shù)其算法可以描述如下:(i)輸入兩個整數(shù)n1、n2。(ii)(由于1可能不是它們的最大公約數(shù),所以可以檢測

2、3、4......

n1及n2的整數(shù))取

k=2;(iii)當k是

n1及n2的整數(shù)時,重復執(zhí)行下面兩步操作:

i)k是n1、n2的最大公約數(shù)嗎? 如果是的,則最大公約數(shù)gcd就是k;(即gcd=k)

ii)k加1;(iv)顯示“最大公約數(shù)是”gcd。上面算法中的(ii)、(iii)可以翻譯成下面的代碼:提示一個問題常常有多種解決方案。最大公約數(shù)問題就有許多解決方案。一個更有效的解決方案是使用經典的“歐幾里得”算法(見習題)。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

預測未來學費

假設某大學今年的學費是10000美金,并以每年7%的速度增加。試問:多少年之后學費會翻倍?首先考慮如何手工解決它:第二年是第一年乘以1.07,.....未來的一年都是前一年乘以1.07。所以,每年的學費可以如下計算:doubletuition=10000;intyear=1;tuition=tuition*1.07;year++;tuition=tuition*1.07;year++;tuition=tuition*1.07;year++;......不斷地計算下去,直到學費tuition達到或者超過20000美金為止。51現(xiàn)在可以將這個邏輯翻譯成使用循環(huán)結構實現(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+"后,學費將翻倍!");}}534.7.3

枚舉法

在某些問題中,需要對可能出現(xiàn)的大量情況進行一一測試,以判斷是否滿足某些(或某個)求解的條件。采用循環(huán)語句可以方便地來解決。例如,“百元買百雞”問題。假定小雞每只0.5元,公雞每只2元,母雞每只3元?,F(xiàn)在有100元錢,要求買100只雞。編程列出所有可能的買雞方案。設,小雞、公雞和母雞分別為chickens、cocks、hens只。根據題意,列出方程組如下: 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

蒙特卡洛模擬

為了更多地學習編程解決問題,本節(jié)給出使用蒙特卡洛方法來估算π的值。為了更好地理解這個方法,需要畫出一個圓的外接正方形。如下圖所示:1-1-11

假設這個圓的半徑是1,那么圓面積就是π而外接正方形的面積就是4。隨機產生正方形中的一個點,該點落在這個圓內的概率是

圓面積/正方形面積:π/4。編寫程序,在正方形內隨機產生1000000個點,用變量numberOfHits對落在圓內的點進行計數(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注:蒙特卡洛模擬方法的原理是當問題或對象根據抽樣計算統(tǒng)計量或者參數(shù)的值,隨著模擬次數(shù)的增多,可以通過對各次統(tǒng)計量或參數(shù)的估計值求平均的方法得到穩(wěn)定結論。(想要了解更多的有關知識,請自行上網檢索。)604.8

關鍵字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; }

//結束循環(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的和。其運行結果是:number的值是:20sum的值是:21062

你也可以在循環(huán)中使用關鍵字continue。當程序遇到continue時,它會結束當前迭代,程序控制將轉向循環(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的和。其運行結果是:sum的值是:21064注意雖說break和continue可以為循環(huán)提供額外的控制,并在某種情況下還可以簡化程序設計。但是,過度地使用或者不正確地使用會使得程序難以讀懂并難以測試。通常,總是可以編寫出在循環(huán)中不使用它們的程序。也就是說,只有在能夠簡化程序代碼并使程序更容易閱讀的情況下,才可以適當?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){//重復執(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)結束}}

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不是質數(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;

}顯然,當上面這個循環(huán)結束后,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;//假設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)結束

if(isPrime){

count++; if(count%10==0)//顯示number后換行 System.out.println(number); else//顯示number后不換行 System.out.print(number+""); } number++;

}//while循環(huán)結束}

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論