我們已經用過很多標準函數庫中的函數,現在來看如何自行自訂函數吧!函數的定義格式如下
函數也可以先做函數原型的宣告,這樣一來,函數定義可以放在函數 main() 的定義之後,不然,沒有先宣告函數原型,函數定義必須放在函數 main() 的定義之前
函數原型的參數列只需要宣告參數的型態,參數的名稱不是必須的,編譯器只會檢查函數原型參數列型態的數量及順序,是否與函數定義相符,若不相同的話,編譯時會發生錯誤。
C 語言的函數規定只能有一個回傳值,參數卻可以有多個,數量上沒有限制,通常我們會依需要適當的規劃參數數量,以及函數該回傳哪個數值。
函數也可以沒有回傳值或參數,沒有回傳值的函數就是進行一些工作,而沒有參數的函數就是不需要參數,例如把印出提示訊息集中在某一個函數中,然後替這個函數取個有意義的名稱,這樣一來,功能就可以藉由函數名稱來判別。
常見的應用如以基本資料型態當作參數及回傳值的型態進行計算,我們拿之前寫過的例子重新規劃函數的模組,先來看看以基本資料型態當參數及回傳值的四則運算器的函數版本吧!
利用函數也可以更改調整變數的值,例如把兩個變數所儲存的數字對調,這需要用到指標當作參數。
我們可以利用陣列當作參數,例如線性搜尋的函數版本,我們在陣列中實作出線性搜尋演算法,而氣泡排序的函數版本,則是在陣列中實作出氣泡排序演算法。
結構可以當參數,例如處理時間的函數,回傳結構 my_tm 或是直接以指向 my_tm 指標當參數,也可以利用動態記憶體配置,回傳指向結構的指標。
變數除了名稱、型態、大小外,還有儲存類型、佔用期間、範圍、連結等特性。宣告時理應加入變數的儲存類型指定詞,否則預設都是自動型的變數。
此外我們須注意變數使用有其範圍規則,通常可用全域或區域來作分別,例如使用全域變數的帳號管理程式,便是將 userID[][] 及 userCODE[][] 兩個二維陣列設定為全域變數,也就是宣告在所有函數之外。
使用區域變數的帳號管理程式則是將 userID[][] 及 userCODE[][] 兩個二維陣列設定在函數 main() 之中,然後以參數的方式傳遞給其餘函數進行修改。
最後,我們討論數學上常用的解決模式,換成 C 程式就是遞迴函數,很多問題可以直覺的解決。然而遞迴有其缺點,容易消耗過多的記憶體空間導致計算費時,利用迭代的方案可以避免這樣的問題。
迭代的解決方式並非顯而易見的,然而遞迴與迭代兩種解決問題的方式可以互換,因此,一旦問題找到了迭代的計算方式,就應該改用迭代的方案。
問題與討論
- 請說明函數的定義方式。
- 函數原型的作用是什麼?為什麼要宣告函數原型?
- C 語言的函數可以有幾個回傳值跟參數?
- 請說明如何用指標當參數及回傳值。
- 請說明如何用陣列當參數及回傳值。
- 請說明如何用結構當參數及回傳值。
- 請說明何謂儲存類型。
- 請比較遞迴及迭代各自的優劣。
沒有留言:
張貼留言