日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

Java編程入門(3.3):while與do..while語句

 yy99k 2017-09-14

Java支持簡單語句和復(fù)合語句。比如賦值和子函數(shù)調(diào)用這樣的簡單語句是構(gòu)建程序的基礎(chǔ)模塊。像while循環(huán)和if語句這樣的復(fù)合語句用來將簡單語句組織成復(fù)雜的結(jié)構(gòu)。這種結(jié)構(gòu)被稱作控制結(jié)構(gòu),用來控制語句的執(zhí)行順序。下面的五個章節(jié)會討論Java中的控制結(jié)構(gòu),從本節(jié)的while語句和do…while語句開始介紹。與此同時,我們會給出每種控制結(jié)構(gòu)的示例程序并將其應(yīng)用到前一節(jié)算法設(shè)計例子中。

3.3.1  while循環(huán)

在之前的3.1節(jié)中已經(jīng)介紹了while循環(huán),結(jié)構(gòu)如下:

1
2
while ( boolean-expression )
   statement

while語句是一個代碼塊,由一組語句組合在一起并包含在一對括號中。結(jié)構(gòu)中的statement被稱作循環(huán)體。當(dāng)boolean-expression為true時,會循環(huán)執(zhí)行循環(huán)體中的語句。這個布爾表達(dá)式被稱作循環(huán)條件,執(zhí)行簡單的測試。有幾點需要澄清。在循環(huán)體一次都沒有執(zhí)行前,循環(huán)條件為false時會發(fā)生什么?這種情況下,循環(huán)體永遠(yuǎn)不會執(zhí)行。while循環(huán)的主體可能會任性任意多次,當(dāng)然也可能是0次。當(dāng)執(zhí)行到循環(huán)體中間某條語句時循環(huán)條件由true變?yōu)閒alse時會怎么樣?會馬上結(jié)束循環(huán)嗎?不會,因為計算機(jī)會一直執(zhí)行到循環(huán)結(jié)束為止。只有當(dāng)重新跳轉(zhuǎn)到循環(huán)開始并且測試循環(huán)條件時,循環(huán)才會結(jié)束。

讓我們來看看使用while循環(huán)解決問題的一個典型示例:用戶輸入一組正整數(shù),算出它們的平均值。平均值的算法,是所有整數(shù)的和除以整數(shù)個數(shù)。程序會要求用戶每次輸入一個整數(shù),記錄輸入整數(shù)的個數(shù),然后計算所有已錄入數(shù)字的和。下面是這段程序的偽代碼:

1
2
3
4
5
6
7
8
Let sum = 0     // 保存用戶輸入所有整數(shù)的和
Let count = 0   // 保存用戶輸入的整數(shù)個數(shù)
當(dāng)還有整數(shù)要處理時:
    讀入一個整數(shù)
    加到sum變量
    為count增加計數(shù)
用sum除以count得到平均值
輸出平均值

如何知道還有待輸入的整數(shù)呢?一種典型的解決方法是,讓用戶在所有數(shù)據(jù)錄入完畢時輸入0。這種方法在所有數(shù)據(jù)都是正整數(shù)的情況下有效,這時0不是一個合法的數(shù)值。0本身不作為計算平均數(shù)集合中的數(shù)據(jù),僅僅作為真實數(shù)據(jù)錄入結(jié)束的標(biāo)志。這種方法一些場合下被稱為使用哨兵值。所以,現(xiàn)在while循環(huán)的測試條件變?yōu)椤爱?dāng)輸入的整數(shù)非0”。但是這里有另外一個問題!第一次判斷循環(huán)條件時,循環(huán)體尚未執(zhí)行,這時還沒有讀取任何數(shù)值。也就是說,還沒有“輸入的整數(shù)”。這時判斷輸入整數(shù)是否為0是沒有意義的。因此,我們需要在循環(huán)執(zhí)行做一些處理,把必要的信息準(zhǔn)備好。這里,我們只要在循環(huán)的前面讀取第一個整數(shù)就可以了。下面是修改后的算法:

1
2
3
4
5
6
7
8
9
Let sum = 0
Let count = 0
讀取一個整數(shù)
整數(shù)非0時:
    將整數(shù)加到sum
    增加count計數(shù)
    讀取一個整數(shù)
