Presentation is loading. Please wait.

Presentation is loading. Please wait.

第五章 函數與儲存類別. 函數 函數為完成某一次特定任務或工作的小程式 函數的類型 庫存函數 (library functions) 如: scanf() 、 printf() 函數 … 等 此函數為系統所提供可以直接呼叫使用之 自定函數 (user-define functions) 此函數是使用者自行定義之函數.

Similar presentations


Presentation on theme: "第五章 函數與儲存類別. 函數 函數為完成某一次特定任務或工作的小程式 函數的類型 庫存函數 (library functions) 如: scanf() 、 printf() 函數 … 等 此函數為系統所提供可以直接呼叫使用之 自定函數 (user-define functions) 此函數是使用者自行定義之函數."— Presentation transcript:

1 第五章 函數與儲存類別

2 函數 函數為完成某一次特定任務或工作的小程式 函數的類型 庫存函數 (library functions) 如: scanf() 、 printf() 函數 … 等 此函數為系統所提供可以直接呼叫使用之 自定函數 (user-define functions) 此函數是使用者自行定義之函數 函數的其它特點 它與變數一樣都有資料型態 函數傳回值之資料型態必須和函數之資料型態一致

3 函數的三個要素 /* File name: ex5-1a.c */ #include void print_star(); int main( ) { print_star(); printf("Bright Tsai"); print_star(); } void print_star( ) { printf("***********"); } 函數的語法 函數的呼叫 函數的定義

4 函數的三個要素 函數的語法 好比說英文或法文時,需符合英文文法或法文文法 一樣,因此當您在函數呼叫時,若與函數語法不符, 編譯程式便在編譯時期會發出錯誤訊息 函數的語法,一般寫在 main( ) 函數的上面,從此便 可知此程式用到了幾個函數 函數的呼叫 函數的呼叫是執行函數的定義區段 函數的定義 此區段為函數所要完成的工作,如範例 5-1a.c 為印 出 11 個 ’ * ’

5 函數的呼叫 函數的呼叫可以帶有參數 參數的類型 形式參數( formal argument ) 實際參數( actual argument ) 參數傳遞方式 傳值呼叫( call by value ) 傳址呼叫( call by address ) 範例 ex5-1b.c

6 傳值呼叫 /* File name: ex5-1b.c */ #include void print_star(int); int main() { print_star(30); printf( “ Mr. Bright Tsai is at the NCTU\n ” ); print_star(30); } void print_star(int k) { int i; for(i = 1; i <= k; i++) printf( “ * ” ); print( “ \n ” ); } 形式參數 實際參數

7 return 敘述 在函數定義中, return 敘述表示將此結果傳回給呼 叫此函數的敘述,並將控制權交回 若無 return 敘述,則遇到右大括號( } )便結束函數 定義且交回控制權給呼叫此一敘述的下一個敘述 C 程式中不可有巢狀函數 (nested function)

8 return 程式範例 ( 一 ) /* File name: ex5-2a.c */ #include double average(double, double); int main( ) { double score_1, score_2, aver; printf("Enter two double numbers: "); while(scanf("%lf %lf", &score_1, &score_2) == 1) { printf("Input error!!\n"); printf("Enter two number: "); } aver = average(score_1, score_2); printf("%.2f + %.2f / 2 = %.2f\n", score_1, score_2, aver); } double average(double f1, double f2) {

9 return 程式範例 ( 一 ) float average(float f1, float f2) { return ((f1 + f2) / 2); } 程式解說 當一函數執行完有傳回值傳回呼叫函數的敘述時, 必須注意此函數的資料型態必須與傳回值的資料型 態一致才可 如傳回值為 ((f1+f2)/2) 是一浮點數,故 average 的函 數資料型態也必須為浮點數

10 return 程式範例 ( 二 ) /* File name: ex5-2b.c */ #include void funct(int, int); int main() { int a = 1000, b = 2000; funct(a, b); printf( “ a = %d b = %d\n ”, a, b); }

11 return 程式範例 ( 二 ) void funct(int a, int b) { int c; c = a + b; printf("a + b = %d\n", c); return c; } 程式解說 若參數使用 void ,如 funct(void) 是表示 funct 函數 不接受任何參數

12 遞迴函數 遞迴函數 (recursive function) 在函數本身中, 若有一敘述又呼叫它本身函數 遞迴函數範例 計算某數的階層,如: 6! 費氏數列 設計遞迴函數時必須注意結束點

13 計算 n 階層 /* File name: ex5-3a.c */ #include int fact(long); int main() { long number, total; printf( “ Enter a number: ” ); while(scanf( “ %ld ”, &number) == 1) if(number > 13) { printf( “ Input must be less than 13\n ” ); printf( “ Enter a number: ” ); } else break; total = fact(number); printf( “ %ld! = %ld\n ”, number, total); }

