使用者自定函式

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;
}

我們先看 ipow() 的宣告指令:
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) 那裡獲得的兩個參數, 依序分別叫做 baseexp:底數和指數。 然後在 ipow() 的 BODY 裡面, 又宣告了兩個變數 iansipow() 的指令不過就是將 base 自乘 exp 遍, 於是得到了次方答案:ans。 注意 ans = ans * base; 這個語句,這是做連乘的常用伎倆。

注意,如果呼叫 ipow(2, -3) 將不會出現任何錯誤或警告訊息, 而答案是 1。這是錯誤答案。 這是典型的輸入確認 (input validation) 問題。 處理這種問題,有幾種常見方式:

  1. 沒有任何訊息,回應錯誤答案。 我們假設使用者必須自我負責,檢查他使用本函式的方法與目的是正確的。
  2. 回應錯誤答案,使得整個程式能夠繼續執行,但是輸出警告訊息。
  3. 終止執行,輸出錯誤訊息。
只要不引起當機事件,以上的解決方案都可以。 應當視情況需要而採取合適的方案。

讀者應該看得出來,在結構上,ipow()main() 的寫法完全一致。 所以任何 C 程式,主要由函式組成。 任何函式,除了 main() 以外,在呼叫之前必須先宣告。 而函式的定義,基本格式都一樣。這就是 C 在邏輯與設計上的簡明之處。

習題

  1. 如果呼叫 ipow(0.5, 3) 是否正確?結果會怎樣?
  2. 描述以下函式各需要幾個參數?哪些型態的參數?函式值是什麼型態?
    1. int one(float);
    2. double two(double, double);
    3. int three(int, char, char);
    4. char four(char, char, int, double);
  3. a b c 各是一個介於 0 和 9 之間 (含) 的整數, 寫一個程式,自動找出所有符合 a3+b3+c3 = abc 的數字 abc。(abc 的意思就是 100a+10b+c。) 例如 000 就是一個,因為 03+03+03 = 000。 比較有意思的是 13+53+33 = 153。 除了 000 和 153 之外,至少還有 4 組答案。
  4. 能夠寫成兩組不同的正整數平方和的最小整數是
    65 = 12 + 82 = 42 + 72
    能夠寫成兩組不同的正整數立方和的最小整數是
    1729 = 13 + 123 = 103 + 93
    請問能夠寫成兩組不同的正整數四次方和的最小整數是多少? 它可以寫成哪兩組四次方和? 這個習題關係到數學家 Godfrey Hardy (1877--1947) 和 Srinivasa Ramanujan (1887-1920) 之間的一個故事。

[ 前一節 ]‧[ 後一節 ]‧[ 回目錄 ]



注意:此處所有文件均為原著,個別的版權宣告日後會一一公布, 整體版面設計亦尚未完成。但仍請勿抄襲文字與圖片,以免觸犯著作權法。

Created: Mar 31, 2000
Last Revised: Mar 31, 2000
© Copyright 2000 Wei-Chang Shann 單維彰

shann@math.ncu.edu.tw