用sum除以count得到平均值
輸出平均值

請注意,這里我重新調(diào)整了循環(huán)體。由于在循環(huán)開始前就讀取了整數(shù),在循環(huán)一開始就需要處理讀到的整數(shù)。在循環(huán)的最后,計算機(jī)會讀取一個新的整數(shù)。計算機(jī)會跳轉(zhuǎn)到循環(huán)開始的地方,用新讀取的值測試循環(huán)條件。注意:當(dāng)計算機(jī)讀取最后的哨兵值以后,會直接結(jié)束循環(huán)而不對其進(jìn)行處理。既不會累計到sum中,也不會算到count里。這就是算法的工作機(jī)制。哨兵值不作為數(shù)據(jù)的一部分。在最初的算法中,不做循環(huán)前的準(zhǔn)備會累計所有的值包括哨兵值,所以結(jié)果是錯的。(哨兵值為0,因此sum的結(jié)果是正確的,但是count會多算了1個。這種常見的錯誤被稱作“差一錯誤”。循環(huán)中進(jìn)行計數(shù)會比看上去難得多?。?/p>

可以很容易地把算法轉(zhuǎn)換成一個完整的程序。注意,在程序中不能用“average = sum/count;”這樣的語句計算平均值。因為sum和count都是int類型,sum/count的結(jié)果是整數(shù),而平均值應(yīng)該是實數(shù)。我們之前已經(jīng)遇到過了這個問題:把其中一個int值轉(zhuǎn)換為double類型,強(qiáng)制計算機(jī)把商值作為實數(shù)計算。具體的做法,將其中一個變量強(qiáng)制類型轉(zhuǎn)換為double?!?double)sum”將sum值轉(zhuǎn)為實數(shù),因此計算平均數(shù)可以改成“average = ((double)sum) / count;”。還有一種方法,把聲明變量時就聲明為double類型。

程序還存在另一個問題:用戶一開始輸入0時,程序不會再處理其它輸入。這種用例可以來測試循環(huán)結(jié)束時count是否還等于0??雌饋磉@是細(xì)節(jié)問題,但是仔細(xì)的程序員應(yīng)該考慮所有的情況。

下面是程序的完整代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
 * 這個程序會讀取一個用戶輸入的正整數(shù)序列,
 * 輸出所有整數(shù)的平均值。
 * 程序會提示用戶每次輸入一個整數(shù)。
 * 當(dāng)用戶輸入0時表示輸入結(jié)束。
 * (0不會作為數(shù)據(jù)加入平均值計算)
 * 該程序不會檢查用戶輸入是否為正整數(shù),
 * 即使輸入負(fù)數(shù)也會加入計算。
 */
public class ComputeAverage {
   public static void main(String[] args) {
      int inputNumber;   // 用戶輸入
      int sum;           // 正整數(shù)和
      int count;         // 輸入的正整數(shù)個數(shù)
      double average;    // 平均數(shù)
      /* 初始化sum和count變量*/
      sum = 0;
      count = 0;
      /* 讀取并處理用戶輸入 */
      System.out.print('Enter your first positive integer: ');
      inputNumber = TextIO.getlnInt();
      while (inputNumber != 0) {
         sum += inputNumber;   // 把inputNumber累加到sum
         count++;              // count加1
         System.out.print('Enter your next positive integer, or 0 to end: ');
         inputNumber = TextIO.getlnInt();
      }
      /* 打印計算結(jié)果 */
      if (count == 0) {
         System.out.println('You didn't enter any data!');
      }
      else {
         average = ((double)sum) / count;
         System.out.println();
         System.out.println('You entered ' + count + ' positive integers.');
         System.out.printf('Their average is %1.3f.n', average);
      }
   } // end main()
} // end class ComputeAverage

3.3.2  do..while語句

有時候,在循環(huán)結(jié)尾測試循環(huán)條件會比像while循環(huán)那樣開頭判斷更加方便。do..while語句與while循環(huán)非常類似,區(qū)別在于“while”及循環(huán)體被移到了結(jié)尾,在循環(huán)的開頭添加了“do”。do..while語句的結(jié)構(gòu)如下:

1
2
3
do
    statement
while ( boolean-expression );

通常情況下,statement可能是一個代碼塊:

1
2
3
do {
    statements
} while ( boolean-expression );

注意:在do..while的結(jié)尾有一個分號“;”。這個分號也是語句的一部分,與賦值語句或聲明語句結(jié)尾的分號一樣。漏寫分號會造成語法錯誤。(通常,每個Java語句都會以分號或右花括號“}”結(jié)尾)

