CHAPTER 迴圈流程控制 本章重點 6.1 迴圈結構 for 6.2 迴圈結構 while 6.3 continue 與 break 敘述 6.4 視窗程式範例 6.5 習題
在程式流程控制當中, 除了上一個單元的判斷流程控制以外, 另一個很重要的部分就是迴圈流程控制了 什麼時候會用到迴圈流程控制呢? 舉最簡單的例子來說, 若我們要用前面常用的 WriteLine 方法, 在螢幕上印出 100 次 Hello, 這時如果要一列一列的寫程式碼, 就會需要 100 列的 WriteLine 程式敘述, 這樣的作法相當耗時且感覺沒有什麼意義, 幸好大部分程式語言都提供了迴圈流程控制結構 (Loop), 可以簡化這種重複動作的撰寫, 讓我們只要用短短幾行的程式碼, 就可顯示 100 次的 Hello 了 迴圈結構使得程式語言更具威力, 且迴圈結構善用了電腦 不厭其煩 的好處, 我們可以藉由迴圈結構輕鬆的重複執行特定的程式敘述以完成某個指定的動作 迴圈就像是一條圓型的道路, 從原點開始走, 走一圈會回到原點, 當回到原點時, 可以選擇要不要繼續走 藉由這種判斷執行次數的控制, 我們可以很容易的進一步設計許多較為複雜的程式 C# 語言提供了 for while do while 等迴圈結構, 接下來將分別介紹之 6.1 迴圈結構 for for 迴圈藉由 起始式 (initial statement) 判斷式(conditional statement) 和 運算式(execution statement), 來控制迴圈的執行與結束 起始式和運算式, 都可以是一行程式敘述 判斷式的用法則與 if 類似,for 迴圈會依據判斷式的是否滿足, 來控制程式執行的次數 for 迴圈語法如下 : for( initial statement; conditional statement; execution statement) program statements;... for 迴圈的流程圖表示法如下 : 6-2
Chapter 6 迴圈流程控制 起始式 True 迴圈內程式敘述 檢查判斷式 是否為真 運算式 False 迴圈之後的敘述 就最簡單的迴圈用途來說,for 迴圈中 起始式 判斷式 和 運 算式 的用法, 通常是如下列表所述的 : 起始式 判斷式 運算式 用來初始化一個或多個變數的值 運用此變數的真假值來判斷是否進入程式區塊 對此變數做一些運算, 例如 : 遞增或遞減運算 參考下面的程式碼 : using System; class Program public static void Main() int i; for(i = 0;i < 10; i++) Console.WriteLine(i); Console.Read(); 這段簡單的程式執行結果, 會在螢幕上依序印出 0~9 的數字 我們 用這個例子來觀察一下這段程式碼的執行流程, 並比照一下 for 迴圈中的 起始式 判斷式 和 運算式 與程式碼的對應關係 6-3
當程式第一次執行至 for 迴圈時, 起始式 i=0 會把變數 i 的值初始化為 0, 接下來判斷式 i<10 的要求是變數 i 要小於 10, 而這時的 i( 值為 0) 會符合要求, 因此會進入迴圈中的程式區塊, 執行 WriteLine 方法印出 i 的值, 最後再執行運算式 i++, 將變數 i 加上 1,i 的值變成 1, 最後回到迴圈的開頭, 此時程式不會再重新執行一次起始式的敘述, 而是會直接比對判斷式, 決定是否再次進入迴圈中的程式區塊, 如此一直執行下去, 直到某次判斷時, 變數 i 不符合判斷式 i<10 為止, 程式就會離開整個迴圈區塊 在 for 迴圈中, 起始式 判斷式和運算式都可以為空白, 但是中間分號仍然要寫出來, 否則會造成語法錯誤 以下為這段程式碼的執行結果 : 我們再參考下面這個計算 1+2+ +10 級數 ( 從 1 加到 10) 的範例程式碼 : using System; class Program public static void Main() int i, sum = 0; for(i = 0;i <= 10; i++) sum += i; Console.WriteLine(" 級數總和為 : " + sum); Console.Read(); 6-4
Chapter 6 迴圈流程控制 注意到這個例子中,for 迴圈的內容沒有加上大括號, 理由和前一單 元 if 判斷結構的原因一樣, 在這類結構中, 當我們只有一行程式敘述時, 大括號通常是可以省略的 這個迴圈的 起始式 判斷式 和 運算式 與前一段程式碼大致相同, 唯一的差異是判斷式 i<=10 的判斷範圍多了一個等號, 而我們在這個例子中使用了另一個變數 sum 來儲存總和, 所以在每次迴圈中, 變數 i 的值都會被加總進變數 sum 當中, 而運算式 i++ 告訴我們變數 i 每次增加 1, 所以這段程式碼相當於從 0+1+... 一直加到 10( 最後一次符合判斷式 ) 為止 最後會在螢幕上列出計算結果, 級數總和為: 55, 如下圖所示 : 程式範例 : 階乘計算 學習重點 : 用 for 迴圈來計算階乘 參考檔案 :6.1-1.cs 一 程式設計目標撰寫一個程式, 可以讓使用者自行輸入 1 個數字, 程式即會計算這個數字的階乘結果, 例如 : 使用者輸入 5, 則程式會計算出 1x2x3x4x5=120, 並印出結果 120 二 程式碼撰寫 01 using System; 02 03 class Program 04 05 public static void Main() 06 6-5
07 Console.Write(" 請輸入欲計算階乘的數字 : "); 08 int number; 09 number = int.parse(console.readline()); 10 11 double sum = 1; 12 for (; number > 1; --number) 13 sum *= number; 14 15 Console.WriteLine(" 階乘結果為 : " + sum); 16 Console.Read(); 17 18 三 程式碼解說 因為階乘的數字是要讓使用者指定的, 所以我們程式一開始一樣先印 出提示輸入的文字並宣告一整數變數 number 用來儲存使用者輸入的階乘 數字, 最後用 ReadLine 方法, 讀進使用者輸入的值並儲存到剛剛宣告的 變數 number 即可 Console.Write(" 請輸入欲計算階乘的數字 : "); int number; number = int.parse(console.readline()); 接著我們用 double 型態宣告變數 sum, 因為階乘的結果常常會很大, 所以在這裡使用 double 型態會比較適合 ( 數字超過支援的範圍依然會溢 位, 但一般情況應該已比整數型態夠用了!) 注意由於後面的迴圈中要 進行連續乘法, 所以 sum 的起始值應該要設為 1 而非前面級數範例的 0, 否則在階乘中會導致階乘結果也變成 0 請注意這裡迴圈中 起始式 判斷式 和 運算式 的設定方式與之前稍有不同, 我們直接使用剛剛 使用者輸入的階乘數遞減來控制迴圈, 故起始式的部份不需要再另外設 定起始值, 運算式 --number 就是遞減的部份, 而迴圈的執行條件 number > 1, 則設定在判斷式中 如此設定,number 變數就會依次遞減直到 1 為止, 而迴圈執行時, 則會每次把當時 number 的值與 sum 相乘, 最後就 可以得到階乘的計算結果了 double sum = 1; for (; number > 1; --number) sum *= number; 6-6
Chapter 6 迴圈流程控制 程式最後只要將儲存在 sum 變數當中的結果, 用 WriteLine 方法印出 來即可 Console.WriteLine(" 階乘結果為 : " + sum); 四 執行結果 6.2 迴圈結構 while while 迴圈的結構與 for 迴圈相似, 但是比 for 迴圈更簡單,while 迴圈並沒有 起始式 與 運算式 的區塊, 只是單純的藉由 判斷式 的真假來決定是否繼續執行迴圈內的程式敘述 while 迴圈的語法如下 : while( conditional statement) program statements;... 流程圖的表示法如下 : 檢查判斷式 是否為真 True 迴圈內程式敘述 False 迴圈之後的敘述 6-7
由於 while 迴圈並沒有起始式與運算式的區塊, 故當我們需要起始式 與運算式的計算時, 就需要在迴圈的前面或裡面加入一些程式敘述 若要將 for 迴圈的觀念用 while 迴圈表示出來, 可以將 for 迴圈的起始式放置在 while 迴圈區塊之前 ; 運算式放置在 while 迴圈區塊結束前的最後一個程式敘述 參考下面的比較範例 : 在本單元一開始介紹 for 迴圈時, 我們用一個印出 0~9 的小程式, 示範了在 for 迴圈當中 起始式 判斷式 和 運算式 的設定方式, 而在這個簡單的例子當中, 起始式是 i=0 判斷式為 i<10 運算式則是 i++ 程式碼如下: int i; for(i = 0;i < 10; i++) Console.WriteLine(i); 而同樣的程式應用, 我們如果用 while 迴圈改寫, 起始式和運算式的位置就得改到適當的位置, 因為 while 迴圈的設定, 只重視判斷迴圈是否繼續的 判斷式, 故我們若有設定起始式或運算式的需求, 就得自己填在適當的位置, 實際上 for 迴圈能做的事,while 迴圈也都能做到, 反之亦然 這個 while 迴圈範例就與上面 for 迴圈的範例之執行結果完全相同 int i; i=0; // 起始式 while(i < 10) Console.WriteLine(i); i++; // 運算式 除了 while 迴圈本身以外,while 迴圈還有一個常見的變形 do while 迴圈 do while 迴圈和 while 迴圈的主要差別在於迴圈內的程式敘述不管如何都會先執行一次, 執行一次後再根據判斷式的成立與否, 決定是否再繼續進入迴圈以執行程式碼 do while 迴圈的使用語法如下 : do program statements;... while(conditional statement); 6-8
Chapter 6 迴圈流程控制 do while 迴圈的流程圖表示法如下 : 迴圈內程式敘述 檢查判斷式是否 為真 True 迴圈內程式敘述 False 迴圈之後的敘述 筆者這邊要再說明一次, 其實 do while 迴圈與 while 迴圈最大的不 同之處, 是在 do while 迴圈內的程式敘述至少會被執行一次, 而接下來的 動作就與 while 迴圈相同了 我們參考下面的程式碼範例 : using System; class Program public static void Main() int i = 0; while(i < 5) Console.WriteLine(" 進入了 while 迴圈 "); i++; do Console.WriteLine(" 進入了 do...while 迴圈 "); while(i < 5); Console.Read(); 在這個例子中,while 迴圈與 do while 的迴圈的判斷式是一模一樣 的 (i < 5), 但讀者可以注意到, 雖然變數 i 的值已在 while 迴圈中超過判 斷式 (i < 5) 要求而跳出了 while 迴圈, 但由於 do while 的特色是迴圈內的 6-9
程式敘述至少會執行一次, 故最後執行程式時, 程式依舊會進入執行 do while 迴圈內的程式敘述一次, 遇到 while 判斷式不符合, 才跳出 do while 迴圈, 故螢幕上還是會印出一次 進入了 do...while 迴圈, 該程式執行結果如下 : 6.3 continue 與 break 敘述 一般迴圈的執行流程都是在迴圈中的程式區塊執行完畢後, 才繼續執行下一輪迴圈 但是在某些特殊狀況, 我們會想要略過程式區塊中某些程式碼, 然後直接跳到下一輪迴圈, 此時我們就可以使用 continue 敘述 continue 敘述通常會配合一個判斷結構, 例如 if 敘述, 也就是當條件符合時, 程式就會跳過接下來的敘述, 執行 continue 的動作, 直接跳到下一輪迴圈程式區塊的起點, 我們參考以下這個範例 using System; class Program public static void Main() Console.WriteLine(" 請輸入一個 1~9 之間的數字 "); int input = int.parse(console.readline()); Console.WriteLine(" 以下是 1~100 中含有 " + input + " 的數字 "); for(int i=1; i<100; i++) if(i%10!= input && i/10!= input) continue; Console.WriteLine(i); Console.Read(); 6-10
6.5 習題 ( )1. 在 for 迴圈當中我們要設定三種式子來控制流程, 請問下列何者 為非? (a) 判斷式 (conditional statement) (b) 迴圈式 (loop statement) (c) 起始式 (initial statement) (d) 運算式 (execution statement) ( )2. 下列哪一個 for 迴圈的設定方式比較合理 ( 假設變數 i 的初始值為 0)? (a)for(;i<10;i++) (c)for(i=5;i>5;) (b)for(int j=5;false;j--) (d) 以上都不合理 ( )3. 請問下列 C# 程式碼執行之後, 變數 i 的值為多少? int i = 0; do i += 2; while(i < 1); (a)0 (c)-1 (b)1 (d)2 ( )4. 請問下列 C# 程式碼執行之後, 變數 number 的值為多少? int number = 0; for(int i = 0;i<10;i++) continue; number += 2; (a)0 (c)20 (b)10 (d)30 5. 執行下列 Visual C# 程式碼片段之後, 螢幕上印出的值為何? int i = 0; while(i < 10) do i ++; while(i > 5 && i < 10); Console.WriteLine(i); 6-18
Chapter 6 迴圈流程控制 程式練習 : 九九乘法表產生程式 學習重點 : 迴圈流程控制以及文字對齊 一 程式設計目標 利用迴圈的概念, 將小時候背的九九乘法表用程式自動計算並列出 來, 接著使用字串型態底下的方法 PadLeft(totalWidth) 來對齊數字, 其中 的 totalwidth 參數為我們指定的總長度, 然後會以空格在左側填補至指定 的總長度 以下用一個簡單的例子來示範 PadLeft 的用法 : string str = "S"; Console.WriteLine(str.PadLeft(1)); Console.WriteLine(str.PadLeft(2)); Console.WriteLine(str.PadLeft(3)); Console.Write(str.PadLeft(1)); Console.Write(str.PadLeft(2)); Console.Write(str.PadLeft(3)); 以上這段程式碼的執行結果會在畫面上印出 : 另外由於 PadLeft 方法只適用於字串, 故讀者可以使用單元 4 談過的 ToString 方法, 將其他型態的變數轉成字串型態, 即可使用 PadLeft 方法 至於 PadRight 方法則是會以空格在右側填補至指定的總長度 6-19
二 執行結果 程式練習 : 質數判斷程式 學習重點 : 本單元內容視窗程式綜合應用 一 程式設計目標建立一個簡單的視窗程式, 可以讓使用者輸入任意正整數, 然後按下判斷按鈕後, 程式會自動判斷使用者輸入的數字是否為一個質數 注意質數定義為除了自己與 1 以外, 不會被其他數字整除的數, 當數字很大時, 我們可以使用迴圈來幫我們快速進行計算判斷 二 執行結果 6-20