1.函數的用途
 
函數(function)又稱函式﹐亦和副程式(subprogram)相似﹐利用函數有下列優點:
     1.1 當某項工作需重覆多次時﹐可寫成函數﹐在需要時呼叫它即可﹐這樣可避免程式碼的重覆撰寫。
     1.2 因為將程式分割成各有所司任務的函數﹐因此程式易於了解﹐架構清楚。 
     1.3 每一函數有獨立性﹐因為函數內的區域變數只有函數本身可使用﹐所以維護也容易。(不會兩三天後就看不懂程式碼)
 
2.函數的範例
 
    
        
            |  //定義hello函數 void hello(){   printf(“Hello!\n”);  }   int main(){//呼叫hello函數     hello(); }   | 
    
 
     
 
 
 
3.函數的定義 
 
syntax:
    
        
            |   回傳資料型態 函數名稱([資料型態1 參數1, 資料型態2 參數2…..]){    敘述1    敘述2…..    [return 回傳值]  }   | 
    
 
 
 
e.g.
    
        
            |  //下列函式可回傳x、y中較大的值 int max(int x,int y){    if(x>y)      return x;    else      return y;  }   | 
    
 
 
說明:如不須回傳資料,則回傳資料型態可用void,如不須傳入參數,則可留空白,如前例void hello(),
 
 
 
4.函數的呼叫
 
syntax:
 
 
 
e.g.
    
        
            |   show_table();//無參數,且無回傳值的函數 minvalue=min(15,10);//有參數,且有回傳值的函數   printf("%d",max(5,10));   | 
    
 
 
 
說明:呼叫函數時,應在呼叫前先行定義函數。另外呼叫函數時,所傳入的參數數目與資料型態須與函數宣告時一致。
 
 
5.區域變數與全域變數(Local variables vs Glabal variables)
 
 
函數內的變數為區域變數﹐外界無法使用。 
若定義全域變數﹐則在定義後的所有段落均可使用。
 
 
請見下例:
    
        
            |   int a=1; void foo_before(int c) {      int d=a+1;      a=c+d;//b=...錯誤!在此不能存取b,因其為main的區域變數。 }   int main() {      int b=2;      foo_before();      printf("a=%d",a);//d=...錯誤!在此不能存取d,因其為foo_before的區域變數。      //foo_after()...錯誤!在此不能呼叫foo_after,因foo_after的宣告在後。 }   void foo_after() { /* Empty function */ }   | 
    
 
 
 
6.想想看,請寫出下列函數。
 
6.1.min(x,y)(求最小值)
6.2.power(x,y)(求x的y次方值)
6.3.ctf(degree)(將攝氏溫度轉華氏溫度,公式為 華式溫度=1.8*攝式溫度+32)
 
 
 
7.參數傳遞方式
 
7.1 傳值呼叫(pass by value)
    參數利用複製值的方式傳遞﹐於函數結束時參數的值不受改變。
7.2 傳址呼叫(pass by address)
    參數利用指標方式傳遞(記憶體位址)﹐參數值可被更改。
7.3 傳參考呼叫(pass by reference)
    機制類似傳址呼叫﹐但使用上較為簡單方便﹐僅需在函數定義時註明&。
7.4 e.g.﹕
    
        
            |  //x:pass by value,y:pass by address,z:pass by reference int foo(int x,int *y,int &z){      x=x+1;      *y=*y+2;      z=z+3; }   int main(){      int a,*b,c;      a=5,b=&a,c=a;//執行foo()函式前,a,*b,c數值為5,5,5      printf(“a=%d,b=%d,c=%d\n”,a,*b,c);      foo(a,b,c);//執行foo()函式後,a,*b,c數值為5,7,8      printf(“a=%d,b=%d,c=%d\n”,a,*b,c); }   | 
    
 
 
 
7.5 想想看:
  7.5.1 寫一函數swap(x,y)﹐能將兩參數調換。
  7.5.2 寫一函數order(x,y,z)﹐能將三參數依大小順序排好。
                  
8.遞迴函數(recursion)
 
8.1     遞迴函數具有以下特徵
特徵1﹕呼叫自身函數 
特徵2﹕需有終止條件
 
8.2     範例一﹕階乘 N!=N*(N-1)*(N-2)*...*2*1
    
        
            |  //階乘函數 fact(n)=n*(n-1)*(n-2)*……*1 int fact(int n){      if(n==1)return 1; //終止條件         elsereturn n*fact(n-1); //呼叫自身函數 }   | 
    
 
 
 
8.3 範例二﹕費布納西數列 f(x)=f(x-2)+f(x-1),f(0)=1;f(1)=1
    
        
            |   int fib(int n){      if(n==0||n==1)           return 1;      else           return fib(n-2)+fib(n-1); }   | 
    
 
 
 
8.4 範例三﹕河內塔
 
8.4.1 遊戲說明:請參考九章出版社網址
     http://ccmp.chiuchang.com.tw/toy/hanoi/hanoi.html
 
8.4.2 線上河內塔游戲
     http://www.shes.hcc.edu.tw/~oddest/math181.swf
 
8.4.3 河內塔範例程式
    
        
            |   #include <stdio.h> #include <stdlib.h> int steps=0; void honai(char src,char dest,char aux,int disk) {     if(disk>=1)     {       honai(src,aux,dest,disk-1);       printf("move disk %d from %c to %c\n",disk,src,dest);       steps++;       honai(aux,dest,src,disk-1);     } }                                              int main() {     int disk;     printf("How many disks?");     scanf("%d",&disk);     honai('A','C','B',disk);     printf("Total steps:%d\n",steps);     system("pause"); }   | 
    
 
 
8.5 想想看
//待補遞迴之練習題及範例