執(zhí)行do循環(huán)時,計算機(jī)會首先執(zhí)行循環(huán)體中的語句,然后判斷循環(huán)條件。如果循環(huán)條件表達(dá)式為true,計算機(jī)會回到do循環(huán)開頭繼續(xù)執(zhí)行;如果為false,計算機(jī)會終止循環(huán)繼續(xù)執(zhí)行程序的其它部分。由于只有在循環(huán)末尾才會進(jìn)行條件判斷,do循環(huán)至少會執(zhí)行一次循環(huán)體。

例如,下面的偽代碼是一個游戲程序。使用do循環(huán)比起while循環(huán)更有意義,至少能玩一盤游戲。程序的開始版本,循環(huán)判斷條件沒有意義:

1
2
3
4
5
do {
   玩一盤游戲
   詢問是否想要再玩一盤
   讀取反饋
} while ( 用戶的反饋是 yes );

把上面的偽代碼轉(zhuǎn)成Java。開始不去討論游戲的細(xì)節(jié),讓我們定義一個Checkers類,其中包含了一個static成員函數(shù)叫做playGame(),和程序的使用者玩跳棋游戲。偽代碼“玩一盤游戲”被轉(zhuǎn)換為調(diào)用“Checkers.playGame();”。我們需要一個變量存儲用戶的反饋。TextIO類通過一個boolean變量存儲 yes/no 的回復(fù)結(jié)果。“Yes”表示true,“no”表示false。因此算法的代碼會變成:

1
2
3
4
5
6
boolean wantsToContinue;  // True表示用戶想要再玩一盤
do {
   Checkers.playGame();
   System.out.print('Do you want to play again? ');
   wantsToContinue = TextIO.getlnBoolean();
} while (wantsToContinue == true);

當(dāng)boolean變量的值變?yōu)閒alse,表示循環(huán)應(yīng)當(dāng)結(jié)束。在程序的一個地方賦值,在另一個地方作為判斷條件——當(dāng)boolean變量這樣使用時,被稱為標(biāo)志(flag)或標(biāo)志變量(表示信號標(biāo)志)。

順便說一下,程序員通常會鄙視這樣的寫法“while (wantsToContinue == true)”。這種方式過于教條,可以用“while (wantsToContinue)”代表同樣的含義。類似的,還有“flag == false”這樣的寫法,flag是一個boolean變量。“flag == false”與“!flag”完全等價,這里的感嘆號!表示對boolean值進(jìn)行取反操作。所以,可以用“while (!flag)”取代“while (flag == false)”,用“if (!flag)”取代“if (flag == false)”。

盡管do..while語句有時候比while語句更加方便,但是兩種循環(huán)并沒有讓語言更強(qiáng)大。任何可以用do..while循環(huán)解決的問題都可以用while完成,反之亦然。事實上doSomething可以代碼任何一個代碼塊:

1
2
3
do {
    doSomething
} while ( boolean-expression );

與下面的代碼功能一致:

1
2
3
4
doSomething
while ( boolean-expression ) {
    doSomething
}

類似的,

1
2
3
while ( boolean-expression ) {
    doSomething
}

可以替換為:

1
2
3
4
5
if ( boolean-expression ) {
   do {
       doSomething
   } while ( boolean-expression );
}

程序的功能沒有任何變化。

3.3.3  break和continue語句

while循環(huán)與do..while循環(huán)會在程序的開始或結(jié)尾測試循環(huán)條件。有時候,在循環(huán)體中間或者幾個不同的地方測試條件會更加合理。Java提供了在循環(huán)體中跳出循環(huán)的通用方法,叫做break語句,形式如下:

1
break;

