撰寫程式應該要有幾個基本原則
不要在半睡眠狀況下撰寫或是偵錯程式
千萬不要在半睡眠狀況下撰寫或是偵錯程式,
那不會有任何的好處,
最多能達成的是把答案湊出來而已。
那寫作業不是就只要寫出能夠作出答案的程式就好了嗎?
其實不只這樣耶,
寫作業最主要是讓你/妳:
-
了解練習上課提及的一些語法,
-
挖掘上課沒有提及的函式庫使用之細節,
-
練習使用程式表達解決問題的方法,
如果你/妳在不清醒的情況下撰寫程式,
你可能無法掌握究竟程式對資料做了些什麼事情,
甚至你沒辦法掌握究竟你對程式做了什麼事情,
當然也就無法得到正確的結果了。
每一個測試的結果或是對程式的更正一定要歸納成結論,
不要常說"好像"會怎樣、"好像"是怎樣的。
請先讓自己模擬成電腦一步一步執行你設計的程式
請先設計資料項目 (適當之型態、足夠之數目) 並指定名稱,
並且由你自己模擬計算機將測試資料運用 + - * / ..算術運算、
&&,||..邏輯運算、
while/for 迴圈、
= 設定、
if/switch 等等敘述一步一步完成所要得到的結果,
記錄所需要的步驟。
千萬不要使用不太了解的敘述
每一個程式敘述你都要詳細知道它對於資料變數的作用,
萬一結果不對時你可以一步一步地追蹤資料的變化,
了解你寫的程式敘述究竟如何處理你的資料,
萬一你寫的程式敘述無法照你想像的去處理資料項目時你再來修改你的程式敘述,
不要隨便把自己寫的敘述改來改去,
只為了試試看而已,
要試試看可以,
一定要先預測你改後的結果,
如果你不知道結果會是怎樣那就不要改了
,沒有意義啊!
就算結果對了也只是猜的而已,
你沒有累積下製作正確程式的經驗,
下一回遇見類似的問題還是不會的。
設計測試程式、設計實驗
對於不太了解的敘述應該撰寫很小的程式來測試它,
看看它對於資料的運作是不是完全如你所想像的,
如果是的話,
好好記住這個範例,
然後再運用於其它程式中。
非必要不用原始碼偵錯器偵錯 (source debugger)
Turbo C 中的原始碼偵錯器 (source debugger)當然很好用,
可是千萬小心不要太倚賴它,
原因至少有三點:
-
很多人因為太倚賴它所以寫程式的時候不夠嚴謹,
-
原始碼偵錯器把程式徹底的拆開來一步一步地執行,
雖然有助你了解任何一步驟對於資料的影響,
可是常常使你無法由大處來看整個程式的邏輯正確性,
-
原始碼偵錯器為了在你的程式執行當中列印出你想看的結果,
它必須增加一些你看不到的機器碼,
改變你原來記憶體的配置,
因此你實際執行的程式不單純是你自己的程式,
還有一大部分是偵錯器的程式,
有很多記憶體使用的錯誤在記憶體配置改變後可能就"隱藏"起來了,
請注意並不是沒有錯誤了,
只是你用同樣的測試資料執行時可能無法觀測到同樣的錯誤了。
一個程式在撰寫時要考慮到逐步的測試,
適當地加入測試點及測試程式碼
(設計時就要想說程式執行到了這裡資料應該是什麼樣子的,
發生錯誤時可以來看看實際資料是不是和設計的時候想的一樣,
不要等到執行時錯了才來抱佛腳,
臨時用原始碼偵錯器來這裡看看那裡看看、
這樣一定會搞成事倍功半的啊!),
可以隨時觀察資料的變化,
適當地加入測試敘述,
例如檢查陣列註標是否超過所宣告的大小、
檢查資料的合理性…
就我個人的觀點原始碼偵錯器最有用的地方有兩個:
-
應該是十行以下的測試程式,
讓你了解編譯器及 CPU 究竟做了什麼事,
-
當你寫 C++ 程式需要暸解類別函式庫如何執行時。
資料流程簡化
程式中變數內數值的設定
(注意並不是說是"變數的定義"哦!
請參考變數最小作用範疇原則)
和其數值的使用必須儘量靠近,
不要在第一列設定 i=10;
到了第八十列才使用到 i 的內容,
例如 x=i*100; 如此你在閱讀此程式時會很痛苦的,
你看到 x=i*100 時要拼命的去想說到底變數 i 裡面是放些什麼呀,
如果萬不得已必須分開那麼遠,
請你避免用無意義的變數名稱例如 i, j, k, a, b, c,
請盡量使用有意義的變數名稱例如 NumberOfCards,
StudentID….去記錄。
模組化製作、測試
每一函式理想的平均長度大概在 60 列以下,
儘量使用函式來分工,
將性質相近的敘述合為一函式,
使用適當且可以辨別意義的函式名稱,
函式每寫完一個,
最好個別測試過一次.....,
不要雖然分了很多函式,
不過都沒有測試過,
一起 debug 時真的很快就抓狂了....
分割區塊的每一對大括號要對齊在同一行
同一區塊內的敘述要對齊在同一行,和外層區塊的敘述要有層次差別
還有兩個大括號要先寫起來再寫中央的程式碼,
函式 , while , for , if ,fopen() fclose(),malloc() free(),.....
都最好是這樣子做,
別要一下就少了三四個右邊的 " } ",
像失蹤人口一樣..... 找都找不到,
尤其是用多層迴圈時,更是要注意......,
也有其它的方法,
例如某些書裡是用加註解的方法:
if (....) {
......
........
} //end of if
不過我覺得習慣養成後應該就不用這麼麻煩了....
(加上還是比較好的習慣,至少閱讀程式的人比較清楚。)
還有,
有一種說法是就算括號內的敘述只有一行,
也不要把括號省略,
因為雖然現在只有一行,
但很難講你等一下會不會再加上個幾行,
如果你又忘了加括號,
那就又孵出一隻很難找的虫虫 (bug) 了!