目錄表

國立屏東大學 資訊工程學系 物件導向程式設計

8. Loops


Chicago的捷運系統自1892年起開始營運(不過它還不是世界上最早的捷運系統,London的捷運自1863年起就開始營運了),目前共有八條路線,大部份路線為高架或地面路線。Chicago的downtown稱為路普區,這是因為當捷運進入市區後,會以環狀的方式繞行一圈才離開,請見figure 1。路普的英文是Loop,意思就是繞圈。

 資料來源:http://chicago.straightdope.comFig. 1

在Java語言中,也有所謂的Loop,我們稱之為迴圈,用以重複地執行特定的程式碼。請參考figure 2,一個迴圈通常使用一組大括號將一些程式敘述包裹起來,並且反複地執行,直到特定的條件成立或不成立為止。判斷是否繼續執行的地方,可以在迴圈區塊的開頭處或是結束處,視所使用的loop敘述而定。本章將Java語言所支援的loop敘述分別加以介紹。

典型的loop執行動線Fig. 2

8.1 while迴圈

while敘述的語法如下:

while (controlling_expression) statements

while敘述先判斷controlling_expression的值,若為true則一直執行後續的statement,直到controlling_expression的值為false時才結束。

<note important>

while迴圈可包含一行或一行以上的敘述

</note>

所以,while迴圈中的敘述可能會被執行0次到無限多次,視其controlling_expression的值而定。以下是一些例子:

// 計算1+2+3+...+10的結果
int i=1, sum=0;
 
//執行十次
while(i<=10)
{
   sum+=i;
   i++;
}
System.out.printf("sum of 1 to 10 is %d.\n", sum);


// 印出介於1到100間可以被7整除的數字
int i=1;
 
while(i<=100)
{
   if(i%7==0)
      System.out.printf("%d ", i);
   i++;
}

// 反覆執行直到使用者輸入0為止
boolean quit=false;
int c;
 
Scanner sc = new Scanner(System.in);
 
while(!quit)
{
   // do something
   ...
   printf("continue (0 for quit)?");
   c=sc.nextInt();
   if(c==0)
      quit=true;
}
sc.close();

// 反覆執行直到特定條件成立為止
 
while(true)
{
   // do something
   ...
   if(expression)
      break;      //直到特定條件成立時,使用break跳離
}

8.1.1 無窮迴圈(infinite loop)

有時,不小心設定while的controlling_expression,其結果會導致程式永遠無法結束,因為不論在各種情況下,controlling_expression永遠為true。我們將這種情況稱為無窮迴圈(infinite loop),例如:

int i=0;
while(i==100)      //這裡將i==100寫成了i=100
{
   // do something
   ...
//   i++;          //除錯時,不小心把這一行註解掉了
}

8.2 do迴圈

do敘述的語法如下:

do statements while (controlling_expression);

do迴圈與while迴圈類似,不同之處在於其判斷是否繼續之處位於exiting point。do敘述執行statements,然後才判斷接在while後面的controlling_expression的值,若為true則繼續回到do迴圈開頭處再次執行;若controlling_expression的值為false時,do迴圈才結束。相較於while迴圈,do迴圈內含的statements至少會被執行一次。以下是一些例子:

i=10;
 
do
{
     System.out.printf("%d\n", i);
     i--; 
} while (i>0);

i=10;
 
do
{
     System.out.printf("%d\n", i);
} while (--i>0);

i=10;
 
do
{
     System.out.printf("%d\n", i);
} while (i-- > 0 );


8.3 for迴圈

for敘述的語法如下:

for ( expression1; expression2; expression3 ) statements

其中expression1、expression2與expression3,分別是用以定義迴圈的初始條件、中止條件與更新(update)的處理,說明如下:

我們可以用while的語法,來將for的語法改寫如下:

expression1;
while ( expression2)
{
   statements
   expression3;
}

以下是一些例子:

int i,sum=0;
 
for(i=1;i<=10;i++)
{
   sum+=i;
}
System.out.printf("sum=%d\n", sum);

在expression1與expression3中也可以用','同時指定多個運算式,例如:

int i,sum;
 
for(i=1, sum=0;i<=10;i++)
{
   sum+=i;
}
System.out.printf("sum=%d\n", sum);

expression1-3也可以被省略,例如:

int i=0;
 
for( ; i<10;i++)
   System.out.printf("i=%d.\n", i);

8.4 巢狀迴圈(nested loop)

一個迴圈內如含有另一個迴圈,則稱之為,巢狀迴圈(nested loop)。每一層的迴圈可以是for、while或do其中一個,以下我們僅以for迴圈為例,其它的組合您可以自行學習。

//印出1!+2!+3! + ... + 10!
int i,j,temp,sum=0;
 
for(i=1;i<=10;i++)
{
   temp=1;
 
   for(j=1; j<=i; j++)
   {
      temp*=j;
   }
 
   sum += temp;
}
 
System.out.printf("sum=%d.\n", sum);

請思考以下問題:

8.5 從迴圈中跳離

除了使用迴圈的controlling_expression來控制迴圈的執行外,我們還可以使用break、continue與goto敘述來改變程式的動線,使其可以跳離迴圈所屬的程式區塊。

8.5.1 break敘述

break在迴圈中一旦被執行,則在此次迴圈執行過程中剩下還未執行的敘述就會被跳過不執行,並且結束迴圈的執行。當迴圈的中止條件不在開頭或結尾時,break敘述就便得很有用處,例如:

//反覆要求使用者輸入一個整數,並且將其累加,直到使用者輸入0為止
 
int n, sum=0;
Scanner sc = new Scanner(System.in);
for(;;)
{
   System.out.printf("Please input a number (0 for quit):");
   n=sc.nextInt();
   if(n==0)
      break;
   sum+=n;
}
System.out.printf("sum=%d.\n", sum);
sc.close();

8.5.2 continue敘述

continue則和break相反,它並不會結束迴圈的執行,而是省略當次執行時未完成的程式碼,直接執行迴圈的下一回合。

//反覆要求使用者輸入一個整數,並且將其累加,直到使用者輸入0為止,但輸入值若為負數則加以忽略
 
int n, sum=0;
Scanner sc = new Scanner(System.in);
for(;;)
{
   printf("Please input a number (0 for quit):");
   n=sc.nextInt();
   if(n==0)
      break;
   if(n<0)
      continue;
   sum+=n;
   // continue敘述使程式碼跳到了這裡
}
System.out.printf("sum=%d.\n", sum);
sc.close();