當(dāng)計算機(jī)在循環(huán)體重執(zhí)行break語句時,會立刻跳出循環(huán)。接下來會繼續(xù)執(zhí)行循環(huán)后面的語句??紤]下面的示例:

1
2
3
4
5
6
7
8
while (true) {  // 看起來會一直循環(huán)下去!
   System.out.print('Enter a positive number: ');
   N = TextIO.getlnInt();
   if (N > 0)   // 輸入OK,跳出循環(huán)
      break;
   System.out.println('Your answer must be > 0.');
}
// continue here after break 在break執(zhí)行后,從這里開始繼續(xù)執(zhí)行

如果用戶輸入的數(shù)值大于0,會執(zhí)行break語句跳出循環(huán)。否則,計算機(jī)會輸出“Your answer must be > 0.”然后跳轉(zhuǎn)到循環(huán)的開頭繼續(xù)讀取其它用戶輸入的值。

循環(huán)的第一行,“while (true)”可能會有一點奇怪,但確是合法的。while循環(huán)的條件可以是任意boolean類型的表達(dá)式。計算機(jī)會判斷檢查式的值看是true還是false。boolean值“true”也是一個boolean表達(dá)式,值為true。所以,“while (true)”表示無限循環(huán),可以通過break語句終止無限循環(huán)。

break語句會立刻終止包含了該語句的循環(huán)。Java支持循環(huán)嵌套,即一個循環(huán)中包含另一個循環(huán)。如果在嵌套的循環(huán)內(nèi)調(diào)用break語句,只會跳出該層循環(huán),而非跳出外層循環(huán)。還有一種跳轉(zhuǎn)叫做標(biāo)簽中斷(labeled break),可以指定希望跳出的循環(huán)。這種用法并不常見,這里我會快速帶過。標(biāo)簽(Label)的工作方式如下:可以在任何循環(huán)前面加上標(biāo)簽。標(biāo)簽由一個簡單標(biāo)識符帶一個冒號組成。例如,帶label的while循環(huán)看起來像這樣“mainloop: while…”,在循環(huán)內(nèi)部,你可以使用帶標(biāo)簽的跳轉(zhuǎn)語句,比如“break mainloop;”來跳轉(zhuǎn)帶標(biāo)簽的循環(huán)。例如,下面這段代碼檢查兩個字符串,s1和s2,有一個共同的字符。如果找到共同字符,標(biāo)志變量nothingInCommon會置為false,通過標(biāo)簽中斷結(jié)束處理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
boolean nothingInCommon;
nothingInCommon = true// 假設(shè)s1和s2沒有共同字符
int i,j;  // 在s1和s2中用來循環(huán)的迭代變量
i = 0;
bigloop: while (i < s1.length())="">
   j = 0;
   while (j < s2.length())="">
      if (s1.charAt(i) == s2.charAt(j)) { // s1和s2有共同的字符
          nothingInCommon = false;
          break bigloop;  // 跳出所有2層循環(huán)
      }
      j++;  // 繼續(xù)處理s2中的下一個字符
   }
   i++;  // 繼續(xù)處理s1中的下一個字符
}

continue語句與break類似,但是很少使用。continue語句告訴計算機(jī)跳過本次循環(huán)剩余語句的執(zhí)行。然而,與跳出循環(huán)不同,continue會跳轉(zhuǎn)到循環(huán)開始繼續(xù)下一次迭代(包括判斷循環(huán)變量的值是否需要繼續(xù)迭代)。與break語句類似,在嵌套循環(huán)中執(zhí)行continue語句時,會直接轉(zhuǎn)到包含該語句的循環(huán)開始;“標(biāo)簽繼續(xù)(labeled continue)“會轉(zhuǎn)到指定的循環(huán)繼續(xù)執(zhí)行。

break和continue語句可以用在while循環(huán)與do..while循環(huán)中。它們也可以在接下來的章節(jié)中介紹的循環(huán)中使用。在3.6節(jié),我們會看到在switch語句中使用break。break還可以在if語句中使用,前提是if語句嵌套在循環(huán)火種switch語句中。在這種情況下,break并意味著會跳出if語句,而是跳出包含著if語句的循環(huán)或switch語句。在if語句中使用continue也是類似的用法。

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多