3.8.2循環語句
3.8.2.1while語句
最近這些年買彩票隻能去投注站買,早些年,筆者經常是在網上買。在網上買有個功能:追号。就是假如你想一直買同一組号碼,直到中大獎為止。你可以設定一個條件,比如中了頭獎就不繼續買了,如果沒有中頭獎,下一期繼續買同樣的号碼。對于這樣的功能,在程式中可以采用while循環來實作:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5CN4YTZ1EDZxQ2YiJmZlRzYjNjNxUmZkN2M3QmMwITOy8CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
代碼如下:
while(n<5000000) { System.out.println("下一期繼續買同一組号碼"); }
但是事實上,我們先要買第一期,然後才能判斷是否中頭獎,循環才能繼續:
代碼如下:
do { System.out.println("買一組号碼");} while (n < 5000000);
下面我們再用一個示例來解決我們兒子最近學奧數的一個數學問題,計算1+2+3+…+100;
int sum = 0;// 最終結果,初始為0int add = 1;// 加數,初始為1while (add <= 100) { sum = sum + add; add++;// 加完後,自增1}System.out.println(sum);//最終結果是5050
通過上面執行個體我們知道,當while的條件為真,則執行循環語句。如果這個條件一直為真的話,程式就會進入一個死循環了。是以在實際程式編寫的時候,一定要保證這個條件随着程式的運作,會在某一個時刻變為假,避免程式進入死循環。比如上面這個例子變量add會自增,是以一定大于100。
3.8.2.2for語句
對于上面這個數學問題,我們可以看出來,它的循環次數是固定的,對于這種循環問題,Java還有一種更加簡潔的語句來實作,就是for循環。代碼可以寫成這樣:
int sum = 0;// 最終結果,初始為0for (int add = 1; add <= 100; add++) { sum += add;}System.out.println(sum);// 最終結果是5050
我們可以看到,代碼的第2行,把加數add的初始化、循環條件和add的自增都放到一行了,顯得更加簡潔。它的通用結構如下:
for(表達式1 ; 表達式2 ; 表達式3)
- 表達式1:一般用來初始化循環疊代計數器
- 表達式2:必須是一個結果為boolean的表達式,一般用作循環條件
- 表達式3:一般用來疊代循環計數器
其實對于for循環中括号内,是分成3個部分,每個部分之間用分号(;)隔開。Java允許這3個部分放置任何表達式,并且都是可以省略不寫的。示意圖如下:
另外,對于在表達式1中聲明的變量,它的作用域是整個for循環的循環體。對于在循環語句中定義的變量,作用域隻能在循環體{}内。
有的時候,在一個for循環中,會有多個計數器,例如前面追号買彩票的例子,可以設定追号10期,但是有的時候你的賬戶餘額不足了,彩票站不會給你墊錢追号的,代碼可以寫成這樣:
for (int balance = 10, count = 1; balance >= 2 && count <= 10; count++, balance -= 2) { System.out.println("餘額還剩" + balance + "元,購買第" + count + "期彩票");}
運作結果:
餘額還剩10元,購買第1期彩票餘額還剩8元,購買第2期彩票餘額還剩6元,購買第3期彩票餘額還剩4元,購買第4期彩票餘額還剩2元,購買第5期彩票
我們可以看到:
- 表達式1可以同時定義多個同類型的變量(balance和count)
- 表達式2循環條件是餘額大于等于2(夠一張彩票錢)并且追号期數小于等于10(我們設定的期數)
- 表達式3可以同時對balance和count進行更新
雖然Java的文法規則對for循環的表達式1、表達式2、表達式3的限制非常少,但是筆者不建議編寫晦澀難懂的語句,盡量保證代碼的可讀性。
3.8.2.3break
在上面這個例子中,代碼其實寫的就有點晦澀,不易閱讀。對于餘額不足的情況,其實可以認為是中止循環的一個條件。我們可以用break來中止循環,代碼可以改寫:
int balance = 10;for (int count = 1; count <= 10; count++) { System.out.println("餘額還剩" + balance + "元,購買第" + count + "期彩票"); balance -= 2; // 當餘額不足2元的時候,中止循環 if (balance < 2) { break; }}
在while中同樣可以使用break,我們将上面代碼改寫成while版本:
int balance = 10;int count = 1;while (count <= 10) { System.out.println("餘額還剩" + balance + "元,購買第" + count + "期彩票"); count++; balance -= 2; // 當餘額不足2元的時候,中止循環 if (balance < 2) { break; }}
這2段代碼的運作結果都是:
餘額還剩10元,購買第1期彩票餘額還剩8元,購買第2期彩票餘額還剩6元,購買第3期彩票餘額還剩4元,購買第4期彩票餘額還剩2元,購買第5期彩票
break關鍵字,隻能中止目前循環,當有多個循環嵌套使用的時候,有時候想要直接中止最外層循環,對于這種需求,在C++中是使用goto關鍵字來實作的。我們在學習關鍵字的時候,發現Java将goto作為保留字了,但是卻沒有使用它,而是用了另外一種方法來實作。叫做帶标簽的break語句。
首先我們得想一個多層嵌套的例子,正當我冥思苦想的時候,突然發我兒子床頭的一張乘法口訣表:
假如我們用程式列印這張表,可以用到2層嵌套的循環語句。第一層循環列印每一行的所有算式,然後我們把列印每一行的功能也用一個循環來實作即第二層循環。代碼如下:
// row是行号,一共需要列印9行for (int row = 1; row <= 9; row++) { // column是列号,對于第row行,一共需要列印row列 for (int column = 1; column <= row; column++) { System.out.print(column + "×" + row + "=" + column * row + " "); } System.out.println();// 列印完一行,需要換行}
運作結果如下:
1×1=11×2=2 2×2=41×3=3 2×3=6 3×3=91×4=4 2×4=8 3×4=12 4×4=161×5=5 2×5=10 3×5=15 4×5=20 5×5=251×6=6 2×6=12 3×6=18 4×6=24 5×6=30 6×6=361×7=7 2×7=14 3×7=21 4×7=28 5×7=35 6×7=42 7×7=491×8=8 2×8=16 3×8=24 4×8=32 5×8=40 6×8=48 7×8=56 8×8=641×9=9 2×9=18 3×9=27 4×9=36 5×9=45 6×9=54 7×9=63 8×9=72 9×9=81
Perfect!完美的列印出來了。假如我們想在列印到第8行第5列的時候,不想列印了,代碼改成下面這樣:
// row是行号,一共需要列印9行for (int row = 1; row <= 9; row++) { // column是列号,對于第row行,一共需要列印row列 for (int column = 1; column <= row; column++) { System.out.print(column + "×" + row + "=" + column * row + " "); if (row == 8 && column == 5) { break; } } System.out.println();// 列印完一行,需要換行}
但是這樣的結果如下:
1×1=11×2=2 2×2=41×3=3 2×3=6 3×3=91×4=4 2×4=8 3×4=12 4×4=161×5=5 2×5=10 3×5=15 4×5=20 5×5=251×6=6 2×6=12 3×6=18 4×6=24 5×6=30 6×6=361×7=7 2×7=14 3×7=21 4×7=28 5×7=35 6×7=42 7×7=491×8=8 2×8=16 3×8=24 4×8=32 5×8=401×9=9 2×9=18 3×9=27 4×9=36 5×9=45 6×9=54 7×9=63 8×9=72 9×9=81
雖然第8行第5列之後的沒有列印,但是第9行又列印出來了。我們再改成帶标簽的break。
運作結果:
1×1=11×2=2 2×2=41×3=3 2×3=6 3×3=91×4=4 2×4=8 3×4=12 4×4=161×5=5 2×5=10 3×5=15 4×5=20 5×5=251×6=6 2×6=12 3×6=18 4×6=24 5×6=30 6×6=361×7=7 2×7=14 3×7=21 4×7=28 5×7=35 6×7=42 7×7=491×8=8 2×8=16 3×8=24 4×8=32 5×8=40
這一次結果正确。我們在第1行添加一個标簽“print_row”,然後在第7行中止該标簽。這樣做相當于跳轉到标簽“print_row”标記的代碼塊的末尾即第11行。需要注意的是,标簽後面需要緊跟一個冒号(:)。
3.8.2.4continue
在上面列印乘法口訣表的例子,假如我們不想列印第4行和第4列,想想有啥辦法嗎?我們可以想到,當列印到第4行的時候,直接換一行去列印第5行。當列印到第4列的時候,也跳過,然後去列印第5列。對于這種需求,我們可以用到continue語句。continue的作用就是跳過目前循環體中剩餘的部分,回到目前循環的首部。代碼如下:
for (int row = 1; row <= 9; row++) { /*第4行,列印換行,然後繼續列印下一行*/ if (row == 4) { System.out.println(); continue; } for (int column = 1; column <= row; column++) { /*第4列,打6個空格,然後繼續列印下一列*/ if (column == 4) { System.out.print(" "); continue; } System.out.print(column + "×" + row + "=" + column * row + " "); } System.out.println(); }
運作結果如下:
1×1=11×2=2 2×2=41×3=3 2×3=6 3×3=9 1×5=5 2×5=10 3×5=15 5×5=251×6=6 2×6=12 3×6=18 5×6=30 6×6=361×7=7 2×7=14 3×7=21 5×7=35 6×7=42 7×7=491×8=8 2×8=16 3×8=24 5×8=40 6×8=48 7×8=56 8×8=641×9=9 2×9=18 3×9=27 5×9=45 6×9=54 7×9=63 8×9=72 9×9=81
我們看到,結果第4行和第4列都空出來了。需要注意的是,continue隻是跳過目前循環體的剩餘部分,如果是for循環,表達式3部分還是會執行的。
continue語句也可以帶标簽,作用是跳到與标簽比對的循環首部(如果是for循環,則是表達式3)。我們看代碼和結果:
print_row:for (int row = 1; row <= 9; row++) { for (int column = 1; column <= row; column++) { /*第4列,則直接列印下一行*/ if (column == 4) { System.out.println(); continue print_row; } System.out.print(column + "×" + row + "=" + column * row + " "); } System.out.println();}
結果:
1×1=11×2=2 2×2=41×3=3 2×3=6 3×3=91×4=4 2×4=8 3×4=121×5=5 2×5=10 3×5=151×6=6 2×6=12 3×6=181×7=7 2×7=14 3×7=211×8=8 2×8=16 3×8=241×9=9 2×9=18 3×9=27