迴圈敘述 5-1 for 迴圈 5-2 while 迴圈 5-3 do...while 迴圈 5-4 巢狀迴圈 5-5 break 與 continue 5-6 ++ 附加於條件運算式 5-7 迴圈的應用範例 5-8 關鍵字 5-9 問題演練 5-10 程式實作
5-2 迴圈敘述 (loop statement) 的功能就是可以重複執行敘述 迴圈敘述主要有 for while 和 do...while 三種不同語法迴圈敘述 5-1 for 迴圈 我們先來介紹 for 迴圈, 其語法如下 : for( 初值設定 ; 條件運算式 ; 更新運算式 ) 條件運算式為真時, 執行的主體敘述 ; 此迴圈由三個部分所組成, 分別為初值設定 條件運算式及更新運算式, 茲說明如下 : for 迴圈功用 初值設定 條件運算式 更新運算式 設定變數的初值 若為真, 則執行其所對應的敘述 ; 若為假, 則結束迴圈 更新變數值 此三部份是用分號 (;) 隔開, 而不是逗號 (,) 注意,for 敘述小括弧 ( ) 的後面不可加分號 (;), 若執行敘述的部份為單一敘述時, 則大括弧 是可以省略的, 若是複合敘述時, 則不可以省略 但有些人不管單一敘述或是複合敘述, 皆加上大括號, 如範例 5-1a 所示 範例 5-1a 01 /* ex5-1a.c */ 02 03 04 05 06 int num; 07 for(num=0; num<=5; num++) 08
第 5 章迴圈敘述 5-3 09 printf("num is %d\n", num); 10 11 12 13 輸出結果 Num is 0 Num is 1 Num is 2 Num is 3 Num is 4 Num is 5 程式剖析 第 7 行 for 迴圈先將 num 的初值設為 0, 判斷 num 是否小於等於 5, 若是, 則印出 num 值 ( 第 9 行 ) 之後, 再對 num 加 1, 並判斷 num 是否小於等於 5 若是, 則印出 num 值 週而復始, 直到 num 不是小於等於 5, 結束迴圈為止 注意! 迴圈結束時,num 的值是 6 以流程圖表示如下: 以下我們來探討 for 迴圈的一些變形寫法 程式中 num 變數的初值設定, 可以在定義變數就給定之, 此時 for 迴圈內的初值設定敘述就可以省略, 但其後面的 ; 不可省略 如範例 5-1b 第 7 行所示
5-4 範例 5-1b 01 /* ex5-1b.c */ 02 03 04 05 06 int num = 0; /* 設定 num 初值為 0 */ 07 for( ; num<=5; num++) /* 省略初值的設定 */ 08 09 printf("num is %d\n", num); 10 11 12 13 輸出結果 Num is 0 Num is 1 Num is 2 Num is 3 Num is 4 Num is 5 程式剖析 此程式在定義變數時, 也同時設定其初值 其次, 也可以將 for 迴圈的更新運算式移至它處, 如範例 5-1c 第 10 行所示 範例 5-1c 01 /* ex5-1c.c */ 02 03 04 05 06 int num = 0; 07 for( ; num<=5; ) 08 09 printf("num is %d\n", num); 10 num++; 11
第 5 章迴圈敘述 5-5 12 13 14 輸出結果 Num is 0 Num is 1 Num is 2 Num is 3 Num is 4 Num is 5 程式剖析 for 迴圈的更新運算式移至執行的主體敘述內, 但不可以省略前面的分號 輸出結果同上一範例 與上一章的 if...else 敘述一樣, 當 for 迴圈所要執行的主體敘述是複合敘述 ( 指兩個或兩個以上的敘述 ), 必須以左 右大括號括起來 上一範例的 for 迴圈若沒加左 右大括號, 將會形成無窮迴圈, 如範例 5-1d 第 7-9 行所示 範例 5-1d 01 /* ex5-1d.c */ 02 03 04 05 06 int num = 0; 07 for( ; num<=5; ) 08 printf("num is %d\n", num); 09 num++; 10 11 12 輸出結果 這是一無窮迴圈, 請您親身體驗一下
5-6 程式剖析 因為 for 迴圈只對它的下一條敘述有效而已, 所以並沒有執行 num++; 敘述, 導致 num 都是 0, 因此, 形成了無窮迴圈 在 for 迴圈中, 若省略條件運算式, 其結果將會如何? 因為 C 語言認為人性本善, 所以視此條件永遠為真, 導致形成無窮迴圈, 此時必須利用 break 敘述來終止迴圈的執行, 如範例 5-1e 所示 有關 break 敘述的詳細說明, 請參閱 5-5 節 範例 5-1e 01 /* ex5-1e.c */ 02 03 04 05 06 /* 將範例 5-1a 的設定初值 條件判斷式及更新運算式省略 */ 07 int num = 0; 08 for( ; ; ) 09 10 if(num > 5) /* 若 num 大於 5, 則執行 break, 以結束 for 迴圈 */ 11 break; 12 printf("num is %d\n", num); 13 num++; 14 15 16 17 輸出結果 Num is 0 Num is 1 Num is 2 Num is 3 Num is 4 Num is 5
第 5 章迴圈敘述 5-7 程式剖析 在第 8 行 for 迴圈中, 省略了條件判斷式, 表示其條件為真, 所以是一無窮迴圈 此時必須利用第 10 行 if 敘述, 判斷 num 是否大於 5, 若是, 則執行第 11 行 break, 以結束迴圈 上述幾個範例都已給定迴圈所要執行的次數, 此稱為定數迴圈 若沒有給定所要執行次數, 則稱之為不定數迴圈, 這種迴圈由使用者決定是否要繼續執行 範例 5-1f 就是一典型不定數迴圈的寫法 範例 5-1f 01 /* ex5-1f.c */ 02 03 04 05 06 /* 要求使用者不斷輸入數字, 直到數字為負 */ 07 int num = 0; 08 for( ; num>=0; ) 09 10 printf(" 請輸入一整數 ( 當此數為負時, 將結束迴圈 ): "); 11 scanf("%d", &num); 12 13 printf(" 輸入結束!!"); 14 15 16 輸出結果 請輸入一整數 ( 當此數為負時, 將結束迴圈 ): 77 請輸入一整數 ( 當此數為負時, 將結束迴圈 ): 30 請輸入一整數 ( 當此數為負時, 將結束迴圈 ): 25 請輸入一整數 ( 當此數為負時, 將結束迴圈 ): 66 請輸入一整數 ( 當此數為負時, 將結束迴圈 ): 12 請輸入一整數 ( 當此數為負時, 將結束迴圈 ): -20 輸入結束!!
5-8 程式剖析 在第 8 行 for 迴圈中只有條件運算式, 其它都省略了, 當輸入 num 的數值為負時, 將結束迴圈 最後, 我們撰寫一程式, 從 1 加到 100, 每次遞增 1, 如範例 5-1g 所示 範例 5-1g 01 /* ex5-1g.c */ 02 03 04 05 06 int i, total = 0; 07 for(i=1; i<=100; i++) 08 09 printf("1 + 2 + 3 +... + 100 = %d\n", total); 10 11 12 輸出結果 1 + 2 + 3 +... + 100 = 5050 程式剖析 程式中第 7 行的累加動作, 是以遞增的方式 (++) 來處理, 同時 for 迴圈執行的主體敘述是單一敘述, 所以左 右大括號省略了 如下所示 : for(i=1; i<=100; i++) 當然也可以用遞減的方式 (--) 來處理, 如下所示 : for(i=100; i>=1; i--)
第 5 章迴圈敘述 5-9 先將初值設為 100, 而條件運算式為 i>=1, 這樣就可以算出 1 加到 100 的總和 以此類推, 可以很容易的將 1 到 100 的奇數或偶數做累加 如 for(i=2; i<=100; i+=2) 就是執行偶數的累加, 而奇數的累加, 則可以下列的片段程式表示之 for(i=1; i<=100; i+=2) 小蔡老師上完 for 迴圈之後, 請大家計算 1 到 100 的偶數和 1. 以下是小王寫的程式, 請您更正之 /* bugs5-1-1.c */. int i, total = 0; for(i=2; i<=100;) i += 2; printf("1 到 100 的偶數和是 %d\n", total); 2. 以下是小張寫的程式, 請您更正之 /* bugs5-1-2.c */ int i, total; for(i=2; i<=100;)
5-10 i += 2; printf("1 到 100 的偶數和是 %d\n", total); 3. 以下是小美女寫的程式, 請您更正之 /* bugs5-1-3.c */ int i, total=0; for(i=2; i<100;) i += 2; printf("1 到 100 的偶數和是 %d\n", total); 4. 以下是小帥哥寫的程式, 請您更正之 /* bugs5-1-4.c */ int i, total=0; for(i=1; i<100; i+=2) printf("1 到 100 的偶數和是 %d\n", total); 5. 以下是小王子寫的程式, 請您更正之 /* bugs5-1-5.c */
第 5 章迴圈敘述 5-11 int i, total=0; for(i=2; i<100; i+=2); printf("1 到 100 的偶數和是 %d\n", total); 6. 以下是小英寫的程式, 請您更正之 /* bugs5-1-6.c */ int i, total=0; for(i=1; i<100;) i += 2; printf("1 到 100 的偶數和是 %d\n", total); 1. 要求使用者利用 for 迴圈輸入一些數字, 當輸入 -9999 時結束輸入, 接著輸出這些數字的總和與平均 2. 利用 for 迴圈計算 1 + 3 + 5 +... + 99 的和 5-2 while 迴圈 接下來介紹 while 迴圈, 其語法如下 : while( 條件運算式 ) 條件運算式為真時, 執行的主體敘述 ;
5-12 若條件運算式為真, 則重覆執行其所對應的敘述 如範例 5-2a 所示 範例 5-2a 01 /* ex5-2a */ 02 03 04 05 06 int num = 0; 07 while(num >= 0) 08 09 printf(" 請輸入一整數 ( 當此數為負時, 將結束迴圈 ): "); 10 scanf("%d", &num); 11 12 printf(" 結束 "); 13 14 15 輸出結果 請輸入一整數 ( 當此數為負時, 將結束迴圈 ): 55 請輸入一整數 ( 當此數為負時, 將結束迴圈 ): 75 請輸入一整數 ( 當此數為負時, 將結束迴圈 ): 32 請輸入一整數 ( 當此數為負時, 將結束迴圈 ): -11 結束 程式剖析 上例是將 P5-7 範例 5-1f 第 8-12 行的 for 迴圈, 改用第 7-11 行 while 迴圈來執行 您有沒有發現, 其實只是將範例 5-1f 中的 for 改為 while, 並去掉分號而已 以流程圖表示如下 :
5-38 小蔡老師請大家將 1 加至 100, 並輸出 Total = 5050 以下是班上幾位同學所撰寫的程式, 請您 debug 一下 1. /* bugs5-6-1.c*/ int i = 0, total = 0; while(i++ <= 100) printf("total = %d\n", total); 2. /* bugs5-6-2.c*/ int i = 0, total = 0; while(++i < 100) printf("total = %d\n", total); 3. /* bugs5-6-3.c*/ int i = 1, total = 0; while(++i <= 100) printf("1 + 2 + 3 +... + 100 = %d\n", total); printf("i=%d\n", i);
第 5 章迴圈敘述 5-39 4. /* bugs5-6-4.c*/ int i = 1, total = 0; do total +=i; while(i++ <= 100); printf("1 + 2 + 3 +... + 100 = %d\n", total); printf("i=%d\n", i); 1. 試問下列片段程式的輸出結果為何? (a) int i=1,total=0; do while(i++<=100); printf("total = %d\n",total); (b) int i=1,total=0; do while(++i<=100); printf("total = %d\n", total); (c) int i=1, total=0; do while(i++ < 100); printf("total = %d\n", total);
5-40 5-7 迴圈的應用範例 以下將舉三個利用迴圈的應用範例 一為產生前 100 個質數, 二為計算兩數的公因數, 三為九九乘法表 讓我們從產生質數開始 5-7-1 產生前 100 個質數 質數的定義是, 大於 1 的自然數中, 只能被 1 或其本身整除 如 2 3 5 等等是質數, 而 4 6 等等則不是質數 我們將撰寫一程式產生前 100 個質數, 如範例 5-7a 所示 : 範例 5-7a 01 /* ex5-7a.c */ 02 03 04 05 int numofprimes = 100; 06 int numofprimesofperline = 10; 07 int count = 0; 08 int number = 2; 09 10 printf(" 前 100 個質數如下 :\n\n"); 11 while (count < numofprimes) 12 int isprime = 1; 13 14 // 測試是否為質數 15 for (int divisor=2; divisor<=number/2; divisor++) 16 if (number % divisor == 0) 17 isprime = 0; 18 break; 19 20 21 22 // 顯示質數, 並累加其總數 23 if (isprime) 24 count++; 25 if (count % numofprimesofperline == 0) 26 printf("%4d\n", number); 27 else 28 printf("%4d", number); 29 30
5-42 5-7-2 計算兩數公因數 兩整數的公因數假設是 g, 則表示這兩整數都可以被 g 整除 此處要找出其最大的公因數 (greatest common divisor,gcd) 如範例 5-7b 所示 : 範例 5-7b 01 /* ex5-7b.c */ 02 03 04 05 int num1, num2; 06 printf(" 請輸入第一個數字 : "); 07 scanf("%d", &num1); 08 09 printf(" 請輸入第二個數字 : "); 10 scanf("%d", &num2); 11 12 int gcd = 1; 13 int n = 2; 14 while (n <= num1 && n <= num2) 15 if (num1 % n == 0 && num2 % n == 0) 16 gcd = n; 17 18 n++; 19 20 21 printf("%d 與 %d 的最大公因數是 : %d\n", num1, num2, gcd); 22 23 24 25 輸出結果 請輸入第一個數字 : 125 請輸入第二個數字 : 2525 125 與 2525 的最大公因數是 : 25 程式剖析 先假設兩整數的公因數為 1( 第 12 行 ), 然後設定 n 為 2( 第 13 行 ), 測試 num1 與 num2 是否皆可整除 n( 第 15 行 ), 若是, 將 n 指定給 gcd( 第
第 5 章迴圈敘述 5-43 16 行 ), 直到 num1 或 num2 大於 n 為止 ( 第 14 行 ) 如以下片段程式所示 : int gcd = 1; int n = 2; while (n <= num1 && n <= num2) if (num1 % n == 0 && num2 % n == 0) gcd = n; n++; 5-7-3 九九乘法表 九九乘法表應該是小學生就背過的, 以下將以另一種表示方式來表示九九乘法表 如範例 5-7c 所示 : 範例 5-7c 01 /* ex5-7c.c */ 02 03 04 05 int i, j; 06 /* 印出標頭 */ 07 printf(" 9 * 9 乘法表 \n\n"); 08 printf(" "); 09 for (i = 1; i <= 9; i++) 10 printf("%4d", i); 11 12 printf("\n"); 13 14 /* 印出虛線 */ 15 for (int n = 1; n <= 40; n++) 16 printf("-"); 17 printf("\n"); 18 19 /* 印出乘法表的內文 */ 20 for (i = 1; i <= 9; i++) 21 printf("%d ", i); 22 for (j = 1; j <= 9; j++)
5-44 23 printf("%4d", i*j); 24 25 printf("\n"); 26 27 28 29 30 輸出結果 9 * 9 乘法表 1 2 3 4 5 6 7 8 9 ---------------------------------------- 1 1 2 3 4 5 6 7 8 9 2 2 4 6 8 10 12 14 16 18 3 3 6 9 12 15 18 21 24 27 4 4 8 12 16 20 24 28 32 36 5 5 10 15 20 25 30 35 40 45 6 6 12 18 24 30 36 42 48 54 7 7 14 21 28 35 42 49 56 63 8 8 16 24 32 40 48 56 64 72 9 9 18 27 36 45 54 63 72 81 程式剖析 程式分為三個部份, 一為印出標頭 ( 第 6-12 行 ), 二為印出虛線 ( 第 14-17 行 ), 三為印出乘法表的內文 ( 第 19-26 行 ) 為了輸出數字的整齊, 此處利用第 23 行的欄位寬 (%4d) 加以控制 5-8 關鍵字 迴圈敘述 (loop statement) for while do...while 巢狀迴圈 (nested loop) continue
第 5 章迴圈敘述 5-45 5-9 問題演練 1. 試問下一程式的輸出結果為何? int i = 0; while(i < 3 ) switch(i++) case 0: printf("merry"); case 1: printf("merr"); break; case 2: printf("mer"); default: printf("christmas"); 2. 試問下一程式的輸出結果為何? 請以下列資料測試之 1 1 1 2 3 0 1 4 1 3 int i = 0, num = 0, total = 0; printf("input 10 numbers, or type 0 to quit\n"); while(i++ < 10) printf(" %2d:", i); scanf("%d", &num); if(num == 0) break; total = total + num; printf("total = %d\n", total);
5-46 3. 試問下一程式的輸出結果為何? 請以下列資料測試之 1 1 1 2 3 0 1 4 1 3 int i = 0, num = 0, total = 0; printf("input 10 numbers, or type 0 to continue\n"); while(i++ < 10) printf(" %2d:", i); scanf("%d", &num); if(num == 0) continue; total = total + num; printf("total = %d\n", total); 4. 試問以下程式的輸出結果為何? int i, num, total=0; printf(" 累加正整數 \n"); for(i=1; i<=10; i++) printf(" 請輸入 #%d 個整數 : ", i); scanf("%d", &num); if( num >= 0) total += num; else continue; printf("total=%d\n", total);
第 5 章迴圈敘述 5-47 5. 試問下列片段程式的輸出結果為何? (a) int x=0; while(++x < 3) printf("%4d\n", x); (b) int x=100; while(x++ < 103) printf("%4d\n", x); printf("%4d\n", x); (c) char ch='s'; while(ch < 'w') printf("%c", ch); ch++; printf("%c\n", ch); 6. 試問下列程式的輸出結果為何? (a) int i,i1=0, i2=0, i3=0, i4=0, others=0, k; for(k=1; k<=5; k++) printf("please input a number : "); scanf("%d", &i); switch(i) case 1: i1++; break; case 2: i2++; break; case 3: i3++; break; case 4: i4++; break; default: others++; printf("i1=%d, i2=%d, i3=%d, i4=%d, others=%d\n",i1,i2,i3,i4,others); 試問分別輸入 1 2 3 4 5 的結果為何?
5-48 (b) int i,i1=0,i2=0,i3=0,i4=0,others=0, k; for(k=1; k<=5; k++) printf("please input a number:"); scanf("%d", &i); switch(i) case 1: i1++; case 2: i2++; break; case 3: i3++; case 4: i4++; break; default: others++; printf("i1=%d,i2=%d,i3=%d,i4=%d,others=%d\n",i1,i2, i3,i4,others); 試問分別輸入 1 2 3 4 5 的結果為何? 5-10 程式實作 1. 利用迴圈敘述, 印出以下的圖形 (a) * *** ***** ******* ********* ******* ***** *** * (b) * ** *** **** ***** ****** ******* ******** 2. 先要求使用者輸入等差數列的首項與公差, 再輸入項數, 最後利用迴圈敘述計算該數列的和
第 5 章迴圈敘述 5-49 3. 利用迴圈敘述, 印出攝氏溫度與華氏溫度的對照表 從攝氏溫度 -50 到 100, 每間隔 10 印出 ( 提示 : 華氏溫度 =9/5 攝氏溫度 +32.0) 4. 印出費氏數列 (Fibonacci) 的前 15 次 ( 提示 : 某一項是其前兩項之和, 第一項為 1, 第二項為 1) 5. 以 16 進位印出 11 11 之乘法表, 輸出格式如下所示 << Multiplication table 11 * 11 >> 1 2 4 3 6 9 4 8 12 16 5 10 15 20 25 6 12 18 24 30 36 7 14 21 28 35 42 49 8 16 24 32 40 48 56 64 9 18 27 36 45 54 63 72 81 10 20 30 40 50 60 70 80 90 100 11 22 33 44 55 66 77 88 99 110 121