[討論] 給學弟妹關於計程的建議
各位學弟妹大家好!
我是 b97 的學長 Logan。去年我當了半年的「偽‧強者」,在回答
同學的問題時,發現有不少人會犯一些常見的錯誤,所以一直想寫一
篇文章介紹一些 DOs and DONTs,不過因為一些事情,所以拖稿拖到
今天。所以就發到你們的 hw 版,希望可以讓新手少走一些錯路,並
且學習 C 語言的道路可以更為平坦。
Logan 2009.9.18
--
首先我們先談一些態度上的問題:
1. 作業早點寫!
我個人強烈建議大家可以早點寫作業。一般來說,沒有學過程式不過
能力比較強的同學,至少要 3 個小時以上,而對一般人來說,要使用
的時間遠遠超過 3 個小時。所以不要把作業擠到最後一天才寫。寫
作業的人很累,幫助你的真強者也很累!想想看:如果你是真強者,
你希望同時有十幾個同學問你問題嗎?而且當真強者們同時要面對很
多人時,可能根本沒有辦法好好地向你解釋你的 code 為什麼有問題,
只能告訴你哪裡有問題,我認為這對你而言是一種損失。
2. 實際寫 code 勝過空想解法
大部分剛學習 C 語言的同學最缺乏的是寫 code 的經驗,所以作業發
下來,不要空想三天三夜,等到有完整的想法才動工(而且你認為完整
的想法可能根本就是錯的)。多花一點時間 try-and-error,未來你寫
code 的時候就會有一種 sense 大概哪裡會寫錯。
而且,我必需說:你實際上會遇到的難題可能和你想像的不太一樣。這
就好比老師叫你去屠龍,你本來以為飛龍在天,所以花去很多時間在設
計飛行器,不過後來發現最大的問題是龍會噴火,那眼前的 0 就是逃
不掉的命運了!
3. 尋求幫助與幫助同學
原則上我是建議同學盡可能自力完成作業,尤其是 debug 不應該假他
人之手。Debug 也是一種經驗的累積,為什麼強者們看到 code 大概
就知道錯在哪,這就是所謂的「經驗」!我去年在當偽強者的時候,有
些人少一個分號或大括弧的 syntax error 都拿來問我,我就會很不高
興,這種問題我認為大家都應該有能力自行解決,編譯器提供的 error
訊息用來對付這種問題已經很足夠了!除非你認為你的程式是在邏輯面
有錯誤,不然不要輕易地問別人,不然你會喪失很多學習的機會。記住:
在上機考的時候,是沒有人可以問問題或幫你 debug 的!
對於那些能力比較好的同學,我建議你可以多多幫助同學。有時候幫助
同學你會有一些意想不到的收穫。例如我去年修物件導向程式設計的時
候,因為有人常常問我很有挑戰性的問題,所以我知道了很多額外的東
西,這讓我後來寫考卷寫得很順利(我準備考試的時間相較其他同學也
變短了)!因為有時候你對一個東西只是一知半解,但是當你要解釋給
別人聽的時候,你就會被迫全盤地了解一個東西。我想教學相長大概就
是這個意思。
皆下來我們談一些寫 code 的問題:
1. 忘掉複製功能
在大多數的時間複製貼上都不是一個好主意!常見的問題是:有很多
程式碼長得很像,所以就會有人直接複製之前的程式碼,再稍做修改。
這有二個問題:(1) 在修改複製的程式碼的時候常常會漏掉一些東西,
(2) 如果共同的程式碼突然要再加上一些程式碼就會東漏西漏。更重
要的是:除了你自己之外,不會有多少人想要看你的程式碼,因為太
難讀了,想像一下你的程式碼上千行,而且常常用 if 去做例外處理,
我不認為有多少人願意去看!
2. 變數命名
變數的命名基本上不要使用 a, b, c, d 或 r0, r1, r2 之類的變數
名稱。應該盡可能用有意義的名字。試比較:
int a[100][100];
int b, c, d, e;
scanf("%d%d", &b, &c);
for (d = 0; d < b; ++d)
{
for (e = 0; e < c; ++e)
{
scanf("%d", &a[d][e]);
}
}
與下面這一個程式。
int matrix[100][100];
int height, width, r, c;
scanf("%d%d", &height, &width);
for (r = 0; r < height; ++r)
{
for (c = 0; c < width; ++c)
{
scanf("%d", &matrix[r][c]);
}
}
請問哪一個比較好讀?哪一個比較容易了解?
注意,第二個程式的 r 與 c 也不是亂選的,r 是取自 row,c 是
取自 column,分別代表列與欄。這有什麼幫助呢?事實上他可以
幫助我們除錯:例如你看到 r < width 把行拿來和寬度來比,十之
八九就是寫錯了!
另外,我個人建議如果你用到了 global variables,你在命名時,
就應該加上 g_,global variables 帶來的問題太多了,不勝枚舉!
3. 註解
註解是一個沒人愛寫但大家都想讀的東西。有些人主張不要寫註解,
不過理由絕對不是想要偷懶,而是主張一份良好的程式碼應該是望
文生義,看程式碼就像在讀文件很好讀。但是目前,一般同學寫程
式的能力該都還沒有到達那種境界,所以大家最好乖乖地加上註解!
註解的寫作方式因人而異,不過,一些顯而易見的事就不用特別寫
註解:
int i = 10; /* i = 10 */
int j; /* declares j */
這種註解有跟沒有一樣,就不用花時間去寫了!不過如果有時候會
使用一些特別的技巧,或是有個 global variables 會被多個函式
使用,在使用的同時最好好好寫清楚使用的前提,與變數的變化。
/* g_storage, we can use:
* char *ptr = *g_storage_alloc++;
* to allocate a 1024 sized character array quickly. But, however,
* notice that you can only allocate 20 times, otherwise, overflow
* will occur.
*/
char g_storage[20][1024];
char (*g_storage_alloc)[1024] = g_storage;
4. 風格
C 語言的格式很自由,不過幾年下來,已經有一些特定的寫法,一
般來說,養成良好的 coding 習慣是很重要的,良好的 coding 習
慣也有助於減少 syntax error 與幫助 debug。我在這就介紹我自
己習慣的寫法(基本上是 ANSI C Style)。
- 一定要縮排,一層 4 個空白,不使用 tab。
- {} 自己成為一行,縮排和之前的相同
- 每個變數自成一行,並且給定初始值
- if, for, while 之後總是加上 {}
- switch 的 case 之後總是加上 break
- 非必要不使用 goto Label。
int main()
{
int a = 0;
int b = 0;
int sum = 0;
scanf("%d%d", &a, &b);
if (a > b)
{
int tmp = a;
a = b;
b = tmp;
}
while (a < b)
{
sum += a;
++a;
}
printf("%d\n", sum);
return 0;
}
另外,命名時,我建議:
(1) 變數名用小寫(與底線),3-8 個字為宜(global 例外),而且名
稱要可以明確地表達變數的用途,而且多用「名詞」。
(2) 函式名用小寫(與底線),多用「動詞」命名
(3) 巨集用大寫(與底線),名字越長越好,這樣才不會有名稱衝突,
而且可以減少巨集的使用。
(4) Global variables 的名字也是越長越好!理由和巨集相同,你
應該減少 global variables 的使用。
當然我的建議不一定是最好的建議,如果你已經有特定習慣如 K&R C
就繼續用下去,不過如果沒有,你可以試著遵守我的建議!
另外,Dev C++ 的智慧縮排我強烈建議你把他關掉!愚笨者如我從來
看不懂他是怎麼縮排的。
以上大概是我過去半年的經驗談,希望對學弟妹們有所幫助。
--
LoganChien ----- from PTT2 個板 logan -----
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.112.247.159
推
09/18 12:44, , 1F
09/18 12:44, 1F
推
09/18 13:06, , 2F
09/18 13:06, 2F
推
09/18 16:46, , 3F
09/18 16:46, 3F
推
09/18 16:48, , 4F
09/18 16:48, 4F
推
09/18 19:58, , 5F
09/18 19:58, 5F
※ 編輯: LoganChien 來自: 140.112.30.84 (09/18 20:15)
推
09/18 21:41, , 6F
09/18 21:41, 6F
推
09/18 22:49, , 7F
09/18 22:49, 7F
推
09/18 23:40, , 8F
09/18 23:40, 8F
推
09/19 00:49, , 9F
09/19 00:49, 9F
※ 編輯: LoganChien 來自: 140.112.247.159 (09/19 01:53)
※ 編輯: LoganChien 來自: 140.112.247.159 (09/19 02:05)
推
09/19 09:23, , 10F
09/19 09:23, 10F
推
09/19 10:52, , 11F
09/19 10:52, 11F
推
09/19 11:40, , 12F
09/19 11:40, 12F
推
09/19 16:24, , 13F
09/19 16:24, 13F
推
09/19 17:56, , 14F
09/19 17:56, 14F
推
09/22 13:17, , 15F
09/22 13:17, 15F
推
09/28 19:02, , 16F
09/28 19:02, 16F
推
10/07 15:50, , 17F
10/07 15:50, 17F
推
10/07 15:55, , 18F
10/07 15:55, 18F