C 的 math 函式中提供了 pow(), 現在我們要自己寫一個專門做整數次方的函式 ipow()。
在 C 語言中,所有的變數名和函式名,在使用之前一定要先 宣告! 變數在計算之前一定要先 定義。 但是函式不必事先定義,只要讓編譯器在執行第三步驟 (鏈結) 的時候, 能夠找到它的內容就可以了。 所謂函式的內容,就是它該執行的指令。 在鏈結步驟時,函式的指令必需已經被編譯成了機器碼。 使用者定義函式的方法,最簡單就是將它和 main() 函式寫在同一個檔案內。
在以下範例中,我們在 main() 函式開始之前,前置資料結束之後, 先宣告了 ipow() 函式。 然後我們定義 main() 函式,接著再定義 ipow() 函式。 其實,定義函式的順序並不重要,可以先定義 ipow(), 再定義 main()。只要在同一個原始碼檔案內, 編譯器在鏈結步驟就找得到它們。
以下,ipow() 函式讀入兩個整數參數 m, n,輸出 mn。 而 main() 函式則 呼叫 (call) ipow() 來做一些計算。 在這種情況下,我們稱 main() 是 ipow() 的 呼叫者 或是 原函式 (caller)。 每個函式可以呼叫許多個函式,但每個函式只能有一個原函式。
#include <stdio.h> /* 整數的非負整數次方函數 (test-ipow.c) */ int ipow(int, int); main() { int i; for (i=0; i<10; ++i) printf("%8d %8d %8d\n", i, ipow(2,i), ipow(-3,i)); } int ipow(int base, int exp) { int i, ans=1; for (i=0; i<exp; ++i) ans = ans * base; return ans; }
int ipow(int, int);此處宣告了 ipow 是一個函式名,這個函式必需讀入兩個整數型態的資料, 稱做函式參數 (function arguments),而它的函式值 (return value) 也是整數型態。
我們已經知道 printf() 是一個函式。 由此可見,C 語言容許合成函式 (composite functins)。 亦即:呼叫函式的參數裡面可以再呼叫其他函式,就好像我們在 printf() 的參數中呼叫了 ipow()。 其實,從 printf() 的表現,也可以觀察到, 函式的參數個數可以不一定。例如以下呼叫的 printf(), 分別放了 1, 2, 4 個參數。
printf("Hellow World.\n");注意,一對 " " 內是一個參數。 要如何寫出參數個數不固定的函式?先不要急吧,以後再說。
printf("The answer is %d\n", c);
printf("%8d %8d %8d\n", i, ipow(2,i), ipow(-3,i));
最後,我們看 ipow() 的定義。 在寫函式定義的時候,就要宣告了它的參數的名字。 也就是說,從呼叫者 (caller) 那裡獲得的兩個參數, 依序分別叫做 base 和 exp:底數和指數。 然後在 ipow() 的 BODY 裡面, 又宣告了兩個變數 i 和 ans。 ipow() 的指令不過就是將 base 自乘 exp 遍, 於是得到了次方答案:ans。 注意 ans = ans * base; 這個語句,這是做連乘的常用伎倆。
注意,如果呼叫 ipow(2, -3) 將不會出現任何錯誤或警告訊息, 而答案是 1。這是錯誤答案。 這是典型的輸入確認 (input validation) 問題。 處理這種問題,有幾種常見方式:
讀者應該看得出來,在結構上,ipow() 和 main() 的寫法完全一致。 所以任何 C 程式,主要由函式組成。 任何函式,除了 main() 以外,在呼叫之前必須先宣告。 而函式的定義,基本格式都一樣。這就是 C 在邏輯與設計上的簡明之處。
習題
注意:此處所有文件均為原著,個別的版權宣告日後會一一公布, 整體版面設計亦尚未完成。但仍請勿抄襲文字與圖片,以免觸犯著作權法。
Created: Mar 31, 2000
Last Revised: Mar 31, 2000
© Copyright 2000 Wei-Chang Shann 單維彰