C++ 入門指南 V2.00 - 單元 9 - 函數




函數 (function) 是一種功能性的模組,可以將程式 (program) 分割成小部分,藉由呼叫函數安排執行順序



定義函數需要指定函數的回傳值型態 (return type) 、函數名稱與小括弧中的參數列 (parameter list) ,後面的大括弧區域為函數工作的程式碼區域,如果有定義回傳值型態,大括弧中至少要有一個 return 陳述 (statement) 。我們舉一例如下


001 int big(int a, int b) {
002    // 判斷兩個參數的大小
003    if (a > b) {
004       // a 大於 b ,回傳 a
005       return a;
006    }
007    else {
008       // a 小於 b ,回傳 b
009       return b;
010    }
011 }

big() 函數回傳兩個參數 (parameter) 中的較大值,我們可以看到回傳值型態為 int ,函數名稱為 big ,參數數量則是依需求自己定義,這裡為兩個 ab ,型態都是 int


這裡, ab 都是屬於 big() 內的區域變數 (local variable) ,也就是效力僅限於 big() 後的大括弧中。

也可以不定義參數,這時參數列可宣告為 void 或留空白。

此例用了兩個 return ,有回傳值的函數至少要有一個 returnreturn 就是函數結束執行,將控制權交還原本呼叫函數的地方, return 後只能接運算式 (expression) 或單一數值。我們將 big() 寫成一個完整範例


001 #include <iostream>
002
003 using namespace std;
004
005 // 宣告 big() 的函數原型
006 int big(int, int);
007
008 // main() 由作業系統呼叫,回傳整數給作業系統
009 int main(void) {
010    cout << endl;
011    // 呼叫 big() 並且印出回傳值
012    cout << big(22, 11) << " is bigger!";
013    cout << endl << endl;
014
015    return 0;
016 }
017
018 // 函數 big() 的實際定義
019 int big(int a, int b) {
020    // 判斷兩個參數的大小
021    if (a > b) {
022       // a 大於 b ,回傳 a
023       return a;
024    }
025    else {
026       // a 小於 b ,回傳 b
027       return b;
028    }
029 }
030
031 /* 檔名: big_demo.cpp
032    作者: Kaiching Chang
033    時間: 2014-5 */

此例在函數定義前先加入函數原型 (function prototype) 的宣告 (declaration) ,宣告亦為一行陳述,因此結尾要加分號


005 // 宣告 big() 的函數原型
006 int big(int, int);

宣告函數原型不需要加入參數的識別字,另外函數也可以不經宣告函數原型直接定義,此時函數定義就得放在 main() 之前。

我們在 main() 中呼叫 big() ,當 big() 執行完會在回到原本呼叫的地方,由於 big() 回傳一個整數,因此這裡就會直接印出 big() 的回傳值


011 // 呼叫 big() 並且印出回傳值
012 cout << big(22, 11) << " is bigger!" << endl;

編譯後執行,結果如下



上例只有在 main() 中呼叫 big() 一次,如果有很多個數字需要比較,自然可以需要的次數呼叫。


函數的一個特點就是重複執行的程式碼用自行定義的識別字 (identifier) 代替,另舉一例如下


001 #include <iostream>
002
003 using namespace std;
004
005 // 宣告函數原型
006 void PrintInt(int);
007 void PrintNewline(void);
008
009 int main(void) {
010    int i = 10; // 設定倒數的初值
011
012    PrintNewline(); // 印出空白一行
013    while (i > 0) {
014       PrintInt(i); // 印出數字
015       i--; // 倒數
016    }
017    PrintNewline(); // 印出空白一行
018
019    return 0;
020 }
021
022 // 印出參數
023 void PrintInt(int a) {
024    cout << a << endl;
025 }
026
027 // 印出新行
028 void PrintNewline(void) {
029    cout << endl;
030 }
031
032 /* 檔名: print_demo.cpp
033    作者: Kaiching Chang
034    時間: 2014-5 */

這是我們之前寫過的倒數計時程式,只是將印出的工作定義給函數,這裡可以看到函數名稱可以使程式有清楚的語意


012 PrintNewline(); // 印出空白一行
013 while (i > 0) {
014    PrintInt(i); // 印出數字
015    i--; // 倒數
016 }
017 PrintNewline(); // 印出空白一行

編譯執行的結果是一樣的



函數是最基本也是最簡單的功能模組,可是 C++ 是物件導向程式語言 (object-oriented programming language) ,物件中除了可以有函數也可以有變數,接下來,我們來看看怎麼樣來設計物件吧!


中英文術語對照


函數 function
程式 program
回傳值型態 return type
參數列 parameter list
陳述 statement
參數 parameter
區域變數 local variable
運算式 expression
函數原型 function prototype
宣告 declaration
識別字 identifier
物件導向程式語言 object-oriented programming language

重點整理


  1. 函數為程式中功能性的模組,程式可藉由呼叫函數排列執行順序。
  2. 定義函數須包括回傳值型態、函數名稱、參數列及函數的程式區塊。
  3. 若不宣告函數原型,就得把函數定義放在 main() 之前。
  4. 函數可以有回傳值,也可以沒有回傳值,有回傳值的函數利用 return 回傳數值。
  5. 函數可以有參數,也可以沒有參數,沒有參數的函數在參數列宣告 void 或留空白。
  6. 函數名稱為自行定義的識別字,可以有比較清楚的語意。
  7. C++ 為物件導向程式語言,物件中除了有物件自己的函數,也可以有物件自己的變數。

問題與討論


  1. 參數跟回傳值在函數中的用途為何?為什麼可以有多個參數,卻只能有一個回傳值?
  2. 在函數中可以改變參數的值嗎?
  3. 什麼是區域變數?為什麼說參數是區域變數?

練習


  1. 寫一個程式 exercise0901.cpp ,裡頭設計一個函數 sum() ,用以計算兩個整數的和。
  2. 承上題,另寫一個程式 exercise0902.cpp ,改成接受使用者輸入的版本。
  3. 寫一個程式 exercise0903.cpp ,裡頭設計一個函數 sum() ,只用一個整數參數 p ,結果回傳 1p 之間所有正整數的和。
  4. 承上題,另寫一個程式 exercise0904.cpp ,改成接受使用者輸入的版本。
  5. 寫一個程式 exercise0905.cpp ,裡頭設計一個函數 factorial() ,用以計算階層值。
  6. 承上題,另寫一個程式 exercise0906.cpp ,改成用遞迴方式設計 factorial()
  7. 承上題,另寫一個程式 exercise0907.cpp ,改成接受使用者輸入的版本。
  8. 寫一個程式 exercise0908.cpp ,裡頭設計一個函數 fibonacci() ,用以計算費氏數列。
  9. 承上題,另寫一個程式 exercise0909.cpp ,改成用遞迴方式設計 fibonacci()
  10. 承上題,另寫一個程式 exercise0910.cpp ,改成接受使用者輸入的版本。

the end

沒有留言: