程式中,經常需要重複的進行某些動作,這時候,就需要用到"迴圈"。 其中一種方法是 for 迴圈,語法如下:

for(變數初始值;迴圈繼續的條件;變數遞增值){
	程式敘述;
}
「變數初始值」、「迴圈繼續的條件」、「變數遞增值」這三個部分,必須用分號隔開。 而迴圈中的程式敘述,會依照變數值的變化,被重複的執行。例如,下面這個程式可以印出 1 到 10:
#include <stdio.h>

int main ()
{
	int i;
	for( i=1 ; i<=10 ; i++ ){
		printf("%d\n", i);
	}
	return 0;
}
會跟著迴圈跳動的變數,若沒有其他特殊用途,則習慣上會命名為 i, j, k 等等。 「i++」的意思,與「i=i+1」相同。 第7行的 printf,會因會變數 i 從 1 跑到 10,而印出 1~10 的數字。

在上面的範例中,當 i = 10 的迴圈結束後, 會再次執行「i++」,讓 i 的值變成 11,不符合繼續的條件,迴圈因而停止。 此時,若在迴圈外部印出 i 的值,就可以發現是 11:

#include <stdio.h>

int main ()
{
	int i;
	for( i=1 ; i<=10 ; i++ ){
		printf("in: %d\n", i);
	}
	printf("out: %d\n", i);
	return 0;
}
如果想要印出不太一樣的數列,可以把迴圈的條件修改一下, 例如若想印出 1, 3, ..., 9,則可改為:
for( i=1 ; i<=10 ; i+=2 )
若想印出 10, 9, ..., 1,則可改為:
for( i=10 ; i>=1 ; i-- )

關於「變數初始值」、「迴圈繼續的條件」、「變數遞增值」這三個部分, 可以有零或多個(用逗號隔開)條件和值,不過分號不能省略。:

#include <stdio.h>

int main ()
{
	int i = 3, j = 5;
	for( ; i<=10 ; i++, j=j+2 ){
		printf("%d %d\n", i, j);
	}
	return 0;
}

我們將前面的範例稍微變更一點點,則可以從 1 加到 100:

#include <stdio.h>

int main()
{
	int sum = 0, i;
	for(i=1;i<=100;i++){
		sum = sum + i;
	}
	printf("1 加到 100 是 %d\n", sum);
	return 0;
}
其中的變數 sum,會依次被加上 1, 2, 3, ..., 100,所以迴圈跑完以後,就可以得到 1 加到 100 的結果。 記得一開始要初始化為 0 (歸零),否則可能得到無法預期的結果 (大部分的編譯器會幫你完成這個動作,但是不能保證)。

如果是計算階乘,千萬記得改變一下初始值。以下示範計算 10 的階乘:

#include <stdio.h>

int main()
{
	int prod = 1, i;
	for( i=1 ; i<=10 ; i++ ){
		prod = prod * i;
	}
	printf("1 乘到 10 是 %d\n", prod);
	return 0;
}

如果要計算比較一般化的等差級數和, 則可簡單的把「變數初始值」、「迴圈繼續的條件」、「變數遞增值」改用變數來給值或判斷:

#include <stdio.h>

int main()
{
	int sum = 0, i, a1 = 3, an = 101, d = 2; /* 也可以改成讓使用者輸入 */
	for( i=a1 ; i<=an ; i+=d ){  /* i += d 與 i = i + d 同意 */
		sum = sum + i;
	}
	printf("首項 %d,末項 %d,公差 %d 的級數和是 %d\n", a1, an, d, sum);
	return 0;
}
當然,也可以用公式計算級數和。尤其是項數多的時候,用公式計算會比迴圈來的有效率。

費氏數列也很適合用迴圈來計算, 以下程式可以計算費氏數列第 n (n ≥ 2)項的值:

#include <stdio.h>

int main()
{
	int prev1 = 1, prev2 = 0, n, fn, i;

	printf("請輸入 n 值:");
	scanf("%d", &n);
	for( i=2 ; i<=n ; i++ ){
		fn = prev1 + prev2;
		prev2 = prev1;
		prev1 = fn;
	}
	printf("費氏數列第 %d 項是 %d\n", n, fn);
	return 0;
}

迴圈跟條件判斷一樣,也可以是巢狀(一層包一層)的。以下程式使用了兩層的 for 迴圈來輸出九九乘法表:

#include <stdio.h>

int main ()
{
	int i, j;

	for( i=1 ; i<=9 ; i++ ){
		for(j=1 ; j<=9 ; j++){
			printf("%d*%d=%2d ", i, j, i*j);
		}
		printf("\n");
	}
	return 0;
}
這支程式的輸出為:
1*1= 1 1*2= 2 1*3= 3 1*4= 4 1*5= 5 1*6= 6 1*7= 7 1*8= 8 1*9= 9
2*1= 2 2*2= 4 2*3= 6 2*4= 8 2*5=10 2*6=12 2*7=14 2*8=16 2*9=18
3*1= 3 3*2= 6 3*3= 9 3*4=12 3*5=15 3*6=18 3*7=21 3*8=24 3*9=27
......(以下略)
Question: 如何改成印直的?

使用巢狀迴圈時,要注意內層迴圈的變數必須跟外層不同。 以下是一個會發生問題的範例,內層和外層同時使用了變數 i。 各位可以在執行之前,先預測一下它的效果:

#include <stdio.h>

int main ()
{
	int i, j;

	for( i=1 ; i<=5 ; i++ ){
		for(i=1 ; i<=3 ; i++){
			printf("%d\n", i);
		}
		printf("\n");
	}
	return 0;
}

另外一種迴圈指令是 while,其語法為:

while(條件式){
	程式敘述;
}
只要條件符合,迴圈就會一直執行。

以下程式也會印出 1 到 10,各位可以體會一下 while 與 for 的語法差異:

#include <stdio.h>

int main ()
{
	int i = 1;
	while(i<=10){
		printf("in: %d\n",i);
		i++;
	}
	printf("out: %d\n",i);
	return 0;
}

利用 while 迴圈,很適合觀察「3n+1問題」的數列。這個問題的規則是這樣的:


所以我們可以利用 while 迴圈,加上 if 進行判斷,寫出下面的程式:
#include <stdio.h>

int main()
{
	int n = 13;
	printf("%d ", n);
	while(n!=1){
		if(n%2==0){
			n /= 2;
		}
		else {
			n = 3*n + 1;
		}
		printf("%d ",n);
	}
	printf("\n");
	return 0;
}

與 while 迴圈很相似的是 do...while 迴圈:

do {
	程式敘述;
} while(條件式);
只要條件符合,就跟 while 迴圈一樣,會一直執行。 但 do...while 迴圈在第一次進來執行的時候是無條件的,意思是至少會執行一次。 同樣用印出 1~10 作為範例:
#include <stdio.h>

int main()
{
	int i=1;

	do{
		printf("in: %d\n",i);
		i++;
	} while(i<=10);
	printf("out: %d\n",i);
	
	return 0;
}

「break;」可以跳出所在的這一層迴圈,「continue;」可以繼續下一層迴圈:

#include <stdio.h>

int main()
{
	int i, j;

	printf("First loop:\n");
	for(i=1;i<=5;i++){
		if(3==i){
			break;
		}
		printf("%d ",i);
	}
	printf("\n");

	printf("Second loop:\n");
	for(i=1;i<=5;i++){
		if(3==i){
			continue;
		}
		printf("%d ",i);
	}
	printf("\n");
	
	printf("Nested loop:\n");
	for(i=1;i<=3;i++){
		for(j=1;j<=5;j++){
			printf("%d %d\n", i, j);
            if(i==2){
                break;
            }
		}
	}
	printf("\n");

	return 0;
}

如果熟悉了迴圈的語法,則可以做出一個簡單的終極密碼遊戲。 先來看看虛擬碼(此例之設計為,密碼有可能是上下界之一):

while(1){  /* 無窮迴圈,猜中才能跳出 */

	提示使用者在上下界之間,輸入一個數字

	if( 輸入數字恰為密碼 ){
		猜中、break;
	}
	else if( 數字<密碼 && 數字≥下界 ){
		下界 ← 數字 + 1;
	}
	else if( 數字>密碼 && 數字≤上界 ){
		上界 ← 數字 - 1;
	}
	else {
		不要來亂;
	}

}
C 語言中,把 0 當做「否」,其餘的非 0 值當做「是」, 所以「while(1)」的寫法,會造成無窮迴圈(迴圈停不下來)。 當然,猜中密碼時遊戲就要結束,所以 break 的條件就是猜中密碼。以下是完整程式碼:
#include <stdio.h>

int main()
{
	int low = 1, high = 100, pwd = 35, guess;
	while(1){
		printf("請在 %d 與 %d 之間猜一數字: ", low, high);
		scanf(" %d", &guess);
		
		if(guess==pwd){
			printf("猜中了\n");
			break;
		}
		else if( guess<pwd && guess>=low ){
			low = guess + 1;
		}
		else if( guess>pwd && guess<=high){
			high = guess - 1;
		}
		else {
			printf("範圍有誤,請重新輸入!\n");
		}
	}
	return 0;
}
範例當中的數字是事先寫死的,當然也可以改用亂數產生。往後會提到如何產生亂數。

高中學過的勘根定理,也可以用迴圈來實做。 勘根定理告訴我們,如果函數 f 是連續的,且 f(a)*f(b) ≤ 0,則 [a, b] 之間至少有一根。 求根的步驟如下:

  1. 找一個區間 [a, b],使 f(a) 和 f(b) 異號
  2. 求 a, b 中點 c,並求 f(c)
  3. 如果 f(a) 和 f(c) 同號,則取 c 為新左界,否則取 c 為新右界
  4. 重複 2 和 3,至夠精確為止

面對未知的函數,要很快的猜出適合的 a 和 b,是比較困難的,所以範例中的 a 和 b 是固定值。 以下程式,會計算 x5 - x - 1 = 0 在 (-0.5, 1.5) 之間的某一根:
#include <stdio.h>
#include <math.h>

int main()
{
	double a = -0.5, b = 1.5, c, fa, fb, fc;

	fa = pow(a, 5.0) - a - 1;
	fb = pow(b, 5.0) - b - 1;

	while( fa * fb < 0 ){
		c = (a+b)/2;
		fc = pow(c, 5.0) - c - 1;

		if( fabs(fc) < 0.000001){ /* 夠小則中止 */
			break;
		}

 		if( fa*fc > 0 ){/* f(a), f(c)同號,以c為新左界 */
			a = c;
		}
		else {
			b = c;
		}
	}
	printf("Root: %.4f\n", c);
	return 0;
}