14 計算 n 階層 long fact(long number) { if(number == 0 || number == 1) /* 返迴點 */ return 1; else return (number * fact(number -1)); }

15 計算 n 階層 程式解說 如輸入為 6 ,則其執行的步驟如下: 6 * fact(5) 5 * fact(4) 4 * fact(3) 3 * fact(2) 2 * fact(1) 傳回 1

16 費氏序列 /* File name: ex5-3c.c */ #include int fibonacci(int); int main() { int n, ans; printf( “ Enter a number(n > = 0): ” ); scanf( “ %ld ”, &n); if(n < 0) printf( “ Number must be > 0\n ” ); else { ans = fibonacci(n); printf( “ fibonacci(%ld) = %ld\n ”, n, ans); }

17 int fibonacci(int n) { if(n == 0) return 0; else if(n == 1) return 1; else return (fibonacci(n – 1) + fibonacci(n -2)); }

18 巨集指令 乃是用 #define 以某一名稱代替一些處理問題的步驟 巨集指令會比函數產生較多的程式碼,但其執行比 較快 如: #define SQUARE(x) x * x

19 巨集指令範例 /* File name: ex5-4a.c */ #include #define SQUARE(x) x * x void main() { printf( “ Square of 10 is %d/n ”, SQUARE(10)); printf( “ Square of 8 + 2 is %d\n ”, SQUARE(8 + 2)); }

20 前置處理程式 #define 前置處理程式 除了用來當做巨集指令外,最常用的不外乎以某一 符號常數( Symbol constant )代替此一常數 如:將 RATE 取代 33.699 #include #define RATE 33.699 void main( ) { float total;... total = RATE * 5000;... }

21 區域變數與全域變數 區域變數 定義在函數裡面的變數 全域變數 定義在函數外面的變數

22 區域變數與全域變數 區域變數與全域變數的特性 當一程式區域變數和全域變數同名時,以區域變數 優先 使用區域變數前,一定要設定初值,或由使用者輸 入該變數的初值後才使用,否則可能產生 “ garbage value ” 全域變數的勢力範圍是其定義位置底下的所有函數, 在其以上的函數是不能用的 區域變數的存活期在函數執行完畢之後,區域變數 所佔的記憶體將被回收,等再進入函數時,才會再 次的為此變數配置記憶體

23 區域變數與全域變數程式範例 #include void a(); void b(); void a() { printf( “ k = %d\n ”, k); } int k = 200; /* 全域變數 */ void b() { printf( “ k = %d\n ”, k); } void main() { int k = 100; /* 區域變數 */ printf( “ k = %d\n ”, k); a(); b(); } K 的勢力範圍

24 儲存類別 變數利用資料型態以配置記憶體,並利用儲存 類別規範其存活期 儲存類別分別有 auto, static, register, extern 儲存類別放在資料型態的前面或後面皆可,但 習慣上會以儲存類別在前,資料型態在後

25 儲存類別 --auto auto 儲存類別 先前我們提到的變數皆為 auto ,此為內定值,亦即 不必加以註明也可以,如 auto int i; 與 int i; 具有相同的意義

26 儲存類別 --register register 儲存類別 屬於此類的變數,系統會將它放在 CPU 中的暫存器 (register) 放在暫存器的變數比放在記憶體的變數,處理的速 度來得快,不過由於 CPU 的暫存器有限,且每個皆 各有所司,因此系統最多給程式兩個暫存器儲存類 別的變數,其餘的皆會主動設定為 auto 因此 register 和 auto 大致上功能類似 假設在程式中有一多層的迴圈,若最內層的變數設 定為 register ,會使得程式的執行加快

27 儲存類別 --static 靜態儲存類別變數之宣告方式 在變數名稱前加一 static 關鍵字 靜態儲存類別變數的類型 靜態區域變數:此類變數在程式結束時, 此變數才會 消失 靜態全域變數:資料隱藏

28 儲存類別 --static /* File name: ex5-6a.c */ #include void stat_ai(); int main() { int i; for(i = 1; i <= 5; i++) stat_ai(); } void stat_ai() { int ai = 1; static int si = 1; printf("ai = %d\n", ai++); printf("si = %d\n\n", si++); }

29 儲存類別 --extern /* file 1 */ void callme() int i = 100; int main() { int i = 200; i += 30; callme(); } /* file 2 */ int callme() { extern int i; /* 宣告 */ i += 100; printf( “ i = %d ”, i); } …


Download ppt "第五章 函數與儲存類別. 函數 函數為完成某一次特定任務或工作的小程式 函數的類型 庫存函數 (library functions) 如: scanf() 、 printf() 函數 … 等 此函數為系統所提供可以直接呼叫使用之 自定函數 (user-define functions) 此函數是使用者自行定義之函數."

Similar presentations


Ads by Google