【不是惡夢的開始,而是再度的精進。 自訂函數】

我們在程式中需要重複執行某一組指令功能時,迴圈就是最好的選擇。那麼將這一組能完成特定工作的指令,模組化成一個完整的函數,便可以隨時呼叫引用,這就是自訂函數了。


在這之前,其實我們不知不覺中已經使用過無數次的函數了,那就是主程式的入口

int main(int argc, char** argv)
{
  .....
  .....
  ........
  cout << "\n美麗的新世界就從這裡開始\n";

 return 0;
}


就像是使用變數一樣,想要使用自訂函數時,也必須要宣告函數原型,其中包括傳回型態、傳入函數的引數型態,宣告格式如下:


傳回值型態   函數名稱(引數型態1, 引數型態2, ....);

  int         add    (int, int, .....);  // 回傳值為整數型態,引數為整數型態

  void        symbol (int, char, ....);  // 無回傳值,引數有整數型態與字元型態

  void        symbol (void);             //  無回傳值,無引數


自訂函數名稱的命名和變數的命名規則相同,都不能使用到C++的關鍵字,也都建議以有意義的名稱為函數命名。


一般來說,main()函數放在程式的一開始處,自訂函數在main()函數後面,就需要宣告自訂函數原型。
如果把自訂函數放在main()函數的前面,則不需要宣告自訂還數的原型。

 

自訂函數的寫法和main()函數的寫法類似,格式如下:

傳回值型態   函數名稱(引數型態1, 引數型態2, ....)
{
  變數宣告;
  敘述主體;
  return 運算式;
}


呼叫函數的方式有兩種,如果有傳回值時,則指定某個變數來接收,格式如下:

變數 = 函數名稱(引數);

 

例:

#include <iostream>

using namespace std;

int add(int  initial);


int main(int argc, char** argv)
{
    int ai = 5;
    cout << "main() 呼叫 add()前 ai =  " << ai << "\n\n";
    ai = add(ai);    // 用變數來接收函數的回傳值
    cout << "main() 呼叫 add()後 ai =  " << ai ;

    return 0;

 }

 int add(int bi)
 {
     int  resulti = 0;
     resulti = bi + 8;

     return  resulti;
 }


執行結果:

main() 呼叫 add()前 ai =  5

main() 呼叫 add()後 ai =  13

 

 

函數如果沒有回傳值時,則直接呼叫函數,格式如下:

函數名稱(引數);


例:


#include <iostream>

using namespace std;

void add(int  initial);

int main(int argc, char** argv)
{
    int ai = 5;
    cout << "main() 呼叫 add()前 ai =  " << ai << "\n";
    add(ai);
    cout << "main() 呼叫 add()後 ai =  " << ai ;
    
    return 0;
        
 } 
 
 void add(int ai)
 {
     ai += 8;
     cout << "add()  ai = " << ai << "\n";
     return;
 }
 
 

 
執行結果:

main() 呼叫 add()前 ai =  5
add()  ai = 13
main() 呼叫 add()後 ai =  5

 

上例示範 add(ai); 呼叫函數,另外聊一下區域變數。


在add()函數的大括號{}內並沒有宣告變數 ai,但卻可以直接作加法運算 ai += 8;,因為變數ai在函數的參數就已經宣告了 add(int ai),所以無需另外再宣告一次。


在main()函數和add()函數內都有變數ai,這兩個變數ai並不是同一個變數,是兩個各自獨立的變數。只要是被大括號{}包含住的變數就是區域變數,所以在呼叫add()函數的時候,add()函數內的變數ai的值被改變了,但呼叫完add()函數後,再一次的顯示main()函數內的變數ai,仍然是5,因為add()函數只能改變自己函數內的區域變數ai的值,或更改全域變數的值,並不能該改其他函數main()內的區域變數值。


修改一下程式碼,來看看全域變數


#include <iostream>

using namespace std;

void add(int  initial);

int ai = 0;   // 全域變數

int main(int argc, char** argv)
{
    ai = 5;
    cout << "main() 呼叫 add()前 ai =  " << ai << "\n";
    add(ai);
    cout << "main() 呼叫 add()後 ai =  " << ai ;
    
    return 0;
        
 } 
 
 void add(int bi)
 {
     ai = bi + 8;
     cout << "add()  ai = " << ai << "\n";
        return;
 }
 
 

 
執行結果:

main() 呼叫 add()前 ai =  5
add()  ai = 13
main() 呼叫 add()後 ai =  13


這次我們把 int ai = 5; 宣告在函數外面,只要不被函數的大括號{}包含住,這就是全域變數了。
全域變數的值是每個函數都可以變動更改的,所以main()函數在呼叫add()函數之前先把5設定給變數ai,這樣就改變了變數ai的值了,而呼叫了add()函數後,又把變數ai再更改一次它的值,因此第二次在main()函數又輸出一次變數ai的值時,因為變數ai已經被add()函數更改變數值,所以就和第一次輸出不一樣的值了。


另外我們調整一下全域變數的位置,再編譯一次


#include <iostream>

using namespace std;

void add(int  initial);

//int ai = 0;

int main(int argc, char** argv)
{
        ai = 5;  // 'ai' was not declared in this scope
    cout << "main() 呼叫 add()前 ai =  " << ai << "\n";
    add(ai);
    cout << "main() 呼叫 add()後 ai =  " << ai ;
    
    return 0;
        
 } 
 
 int ai = 0;
 
 void add(int bi)
 {
     ai = bi + 8;
     cout << "add()  ai = " << ai << "\n";
     return;
 }

 

編譯錯誤訊息     [Error] 'ai' was not declared in this scope

在全域變數宣告位置之前的任何函數內都無法使用到該全域變數,因此編譯程式會認為main()函數內的變數ai並還沒有宣告,而在add()函數的變數ai就是宣告過的全域變數。如果你一定要在main()函數內使用ai,那麼在ai = 5; 之前要加一行 extern int ai;宣告ai為外部變數,這樣才能拓展外部變數ai的活動範圍。

正因為任何函數都有可能更改到全域變數的值,當程式有錯誤時會造成全域變數的值很難追蹤所以必須謹慎規劃全域變數,但全域變數還是有它存在的好處。

 

 

 

 

 

.

arrow
arrow
    全站熱搜

    伊蒙‧普羅客 發表在 痞客邦 留言(1) 人氣()