發信人: ax.bbs@bbs.ee.nthu.edu.tw. (athena), 信區: test
標 題: 星星流講座 0020
發信站: ☆清華電機☆ (Tue May 23 11:20:45 1995)
轉信站: star
星星流講座 0020 C 語言教室
第 4 講 之 5 基本的流程控制
Topic: for loop (1)
我們前面討論了 while 和 do-while 的迴圈,為什麼叫迴圈呢?因為在條件
成立的時候會一直執行重複的程式區塊,所以我們叫它迴路或迴圈。許多迴
圈在執行的時候是以執行的次數做為條件的,比方說:
i = 0;
while (i < 10)
{
i++;
/* 迴圈的剩餘部分,但是不會用到 i,i 只是個計次用的變數 */
}
這個時候我們就可以利用 for 迴圈來簡化上面的程式:
for (i = 0; i < 10; i++)
{
/* 迴圈 */
}
for 的用法是這樣的:
for (i = 0; i < 10; i++)
↗ ↑ ↖
計次用變數的 迴圈執行 計次用變數
初始值 條件 每次值的變化
在做進一步的深入探討之前,請你寫作一個九九乘法表的程式,它的輸出和小
學生墊板後面的相同。
for 迴圈最有意思的是計次變數初始值、迴圈執行條件及計次變數的變化都可以不
給,例如:
for ( ; i > 10; i--) /* 前面已給過 i 的初值了,所以迴圈不必再給 */
for ( ; i > 10; ) /* 迴圈中會不規則的變動 i,把 for 當成 while */
/* 來用,這是因為有人不會用 while :) */
for ( ; ; ) /* 永不停止的迴圈 (無窮迴圈 infinite loop) */
以上是最常見的三種情形,其他的情形除非你有特別巧妙的設計,否則該用 while
的時候還是用 while 來做比較清晰易懂。
/* shellsort.c */
#include <stdio.h>
void shellsort (int v[], int n) /* v[]: array to sort */
{ /* n: # elements in array */
int gap, i, j, temp;
for (gap = n / 2; gap > 0; gap /= 2)
{
printf ("shell sort gap %d\n", gap);
for (i = gap; i < n; i++)
{
printf ("shell sort level %d\n", i);
for (j = i - gap; j >= 0 && v[j] > v[j + gap]; j -= gap)
{
temp = v[j];
v[j] = v[j + gap];
v[j + gap] = temp;
}
}
}
}
上面的程式是欣賞用的,我們的目的並不在講 shell sort,而是要和各位談談如何
寫出「乾淨」的程式碼。首先請看到上面程式裡的大括號都是上下對齊的,大括號
內的東西向內縮四格,為什麼要這樣做呢?看看以下錯誤的示範你就知道了:
for (i = 0; i < 10; i++) {
/* .... */
}
第一個不好的習慣是上下的大括號不對齊,像 vi 或 jove 這種編輯器會自動替你
match 括號,提醒你是否有括號不對稱的情形,這當然是很好用的工具。但是如果
我們現在用的是像 PE2 這種不會替你對括號的編輯器,而你自己又不把括號對齊
的話,那麼可以預見的是你常常會得到這個錯誤訊息:
parse error at end of input
第二個不好的習慣是程式碼不縮排,例如:
for(gap=n/2;gap>0;gap/=2)
{
printf("shell sort gap %d\n",gap);
for(i=gap;i<n;i++)
{
printf("shell sort level %d\n",i);
for(j=i-gap;j>=0 && v[j]>v[j+gap];j-=gap)
{
temp=v[j];
v[j]=v[j+gap];
v[j+gap]=temp;
}
}
}
所有的碼擠成一堆,一點層次感也沒有,層次感除了美觀之外,它其實有重要的功
用,在像上面的多重迴圈裡我們要很用力的看才能看出它在幹什麼,而不能如前面
的 shellsort.c 那麼一目了然。程式碼易讀的最大好處是縮短除錯的時間,減少
維護程式的成本。
至於運算元 (operator) 前後的空白,例如 i = j + 4; 等等,筆者個人是模仿
Quick BASIC 的風格,如果是單元運算元 (unitary operator) 就不加空白,如:
i++; ,二元運算元 (binary operator) 則前後加空白,如:i = j;。左小括號 (
前面一定加空白,逗號 , 後面也一定加空白。在 C 語言聖經 K&R 的版本裡他們分
的更細,函數的左小括號前頭沒有空白,非函數的左小括號前頭有空白,例如:
printf("Hello, world!\n"); /* 函數 */
for (i = 1; i < 10; i++)
筆者因為很喜歡按大大的 space 鍵聽它叩叩的聲音,所以左括號前一律加空白 :)
初學者常常因為懶惰而吃掉不少空白,套句補習班常用的廣告詞:今日不做,明日
後悔。別因一時的懶惰種下明日的苦果,什麼苦果?等你程式寫到上千行你就知道了。