第3章 流程控制
程式執行的順序并不會像南北直接貫通的高速公路那樣,可以從北到南一路通到底,事實上程式執行的順序可能複雜到像雲貴高原的公路,九彎十八轉,容易讓人暈頭轉向,是以程式的控制流程就像為公路系統設計的四通八達的通行訓示方向,如圖3-1所示。Java的流程控制一般是按照程式源代碼的順序自上而下按序執行的,不過有時也會根據需要來改變程式執行的順序,此時就是通過流程控制語句或指令來告訴計算機應該優先以哪一種順序來執行程式,程式設計語言中的基本流程控制結構有三種,分别是順序結構、選擇結構和重複結構。本章将介紹Java語言中關于“流程控制”的使用方法。

本章的學習目标
- 程式的流程結構
- 條件結構
- switch條件選擇語句
- 條件運算符
- 循環結構
- 跳轉控制語句
3.1 認識流程控制
Java雖然是一種純粹的面向對象的程式設計語言,但它仍然提供結構化程式設計的基本流程結構,現在分别介紹如下。
1.順序結構
順序結構是以程式的第一行語句為入口點,自上而下(Top-Down)執行到程式的最後一行語句。順序結構在整個程式中沒有特殊的流程、分支或跳轉,大部分的程式都是按照這種結構化子產品(Module)來設計的,如圖3-2所示。
2.選擇結構
選擇結構是使用“條件判斷”表達式的運算結果來決定程式的流程,如果條件成立,就執行一個流程分支;如果條件不成立,就執行另一個流程分支。不過,對于選擇結構要注意的是,無論是條件成立的流程分支還是條件不成立的流程分支,它們流程結束的最終出口都是同一個,如圖3-3所示。if、switch條件語句是選擇結構的典型代表。
3.重複結構
重複結構是一種循環控制,根據所設立的條件重複執行某一段程式語句,直到條件不成立,才會結束循環。重複結構的流程圖如圖3-4所示。
參考圖3-4,“條件判斷”表達式成立時,則進入程式語句1(statement)的分支流程,就是進入重複結構内(循環體内),執行完循環體内的程式語句後再次進入“條件判斷”部分,直到條件不成立時才進入程式語句2(statement),重複結構之外表示結束循環結構了,到循環體之外了。for、while或do-while是程式設計語言中循環結構的典型代表。
3.2 條件選擇語句與條件運算符
Java語言中有if和switch兩種條件選擇語句。if條件語句是各種程式設計語言中常見的條件選擇語句,就是根據所指定的“條件判斷表達式”進行判斷,用判斷的結果來決定程式該執行哪一個程式分支。if條件語句分為三種,分别是if、if-else和if-else-if語句,表3-1所示是它們的文法。
3.2.1 if相關語句
if條件選擇語句隻有在“條件判斷表達式”的結果是true時(條件成立時),才會選擇進入其中的“程式語句區塊”(或稱為程式語句片段);如果條件不成立(條件判斷表達式的結果為false),就會跳離if條件選擇語句。if語句的文法如下:
if (條件判斷表達式) {// 條件判斷表達式可以是“比較兩者之間的關系”,或者複雜的“條件表達式”
程式語句區塊;
}
當if的條件判斷表達式結果為true時,才會執行“程式語句區塊”的部分;如果條件判斷表達式的結果是false,就不會執行“程式語句區塊”的部分。
例如:
if (a < b) {
System.out.println ("比較結果正确");
}
又如若要判斷a的值比0大,則列印輸出“正整數”,語句如下:
if (a >0) {
System.out.println ("正整數");
}
【範例程式:CH03_01】
01 /*檔案:CH03_01.java
02 *說明:if條件選擇語句
03 */
04
05 public class CH03_01 {
06 public static void main(String[] ages) {
07
08 //if條件選擇語句使用範例
09 int Tim=20,Tracy=23;
10 System.out.println("Tim年齡="+Tim+",Tracy年齡="+Tracy);
11
12 if (Tim<Tracy){
13 System.out.println("Tim年齡比Tracy小"+'\n');
14 }
15
16 Tim=25;
17 System.out.println("Tim年齡="+Tim+",Tracy年齡="+Tracy);
18 if (Tim>Tracy){
19 System.out.println("Tim年齡比Tracy大"+'\n');
20 }
21
22 Tim=23;
23 System.out.println("Tim年齡="+Tim+",Tracy年齡="+Tracy);
24 if (Tim==Tracy){
25 System.out.println("Tim年齡和Tracy一樣");
26 }
27 }
28 }
【程式的執行結果】
程式的執行結果可參考圖3-5。
【程式的解析】
第09行:聲明變量Tim和Tracy,并賦予初始年齡,Tim是20歲、Tracy是23歲。
第12行:if條件選擇語句的條件判斷表達式為“Tim第16行:更改Tim的年齡,将Tim指派為25,即25歲。if條件選擇語句的條件判斷表達式為“Tim>Tracy”,如果該條件成立(true),就顯示“Tim年齡比Tracy大”;如果該條件不成立(false),就不再繼續往下執行if條件選擇語句(第18~20行的程式代碼),離開此段程式代碼,繼續往下執行。
第22行:更改Tim的年齡,将Tim指派為23,即23歲。if條件選擇語句的條件判斷表達式為“Tim==Tracy”,如果該條件成立(true),就顯示“Tim年齡和Tracy一樣”;如果該條件不成立(false),就不再繼續往下執行if條件選擇語句(第24~26行的程式代碼),離開此段程式代碼。
3.2.2 if-else相關語句
在3.2.1小節的if條件選擇語句中,隻有條件成立才會執行“{”和“}”大括号内的語句,如果條件不成立,就跳出if條件選擇語句,沒有任何列印輸出的内容。但是,如果條件不成立時有另外的程式執行分支,就可以考慮使用if-else條件選擇語句。例如,當if條件判斷表達式結果為true時,執行“程式語句區塊(1)”;當條件判斷表達式結果為false時,執行“程式語句區塊(2)”。if-else條件選擇語句的文法如下:
【if-else條件選擇語句的文法】
if (條件判斷表達式) {
程式語句區塊 (1);
}
else {
程式語句區塊 (2);
}
例如要設計一段程式代碼,如果a的值比b的值小,就列印輸出“比較結果正确”;否則列印輸出“比較結果不正确”,這段程式代碼的編寫如下:
if (a < b) {
System.out.println ("比較結果正确") ;
}else {
System.out.println ("比較結果不正确") ;
}
值得注意的是“程式語句區塊”定義的問題,也就是大括号的标示問題,尤其是else之後的程式語句區塊部分要記得加上大括号的标示,否則無法正确執行。
【範例程式:CH03_02】
01 /*檔案:CH03_02.java
02 *說明:if-else條件選擇語句
03 */
04
05 public class CH03_02{
06 public static void main(String[] ages) {
07
08 //if-else條件選擇語句使用範例
09 int Tim=27,Tracy=23;
10 System.out.println("Tim年齡="+Tim+",Tracy年齡="+Tracy);
11
12 if (Tim<Tracy) {
13 System.out.println("Tim年齡比Tracy小"+'\n');
14 }else {
15 System.out.println("Tim年齡比Tracy大");
16 }
17 }
18 }
程式的執行結果可參考圖3-6。
第12行:條件判斷表達式為“Tim第14行:加入else的語句,增加了條件不成立時的程式執行分支,加強了判斷結果的明确性。
3.2.3 if-else-if相關語句
if-else-if條件選擇語句是if條件選擇語句的變形,用來判斷多個條件。此條件選擇語句可以使用else if判斷多個條件,當其中某個if條件判斷表達式為true時,就會執行它對應的程式語句區塊。if-else-if語句執行條件判斷表達式的順序是自上而下,每次遇到if語句就需要進行“條件判斷”,如果一直到最後所有的if語句都不成立,就執行最後一個else的程式語句區塊。這種用法可以指定需要判斷的各種情況,也能了解當條件不成立時原因為何。if-else-if條件選擇語句的文法如下:
if (條件判斷表達式) {
程式語句區塊 (1);
}else if (條件判斷表達式) {
程式語句區塊 (2);
}else {
程式語句區塊 (3);
}
if (a < b) {
System.out.println ("比較結果正确 a<b") ;
}else if (a>b) {
System.out.println ("比較結果正确 a>b") ;
} else {
System.out.println ("兩個數值相同") ;
}
【範例程式:CH03_03】
01 /*檔案:CH03_03.java
02 *說明:if-else-if條件選擇語句(1)
03 */
04
05 public class CH03_03 {
06 public static void main(String[] ages) {
07
08 //if-else-if條件選擇語句使用範例
09 int Tim=27,Tracy=23;
10 System.out.println("Tim年齡="+Tim+",Tracy年齡="+Tracy);
11
12 if (Tim<Tracy){
13 System.out.println("Tim年齡比Tracy小"+'\n');
14 }else if (Tim>Tracy){
15 System.out.println("Tim年齡比Tracy大"+'\n');
16 }else{
17 System.out.println("Tim和Tracy年齡相同");
18 }
19
20 Tim=23;
21 System.out.println("Tim年齡="+Tim+",Tracy年齡="+Tracy);
22 if (Tim<Tracy){
23 System.out.println("Tim年齡比Tracy小"+'\n');
24 }else if (Tim>Tracy){
25 System.out.println("Tim年齡比Tracy大"+'\n');
26 }else{
27 System.out.println("Tim和Tracy年齡相同");
28 }
29 }
30 }
程式的執行結果可參考圖3-7。
第20行:設定Tim的年齡為23歲,和Tracy相同。于是條件判斷的結果一直到第26行程式語句才得知,兩人的年齡既沒有“Tim比Tracy大”,也沒有“Tim比Tracy小”,則最終的結果顯示為“Tim和Tracy年齡相同”。
我們再來看另一個例子。
【範例程式:CH03_04】
01 /*檔案:CH03_04.java
02 *說明:if-else-if條件選擇語句(2)
03 */
04
05 public class CH03_04{
06 public static void main(String[] ages){
07
08 //變量聲明
09 int score=88;
10 System.out.println("Tim學期成績總分="+score);
11 //if-else-if條件選擇語句使用範例
12 if(score>=90){
13 System.out.println("測驗得分等級:A"+'\n');
14 }else if((score>=70)&&(score<90)){
15 System.out.println("測驗得分等級:B"+'\n');
16 }else{
17 System.out.println("測驗得分等級:C"+'\n');
18 }
19
20 score=60;
21 System.out.println("Tracy學期成績總分="+score);
22 if(score>=90){
23 System.out.println("測驗得分等級:A"+'\n');
24 }else if((score>=70)&&(score<90)){
25 System.out.println("測驗得分等級:B"+'\n');
26 }else{
27 System.out.println("測驗得分等級:C"+'\n');
28 }
29 }
30 }
程式的執行結果可參考圖3-8。
第12~18行:如果學期總成績(score)為88分,那麼換算成等級應該屬于什麼等級?“score>=90”為等級A、“70<=score<90”為等級B、“score<=70”為等級C。
第14、24行:對于“70<=score<90”的描述,使用AND(&&)邏輯運算符。
3.2.4 嵌套if語句
嵌套if語句是指“内層”的if語句是另一個“外層”if的子語句,此子語句可以是if語句、else語句或者if-else語句。
【嵌套if條件選擇語句的文法】
if (條件判斷表達式1) {
程式語句區塊 (1);
if (條件判斷表達式2) {
程式語句區塊 (2);}
else {
程式語句區塊 (3);
}
}
【範例程式:CH03_05】
01 /*檔案:CH03_05.java
02 *說明:嵌套if語句
03 */
04
05 public class CH03_05{
06 public static void main(String[] ages){
07
08 //變量聲明
09 int a=0,b=0;
10 System.out.println("AND邏輯門=("+a+","+b+")");
11 if (a==1){
12 if (b==1){
13 System.out.println(a+"(AND)"+b+"="+"1"+'\n');
14 }
15 else{
16 System.out.println(a+"(AND)"+b+"="+"0"+'\n');
17 }
18 }
19 else{
20 System.out.println(a+"(AND)"+b+"="+"0"+'\n');
21 }
22 a=1;
23 System.out.println("AND邏輯門=("+a+","+b+")");
24 if (a==1){
25 if (b==1){
26 System.out.println(a+"(AND)"+b+"="+"1"+'\n');
27 }
28 else{
29 System.out.println(a+"(AND)"+b+"="+"0"+'\n');
30 }
31 }
32 else{
33 System.out.println(a+"(AND)"+b+"="+"0"+'\n');
34 }
35 a=1;
36 b=1;
37 System.out.println("AND邏輯門=("+a+","+b+")");
38 if (a==1){
39 if (b==1){
40 System.out.println(a+"(AND)"+b+"="+"1"+'\n');
41 }
42 else{
43 System.out.println(a+"(AND)"+b+"="+"0"+'\n');
44 }
45 }
46 else{
47 System.out.println(a+"(AND)"+b+"="+"0"+'\n');
48 }
49 }
50 }
程式的執行結果可參考圖3-9。
判斷AND邏輯運算的結果。隻有當參與AND邏輯運算的兩個操作數同為1時,AND邏輯運算的結果才為1;其他組合的邏輯運算結果都為0。
第09~48行:若a=1且b=1,則顯示結果為1,其餘組合則顯示結果為0。
3.2.5 switch條件選擇語句
在進行多重選擇的時候,過多if-else-if條件選擇語句的嵌套會造成程式維護上的困擾。在Java語言中提供了switch條件選擇語句,使用它可以讓程式更加簡潔清楚。與if條件選擇語句不同的是,switch隻有一個條件判斷表達式。switch是一種多選一的條件選擇語句,它是按照條件判斷表達式的運算結果來決定在多個程式分支中選擇其中之一的程式分支,并執行這個程式分支内的程式代碼。switch條件選擇語句的文法如下:
switch (表達式) {
case 數值1;
語句1;
break;
case 數值2;
語句2;
break;
default:
語句3;
}
在switch條件選擇語句中,如果找到了case後面比對的結果值,就會執行該case程式區塊内的程式語句,當執行完這個case程式區塊中的程式語句之後,程式流程并不會直接離開switch語句,還會往下繼續執行其他case語句與default語句,這樣的情況被稱為“貫穿”(Falling Through)現象。
是以,我們通常在每個case程式區塊後面加上break語句來結束switch語句,這樣才可以避免“貫穿”的情況。至于default語句,我們可以把它放在switch語句的任何位置,表示如果找不到任何比對的結果值,最後就要執行default語句。此外,如果default語句擺在所有case語句的最後,就可以省略default程式區塊最後的break語句,否則就必須加上break語句來結束switch語句。另外,在switch語句中的花括号絕不可省略,這是“事故多發地”(程式容易出錯的地方)。
如圖3-10所示是switch 條件選擇語句的流程圖。
假如要從期末排名給予對應的獎勵,使用switch條件選擇語句的文法如下:
switch (期末排名) {
case 第一名:
出國旅行;
break;
case 第二名:
國内旅行;
break;
case 第三名:
購書禮券;
break;
default:
要多努力;
}
在上述的程式代碼中,若排名是第一名,則獲得的獎勵是“出國旅行”;若排名是第二名,則獲得的獎勵是“國内旅行”;若排名是第三名,則獲得的獎勵是“購書禮券”;但若名次不在前三名,則沒有獎勵。
【範例程式:CH03_06】
01 /*檔案:CH03_06.java
02 *說明:switch條件選擇語句
03 */
04
05 public class CH03_06{
06 public static void main(String[] ages){
07
08 //變量聲明
09 char math_score='A';
10 System.out.println("Michael數學成績:"+math_score);
11 switch(math_score){
12 case'A':
13 System.out.println("老師評語:非常好!真是優秀!"+'\n');
14 break; // break的作用是跳離switch條件選擇語句
15 case'B':
16 System.out.println("老師評語:也不錯,但還可以更好!"+'\n');
17 break; // break的作用是跳離switch條件選擇語句
18 case'C':
19 System.out.println("老師評語:真的要多用功!"+'\n');
20 break; // break的作用是跳離switch條件選擇語句
21 default:
22 System.out.println("老師評語:不要貪玩,為自己多讀書!"+'\n');
23 }
24
25 math_score='C';
26 System.out.println("Jane數學成績:"+math_score);
27 switch(math_score){
28 case'A':
29 System.out.println("老師評語:非常好!真是優秀!"+'\n');
30 break; // break的作用是跳離switch條件選擇語句
31 case'B':
32 System.out.println("老師評語:也不錯,但還可以更好!"+'\n');
33 break; // break的作用是跳離switch條件選擇語句
34 case'C':
35 System.out.println("老師評語:真的要多用功!"+'\n');
36 break; // break的作用是跳離switch條件選擇語句
37 default:
38 System.out.println("老師評語:不要貪玩,為自己多讀書!"+'\n');
39 }
40 }
41 }
程式的執行結果可參考圖3-11。
第09行:聲明存儲數學成績的變量math_score,并賦初值。
第11~23行:switch語句的條件判斷表達式為math_score,若math_score=A,則顯示“老師評語:非常好!真是優秀!”;若math_score=B,則顯示“老師評語:也不錯,但還可以更好!”;若math_score=C,則顯示“老師評語:真的要多用功!”;若math_score不是A或B或C,則顯示“老師評語:不要貪玩,為自己多讀書!”。
每一個case程式語句區塊結束位置都會加上break語句,目的是說明如果已經滿足該case的條件,其餘的case條件就不需要再進行比較,可以離開switch語句了。
3.2.6 條件運算符
條件運算符(Conditional Operator)是一個三元運算符(Ternary Operator,或稱為三目運算符),它和if else條件選擇語句的功能一樣,可以用來替代簡單的if else條件選擇語句,讓程式代碼看起來更為簡潔,它的文法格式如下:
條件判斷表達式?程式語句一:程式語句二;
如果條件判斷表達式成立,就會執行程式語句一;否則執行程式語句二。不過使用條件運算符隻允許單行語句,例如:
str = ( num>=0 )? "正數":"負數"
等号的右邊是“條件判斷表達式”,問号“?”表示if,冒号“:”表示else。是以,上面的範例說明:如果num的值大于等于0,就顯示“正數”,否則顯示“負數”。
【範例程式:CH03_07】
01 /*檔案:CH03_07.java
02 *說明:條件運算符
03 */
04
05 public class CH03_07{
06 public static void main(String[] ages){
07
08 //變量聲明
09 int math_score=70;
10 System.out.println("Michael數學成績:"+math_score);
11 String str;
12 str=(math_score>80)?"非常好!":"多加油!";
13 System.out.println("老師評語:"+str+'\n');
14
15 math_score=90;
16 System.out.println("Jane數學成績:"+math_score);
17 str=(math_score>80)?"非常好!":"多加油!";
18 System.out.println("老師評語:"+str+'\n');
19 }
20 }
程式的執行結果可參考圖3-12。
第11行:聲明用于存儲結果的字元串變量。
第12行:意思是指:如果成績高于80,老師的評語為“非常好!”;如果成績低于80,老師的評語為“多加油!”。
使用條件運算符的方式可以減少程式的複雜度,但是它的條件判斷功能比較簡單,受到限制。
3.3 計數循環與條件循環
循環語句屬于重複結構中的流程控制語句,當設定的條件符合時,就會執行循環中的程式語句,一旦條件不符合就會跳出循環。循環語句分為for、while和do-while三種。
假如想要讓計算機在螢幕上列印出500個字元'*',我們并不需要大費周章地編寫500次System.out.print語句,這時隻需要使用重複結構即可。Java語言提供了for、while以及do-while三種循環語句來實作重複結構的效果。在尚未開始正式介紹循環語句之前,我們先通過表3-2快速看看這三種循環語句的特性及使用時機。
3.3.1 for循環
for循環又稱為計數循環,是程式設計中較常使用的一種循環形式,可以重複執行固定次數的循環。for語句是一種較嚴謹的循環語句,是一種計數循環(Counting Loop),循環語句中設定有“循環計數變量的起始值”“循環條件”和“循環計數變量的遞增或遞減表達式”。for語句的聲明文法如下:
for (循環計數變量的起始值;循環條件;循環計數變量的遞增或遞減表達式)
{
程式語句區塊;
}
- 循環計數變量的起始值:是for循環第一次開始時循環計數變量的初值。
- 循環條件:當for語句循環的條件結果為false時,循環就會結束。
- 循環計數變量的遞增或遞減表達式:每輪循環執行後,循環變量要增加或減少的表達式。
for 循環的執行步驟說明如下。
步驟1:設定循環計數變量的起始值。
步驟2:如果循環條件表達式的結果為真(true),就執行for循環體内的程式語句。
步驟3:循環體内的程式語句執行完成之後,增加或減少循環計數變量的值,遞增或遞減的步長可以根據需求而定,再重複步驟2。
步驟4:如果循環條件表達式的結果為假(false),就結束for循環。
for (int i=0;i <=5;i++)
{
a=a+1;
}
上面的程式表示:循環計數變量的起始值i=0,重複執行次數是循環條件i<=5成立時,循環變量的遞增量是1(步長為1)。若未超出重複執行次數(循環條件依然成立時),則執行“a=a+1”;若i=6,超出了重複執行次數(循環條件i<=5不成立了),則結束for循環。
【範例程式:CH03_08】
01 /*檔案:CH03_08.java
02 *說明:for循環應用範例
03 */
04 public class CH03_08{
05 public static void main(String args[]){
06 System.out.println("計算1~10之間所有奇數的和");
07 int sum=0;//聲明存儲奇數總和的變量,并賦初值為0
08 System.out.println("1~10之間所有的奇數為:");
09 for(int i=1; i<=10;i++){
10 if(i%2!=0){//使用if語句判斷i是否為奇數
11 sum+=i;
12 System.out.print(i+" ");
13 }
14 }
15 System.out.println();
16 System.out.println("答案="+sum);//輸出答案
17 }
18 }
程式的執行結果可參考圖3-13。
第10行:使用i%2的結果判斷i是否為奇數,當i為奇數時i%2的結果應該為1。
第09~14行:是for循環。循環條件“i<=10”表示循環總共要執行11次,因為i一直增加到11時,“i<=10”的循環條件就不成立了,即達到循環結束的條件。是以當i=11時,就不會再進入for循環體,第10~13行的程式代碼共執行了10次。
3.3.2 嵌套for循環
所謂嵌套for循環,就是多層的for循環結構。在嵌套for循環結構中,執行流程必須先等内層循環執行完畢,才會逐層繼續執行外層循環。注意容易犯錯的地方是内外循環間不可交錯。嵌套for循環的典型應用例子是“九九乘法表”。嵌套for語句的文法如下:
for ( 外層循環的計數變量起始值;循環條件;計數變量的遞增或遞減值 ) {
for ( 内層循環的計數變量起始值;循環條件;計數變量的遞增或遞減值 ) {
程式語句區塊;
}
};
【範例程式:CH03_09】
01 /*檔案:CH03_09.java
02 *說明:嵌套for循環應用範例
03 */
04
05 public class CH03_09{
06 public static void main(String[] ages){
07 for (int i=1;i<=9;i++){
08 for (int j=1;j<=9;j++){
09 System.out.print(i+"*"+j+"="+i*j+'\t');
10 }
11 System.out.print('\n');
12 }
13 }
14 }
程式的執行結果可參考圖3-14。
3.3.3 while循環
如果循環執行的次數可以确定,那麼for循環就是最佳的選擇。對于那些不能确定循環次數的循環,while循環就可以派上用場了。while循環與for循環類似,都屬于前測試型循環。前測試型循環的工作方式是在循環體開始執行前必須先檢查循環條件表達式,當表達式結果為真(true)時,才會執行循環體内的程式語句;如果循環條件表達式結果為假(false),就會結束循環。While循環語句的文法如下:
while (循環條件表達式 )
{
循環體内的程式語句;
循環條件變量的變化;
}
如圖3-15所示為while循環的流程圖。
當while語句的循環條件表達式的結果為真(true)時,就會重複執行循環體内的程式語句,直到循環條件表達式的結果為假(false),才會結束while循環。在進行while循環時,通常會先在while循環之前加上一個變量并賦初值,用于控制while循環的變量,在while循環體内根據循環的需要更改這個變量的值,以便在執行新一輪循環前用來測試循環條件是否成立,例如:
while (i<=10 )
{
a=i+1;
i++; //更改循環變量的值
}
While語句括号内的部分是“循環條件”,“i<=10”表示隻有i值小于等于10,才能夠進入while循環體内,執行“a=i+1”,而後更改循環變量i的值(在此例中是用i++遞增的)。
【範例程式:CH03_10】
01 /*檔案:CH03_10.java
02 *說明:while循環應用範例
03 */
04 public class CH03_10{
05 public static void main(String args[ ]){
06 int n=1,sum=0;//聲明while循環變量n并賦初值,聲明存儲累加值的變量sum
07 //while循環開始
08 while(n<=10){
09 System.out.print("n="+n);
10 sum+=n;//計算n的累加值
11 System.out.println("\t累加值="+sum);
12 n++;
13 }
14 System.out.println("循環結束");
15 }
16 }
程式的執行結果可參考圖3-16。
第08行:n<=10是while語句的循環條件表達式,當該表達式的結果為真(true)時,就會重複執行循環體内的程式語句。
第12行:将計數器n遞增1,再回到第08行檢查循環條件是否依然成立,如果表達式結果為假(false),就會結束這個while循環,繼續執行while循環體後面的第14行程式語句。
3.3.4 do-while循環
do-while循環是先執行循環體内的程式語句,再測試循環條件是否成立,這與之前的for循環、while循環不同。do-while循環屬于“後測型”循環,for循環、while循環屬于“前測型”循環。do-while循環無論如何都會執行一次循環體内的程式語句,再測試循環條件是否成立,如果成立,就傳回循環起點,重複執行循環體内的程式語句。
do-while循環與while循環類似,兩者的差别就是循環條件表達式所在的位置有前後之分。do-while循環語句的文法如下:
do {
循環體内的程式語句;
循環條件變量的變化;
} while (循環條件表達式);
【範例程式:CH03_11】
01 /*檔案:CH03_11.java
02 *說明:do-while循環應用範例
03 */
04 public class CH03_11{
05 public static void main(String args[]){
06 int n=40,m=180;
07 int temp=0;//作為n與m值互換的中間暫存變量
08 System.out.println("n="+n+",m="+m);
09 //do-while循環開始
10 do{
11 temp=m%n;
12 m=n;
13 n=temp;
14 }while(n!=0 );//檢查循環條件表達式
15 System.out.println("兩個數的最大公約數="+m);
16 }
17 }
程式的執行結果可參考圖3-17。
第11行:将m%n的運算結果(餘數)指派給temp,此處m的值必須大于n的值。
第12~13行:借助中間暫存變量temp将n與m的值對調,因為此時n的值大于m的值。
3.3.5 無限循環
在循環語句中設定循環條件表達式時,必須注意不能使循環條件永遠成立,否則就會形成無限循環(或稱為死循環)。下面列出幾個常見的無限循環的例子,請大家在編寫循環語句的時候避免出現無限循環。
while(true){ } //while語句中的循環條件永遠為true
for(;;){ } //for語句中沒有設定任何循環條件
for(int i=1;i>0;i++){ } //循環條件與初始值相比較永遠成立
3.4 控制跳轉語句
控制跳轉語句(Control Jump Statement)是Java語言中與循環語句搭配使用的一種流程控制語句,控制跳轉語句的使用能讓循環的流程控制有更多的變化。控制跳轉語句有break、continue和return三種語句。
3.4.1 break語句
在介紹switch語句時提到過break語句,使用它可以跳離switch語句,繼續執行switch語句後的其他程式語句。不過,break語句不僅可以搭配switch語句,還可以和循環語句搭配使用。break是“中斷”的意思,break語句可以中斷循環的執行并跳轉到标簽(Label)語句定義的一段程式語句區塊,類似于C++語言中的goto語句。break語句的文法如下:
标簽名稱:
程式語句;
……
break 标簽名稱;
事先建立好break的标簽位置及名稱,當程式執行到break的程式代碼時,就會根據所定義的break标簽名稱跳轉到标簽指定的地方。
【範例程式:CH03_12】
01 /*檔案:CH03_12.java
02 *說明:break語句應用範例
03 */
04 public class CH03_12{
05 public static void main(String args[]){
06 int i ,j;
07 System.out.println("跳離一層循環");
08 for(i=1; i<10; i++){
09 for(j=1; j<=i; j++){
10 if(j==5) break ;//跳離一層循環
11 System.out.print(j);
12 }
13 System.out.println();
14 }
15 System.out.println();
16
17 System.out.println("跳離雙層循環");
18 out1://設定标簽
19 for(i=1; i<10; i++){
20 for(j=1; j<=i; j++){
21 if(j==5) break out1;//跳轉到标簽處
22 System.out.print(j);
23 }
24 System.out.println();
25 }
26 System.out.println();
27 }
28 }
程式的執行結果可參考圖3-18。
第10行:此處的break語句隻會跳離第9~12行的for循環(内層循環)。
第8~14行:執行過程如下:
i=1→j=1→顯示結果:1。
i=2→j=1~2→顯示結果:12。
i=3→j=1~3→顯示結果:123。
……
i=5→j=1~5→顯示結果:1234(不會顯示5,因為已經跳離循環)。
i=6→j=1~6→顯示結果:1234。
i=9→j=1~9→顯示結果:1234。
i=10(i<10不成立,結束循環)。
第18行:設定break語句要跳轉的标簽位置及名稱(out1):
break out1;程式語句,會跳出第19~25的雙層循環。
i=5→j=1~5→顯示結果:1234(不會顯示5,而且已經跳離循環,跳轉到第18行程式代碼最外層循環的位置,并且結束循環)。
3.4.2 continue語句
continue 語句的功能是強制for、while、do-while等循環語句終止目前這一輪的循環,而将控制權轉移到循環開始處進行下一輪循環,也就是跳過本輪循環中尚未執行的語句,開始執行下一輪的循環。continue是“繼續”的意思,continue 語句與 break 語句最大的差别在于continue 隻是跳過它之後未執行的語句,但并未跳離循環。continue語句也可以配合标簽指令改變程式執行的流程。
【範例程式:CH03_13】
01 /*檔案:CH03_13.java
02 *說明:continue語句應用範例
03 */
04 public class CH03_13{
05 public static void main(String args[]){
06 int i ,j;
07 for(i=1; i<10; i++){
08 for(j=1; j<=i; j++){
09 if(j==5) continue ;//跳過下面的程式語句繼續執行下一輪循環
10 System.out.print(j);
11 }
12 System.out.println();
13 }
14 System.out.println();
15 out1:
16 //設定标簽
17 for(i=1; i<10; i++){
18 for(j=1; j<=i; j++){
19 if(j==5) continue out1;//跳轉到标簽處繼續執行
20 System.out.print(j);
21 }
22 System.out.println();
23 }
24 System.out.println();
25 }
26 }
程式的執行結果可參考圖3-19。
第09行:當程式執行到j==5時,會跳過第10行,從第8行的循環開始執行下一輪循環。
第07~13行:執行過程如下:
i=5→j=1~5→顯示結果:1234(不會顯示5,因為continue語句會跳過第10行程式代碼)。
i=6→j=1~6→顯示結果:12346。
i=9→j=1~9→顯示結果:12346789。
第19行:continue語句加上标簽會直接跳過第20行程式語句,從第15行繼續執行。
第17~23行:執行過程如下:
i=4→j=1~4→顯示結果:1234。
i=5→j=1~5(不會顯示5,而且跳轉到第15行程式代碼continue語句标簽處,開始執行下一輪for循環。因為第20行的輸出顯示沒有換行,是以輸出結果彼此相連)。
是以,直到i=9→j=1~9→顯示結果:12341234123412341234(從結果可以看出共有5組1234第一組是i=5的顯示結果;第二組是i=6的顯示結果;第三組是i=7的顯示結果;第四組是i=8的顯示結果;第五組是i=9的顯示結果)。
3.4.3 return語句
return語句可以終止程式目前所在的方法(Method)回到調用方法的程式語句。在面向過程的程式設計語言中,return作為函數調用的傳回語句,我們可以把面向對象程式設計語言中的方法(Method)了解成函數(Function)。使用return語句時,可以将方法中的變量值或表達式運算的結果值傳回給調用的程式語句,不過傳回值的資料類型要和聲明的資料類型相符合,如果方法不需要傳回值,那麼可以将方法聲明為void資料類型。以下是return語句的使用方法。
【return語句的文法】
return 變量或表達式;
return; // 沒有傳回值
【範例程式:CH03_14】
01 /*檔案:CH03_14.java
02 *說明:return語句應用範例
03 */
04 public class CH03_14{
05 public static void main(String args[]){
06 int ans;
07 ans=sum(10);//調用sum方法
08 System.out.println("1~10的累加");
09 System.out.println("ans="+ans);
10 }
11
12 //sum方法
13 static int sum(int n){
14 int sum=0;
15 for(int i=1; i<=n; i++){
16 sum+=i;
17 }
18 return sum; //傳回sum變量的值
19 }
20 }
程式的執行結果可參考圖3-20。
第07行:用變量ans來接收sum方法傳回的值,其中10為傳遞的實際參數。
第13~19行:sum()方法的定義區塊,将該方法聲明為static,可以直接被調用和執行,而不必通過類對象的方式。
3.4.4 for-each的for循環
for-each循環和傳統for循環不同的地方是,for-each可以直接讀取“集合(Set)類型”的資料,如數組。for-each可以使循環自動化,不用程式設計人員動手設定循環的計數值、起始值和循環條件(或循環終止值),也不用設定“數組的索引值”,好處是避免索引值超過數組邊界而造成錯誤。for-each語句的文法如下:
for(變量名稱:集合類型){
程式語句區塊;
}
下面舉個例子來說明。假如A是一個數組,其元素的内容或值是整數類型的。如果要讀取數組中元素的值,一般的方式是使用傳統for循環來執行讀取的操作,而讀取數組元素是通過“索引值”(也稱為數組的“下标值”),但是這種方式的風險是可能會引發索引值超過數組邊界的錯誤。
for-each改變了傳統的做法,當進入for-each循環時,讀取方式不再是通過索引值,而是直接讀取數組中的元素值,是以第一次進入循環,x=1,這個1不是指數組的索引值,而是指元素值。是以x是否聲明成整數類型(int)要由數組來決定。圖3-21中的兩個圖對比了傳統for循環與for-each循環讀取上的不同之處。
對比文法,“int x”就是“變量名稱”部分,“A”就是“集合類型”部分,集合類型指的是所聲明的數組。
【範例程式:CH03_15】
01 /*檔案:CH03_15.java
02 *說明:for-each循環應用範例
03 */
04
05 public class CH03_15{
06 public static void main(String[] ages){
07 int A[]={1,2,3,4,5,6,7,8,9};
08 char B[]={'H','a','p','p','y'};
09 System.out.println("數字數組"); // 用傳統for循環讀取數組元素
10 for (int i=0;i<A.length;i++){
11 System.out.print(A[i]+" ");
12 }
13 System.out.println('\n');
14 System.out.println("字元數組");
15 for (int i=0;i<B.length;i++) {
16 System.out.print(B[i]+" ");
17 }
18 System.out.println('\n');
19 System.out.println("數字數組"); // 用for-each循環讀取數組元素
20 for (int i:A){
21 System.out.print(i+" "); //直接讀取數組中的元素值
22 }
23 System.out.println('\n');
24 System.out.println("字元數組");
25 for (char i:B){
26 System.out.print(i+" ");// 因為數組B的元素值是字元,
是以i必須聲明成char 資料類型
27 }
28 System.out.println('\n');
29 }
30 }
程式的執行結果可參考圖3-22。
第20行:for-each循環讀取數組中的元素值,在for-each聲明中的“變量”的資料類型是由數組的元素決定的。“變量”的屬性是“隻讀的”,意思就是隻能讀取的屬性,不能更改或寫入的屬性。
如果是多元數組,那麼将如何使用for-each循環呢?下面通過範例程式來實作多元數組的for-each循環的用法。
【範例程式:CH03_16】
01 /*檔案:CH03_16.java
02 *說明:for-each——讀取多元數組的應用範例
03 */
04
05 public class CH03_16{
06 public static void main(String[] ages){
07 int A[][]=new int[2][3]; //聲明多元數組
08 for (int i=0;i<2;i++){ //給數組中的元素指派,并且讀取數組元素值
09 for (int j=0;j<3;j++){
10 A[i][j]=i+j;
11 System.out.print(A[i][j]+" ");
12 }
13 }
14 System.out.println('\n');
15 for (int i[]:A){ // 改用for-each循環讀取數組元素值
16 for (int j:i){
17 System.out.print(j+" ");
18 }
19 }
20 System.out.println('\n');
21 }
22 }
程式的執行結果可參考圖3-23。
第15~19行:二維數組其實就是數組中的數組。是以,在第15行的外層循環,int i[ ]表示讀取的是一整組的一維數組,在第16行的内層循環則是針對外層循環所指定的一維數組讀取其中的元素值。
3.5 進階應用練習執行個體
本章主要讨論了Java的三種基本流程控制結構及其相關的語句,它們是順序結構、選擇結構與重複結構。下面通過本節的綜合練習讓大家對本章所講述的内容有更深入的認識。
3.5.1 使用條件選擇語句進行考試成績的評級
條件選擇語句根據測試條件選擇性地執行某些分支的程式語句區塊,它包含兩種不同作用的流程控制語句:if…else與switch…case條件選擇語句。兩者最大的差異在于:switch...case語句隻能引入一個參數,也就是說它無法執行“比較”與“判斷”的操作。下面的範例程式綜合運用上述兩種流程控制語句來完成某項考試成績的評級工作。
【綜合練習】使用條件選擇語句進行考試成績的評級
01 //使用條件選擇語句進行考試成績的評級
02 class WORK03_01 {
03 public static void main(String args[]) {
04 int score = 88;
05 int level = 0;
06 //嵌套if…else語句
07 System.out.println("使用if...else語句進行判斷");
08 if (score >= 60) {
09 if(score >= 75) {
10 if(score >= 90) {
11 System.out.println("成績" + score + " 是甲等!");
12 level = 1;
13 }
14 else {
15 System.out.println("成績" + score + " 是乙等!");
16 level = 2;
17 }
18 }
19 else {
20 System.out.println("成績" + score + " 是丙等!");
21 level = 3;
22 }
23 }
24 else
25 System.out.println("成績" + score + " 不及格!");
26 // switch…case語句
27 System.out.println("使用switch...case語句判斷");
28 switch(level) {
29 case 1:System.out.println("成績" + score + " 是甲等!");break;
30 case 2:System.out.println("成績" + score + " 是乙等!");break;
31 case 3:System.out.println("成績" + score + " 是丙等!");break;
32 default:System.out.println("成績" + score + " 是丁等!");break;
33 }
34 }
35 }
程式的執行結果可參考圖3-24。
3.5.2 閏年的判斷與應用
判斷閏年的問題也适合用以上結構來解決,閏年計算的規則是“四年一閏,百年不閏,四百年一閏”。下面的範例程式使用if else if條件選擇語句來執行閏年的計算規則,以判斷某一年份是否為閏年。
【綜合練習】閏年的判斷與應用
01 //閏年的判斷與應用
02 public class WORK03_02 {
03 public static void main(String args[]) {
04 int year=2008;//聲明存儲年份的變量,并指派
05 //聲明整數變量
06 if(year % 4 !=0) /*如果year不是4的倍數*/
07 System.out.println(year+" 年不是閏年。"); /*顯示year不是閏年*/
08 else if(year % 100 ==0) /*如果year是100的倍數*/
09 {
10 if(year % 400 ==0) /*且year是400的倍數*/
11 System.out.println(year+" 年是閏年。");
12 /*顯示year是閏年*/
13 else /*否則*/
14 System.out.println(year+" 年不是閏年。");
15 /*顯示year不是閏年*/
16 }
17 else /*否則*/
18 System.out.println(year+" 年是閏年。"); /*顯示year是閏年*/
19 }
20 }
程式的執行結果可參考圖3-25。
3.5.3 使用各種循環計算1~50的累加之和
循環常被用來計算某一範圍的數字總和。下面的範例程式就是使用三種循環來計算1~50的累加之和。
【綜合練習】使用各種循環計算1~50的累加之和
01 //使用各種循環計算1~50的累加之和
02 class WORK03_03 {
03 public static void main(String args[]) {
04 int totalSum = 0;
05 int var1 = 1;
06 int var2 = 1;
07 int var4 = 50;
08 //while循環
09 while(var1 <= var4) {
10 totalSum += var1;
11 var1 += 1;
12 }
13 System.out.println("用while循環計算1至50的累加之和為" + totalSum);
14 totalSum = 0;
15 //do…while循環
16 do {
17 totalSum += var2;
18 var2 += 1;
19 }while(var2 <= var4);
20 System.out.println("do…while循環計算1至50的累加之和為" + totalSum);
21 totalSum = 0;
22 //for循環
23 for (int var3 = 1; var3 <= var4; var3++)
24 totalSum += var3;
25 System.out.println("用for循環計算1至50的累加之和為" + totalSum);
26 }
27 }
程式的執行結果可參考圖3-26。
課後習題
一、填空題
1. 結構是以程式的第一行語句為入口點,自上而下執行到程式的最後一行語句。
2.循環語句分為 、 和 三種。
3. 語句設定了循環起始值、循環條件和每輪循環結束後的遞增或遞減表達式。
4. 是一種多選一的條件選擇語句,它是根據條件表達式的運算結果來決定在多個分支的程式區塊中選擇執行其中的一個分支程式區塊。
5. 語句是指“内層”的if語句是另一個“外層”if的子語句,此子語句可以是if語句、else語句或者if-else語句。
6.while語句是根據循環條件表達式結果的 值來決定是否要繼續執行循環體内的程式語句。
7.使用循環語句時,當循環條件永遠都成立時,就會形成 。
8.控制跳轉語句有 、 和 三種。
9. 語句類似于C++語言中的goto語句。
10.使用 語句可以跳離循環。
11.流程控制可分為 語句與 語句。
12.選擇結構使用 語句來控制程式的流程。
13.if語句共分為 、 和 三種。
14. 語句可以從條件表達式的多種結果中選擇程式的執行流程。
15. 語句可以終止程式目前所在的方法,回到調用方法的程式語句。
二、問答與實踐題
1.試簡述結構化程式設計中的基本流程結構。
2.do-while語句和while語句的主要差别是什麼?
3.什麼是嵌套循環?
4.在下面的程式代碼中是否有錯誤的地方?如果有,請指出。
switch ( ) {
case 'r':
System.out.println("紅燈亮:");
break;
case 'g':
System.out.println("綠燈亮:");
break;
default:
System.out.println("沒有此信号燈");
}
5.請問下面的語句中變量flag的值是多少?此處假設number=1000。
flag=(number< 500) ? 0 : 1;
6.請問在switch語句中,default指令扮演的角色是什麼?
7.請設計一個Java程式,它可以判斷所輸入的數值是否為7的倍數,其執行的結果可參考圖3-27中的輸出部分。
8.試着用條件運算符改寫第7題。
9.請設計一個Java程式,讓使用者輸入兩個數字,然後将這兩個數字中較小者的立方值列印輸出,程式的執行過程和輸出結果可參考圖3-28。
10.請設計一個Java程式,求100到200之間的所有奇數之和,程式的執行結果可參考圖3-29中的輸出部分。
11.請設計一個Java程式,讓使用者輸入一個整數number,當所輸入的整數小于1時,就會要求使用者重新輸入,直到獲得一個大于等于1的整數number,然後累加1到number之間的所有奇數,程式的執行過程和結果可參考圖3-30。
12.請設計一個Java程式,讓使用者輸入一個整數number,并計算其階乘值,程式的執行過程和輸出結果可參考圖3-31。