函數 Function ●什麼是函數?函數就是一段獨立程式,用來處理獨立的工作。

Slides:



Advertisements
Similar presentations
第一單元 建立java 程式.
Advertisements

第一章 C语言概述 计算机公共教学部.
程式設計 博碩文化出版發行.
C語言中可變参數的用法——va_list、va_start、va_arg、va_end参數定義
Chapter 5 遞迴 資料結構導論 - C語言實作.
Chapter 5 迴圈.
Introduction to the C Programming Language
第十一章 結構.
Visual C++ introduction
簡易C++除錯技巧 長庚大學機械系
函數(一) 自訂函數、遞迴函數 綠園.
2 C++ 程式概論 2.1 C++ 程式結構 程式註解 // 插入標題檔 #include 2-3
列舉(enum).
Chap 10 函数与程序结构 10.1 函数的组织 10.2 递归函数 10.3 宏定义 10.4 编译预处理.
101北一女中 資訊選手培訓營 妳不可不了解的指標 Nan.
第七章 函数 目录 有参的加法函数的开发 函数定义的一般形式 函数参数和函数的值 函数的调用
C語言簡介 日期 : 2018/12/2.
Function.
第 6 章 函式.
類別(class) 類別class與物件object.
SQL Stored Procedure SQL 預存程序.
第6章 函數與巨集 6-1 由上而下的設計方法 6-2 建立函數 6-3 函數的參數呼叫方式 6-4 變數的有效範圍 6-5 遞迴函數
Methods 靜宜大學資工系 蔡奇偉副教授 ©2011.
6 使用者函數 6.1 函數定義 宣告函數 呼叫函數 呼叫多個函數 6-6
期中考试成绩分布 《程序设计》-2017年秋.
Java 程式設計 講師:FrankLin.
程式設計實習課(四) ----C 函數運用----
第七章 函数及变量存贮类型 7.1 函数基础与C程序结构 7.2 函数的定义和声明 7.3 函数的调用 7.4 函数的嵌套与递归
第一單元 建立java 程式.
第1章 概述 本章要点: C语言程序结构和特点 C语言程序的基本符号与关键字 C语言程序的编辑及运行 学习方法建议:
|07 函數.
C语言大学实用教程 第5章 函数与程序结构 西南财经大学经济信息工程学院 刘家芬
輸入&輸出 函數 P20~P21.
第十章 指標.
挑戰C++程式語言 ──第8章 進一步談字元與字串
Oop8 function函式.
認識常數與變數 學習C++所提供的各種基本資料型態 瞭解溢位的發生 學習認識資料型態之間的轉換
Chap 5 函数 5.1 计算圆柱体积 5.2 使用函数编写程序 5.3 变量与函数.
7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
Class & Object 靜宜大學資工系 蔡奇偉副教授 ©2011.
函數 博碩文化出版發行.
C程序设计.
第5章 函 数.
C语言程序设计 李祥 QQ:
C qsort.
<编程达人入门课程> 本节内容 为什么要使用变量? 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ:
第二章 类型、对象、运算符和表达式.
挑戰C++程式語言 ──第7章 輸入與輸出.
流程控制:Switch-Case 94學年度第一學期‧資訊教育 東海大學物理系.
MiRanda Java Interface v1.0的使用方法
Introduction to the C Programming Language
函數應用(二)與自定函數.
陣列與結構.
挑戰C++程式語言 ──第9章 函數.
北一女中 資訊選手培訓營 妳不可不了解的指標 Nan.
Chap 6 函數 故用兵之法,十則圍之,五則攻之,倍則分之, 敵則能戰之,少則能逃之,不若則能避之。 故小敵之堅,大敵之擒也。
第四章 陣列、指標與參考 4-1 物件陣列 4-2 使用物件指標 4-3 this指標 4-4 new 與 delete
What is “this”? 在物件導向程式設計中,類別的定義就是在說明如果創建了“這個物件”的話,它會具有那些屬性與功能,以及這些功能是如何實現的。 而所謂的“這個物件”就以 this 來表示。 當我們在JavaScript與jQuery中寫 script 程式(函式)時,“誰”呼叫這個函式,這個“誰”就是該函式中所謂的.
作業系統實習課(二) -Scheduler-Related System Calls-
Programming & Language Telling the computer what to do
Chapter 6 函數.
Introduction to the C Programming Language
ABAP Basic Concept (2) 運算子 控制式與迴圈 Subroutines Event Block
String類別 在C語言中提供兩種支援字串的方式 可以使用傳統以null結尾的字元陣列 使用string類別
Array(陣列) Anny
C語言程式設計 老師:謝孟諺 助教:楊斯竣.
JUDGE GIRL 使用介紹 & 常見問題 TAs :
方法(Method) 函數.
ABAP Basic Concept (2) 運算子 控制式與迴圈 Subroutines Event Block
InputStreamReader Console Scanner
Presentation transcript:

函數 Function ●什麼是函數?函數就是一段獨立程式,用來處理獨立的工作。 這些工作可以是數值的計算、資料的輸出與輸入、繪圖的控制、字串的處理等等,只要是你想做的任何程式動作,都可用函數來設計。 ●函數的使用,牽涉到函數的定義、宣告與呼叫,傳入函數的引數與傳回的函數值。 ● 一般的C程式發展工具都提供了超過數百個常用的函數,涵蓋了數值資料及字元資料的處理、輸入與輸出的控制,記憶體空間的配置、各種系統設定的訊息、繪圖的應用等等

函數定義(Definition) 定義一個函數的語法如下: 資料型態 函數名稱 ( 引數部份 ) { 函數內部變數宣告 主體敘述 } 資料型態 函數名稱 ( 引數部份 ) { 函數內部變數宣告   主體敘述 } 例 int add1 (int num_in) int num_out; num_out=num_in+1; return num_out;

圖 2-1 C 程式的架構 #include <stdio.h> #include <math.h> 前端處理指令 #define PI 3.14159   float rv; float degree_to_radius(int); 變數及函數宣告   main (int argc, char *argv[ ] ) 主程式 { int deg;   deg=45; rv=degree_to_radius(deg); printf("Degree %d equals to Radius scale %f \n",deg, rv); } float degree_to_radius(int d) 其他函數程式 float rad; rad=d*PI/180; return d;

函數的宣告 通常,我們會把主程式 main 放前面,其他的函數排在程式的後面,因為在主程式中先呼叫函數,而定義在後,所以要先宣告函數傳回值的資料型態,以便 編譯程式安排空間來儲存函數的傳回值。 float degree_to_radius(int); 函數宣告 main () { rv = degree_to_radius(deg); 函數呼叫 }  float degree_to_radius(int d) 函數定義 ... }

函數宣告、呼叫、定義 int add1 (int); 宣告(declare) main() { int a=9,b; b = add1(a); 呼叫(call) } int add1 (int num_in) 定義(define) { int num_out; num_out=num_in+1; return num_out;

函數的原型宣告 (prototype) 完整宣告函數的引數和傳回值,就知道如何呼叫這個函數,這就是所謂函數的原型宣告 (prototype)。使用內建的函數時,應注意其原型宣告要 #include 哪個 .h 標頭檔,例如  #include <math.h> double sqrt (double x);  如果函數沒有宣告或敲錯函數名稱,程式編譯時,通常會得到 Function 'XXX' should have a prototype 的錯誤訊息。

引數的傳遞 呼叫函數時,應注意該函數的定義中,所指定的引數個數,各個引數的資料型態,以及引數排列的次序 , 例如 定義 int max (int a, int b) { if (a>=b) return a; else return b; } 呼叫時 int p,q; r = max(p,q); 每個引數都要個別宣告,所以 max (int a, int b) 不可寫成 max (int a,b),這是初學者常犯的錯誤

傳值呼叫 (call by value) 實際引數的 “值” 會 “拷貝” 一份給型式引數,進入函數之內運用,而實際引數本身不受函數執行的影響 square (int a) // 形式引數 a { a = a*a; return a; } main() { int x=3; y = square( x ); // 實際引數 x printf("x=%d, y=%d",x,y); 執行結果 x=3 y=9

函數的傳回值 ● 一個函數可以有一個或數個輸入引數,或是不帶任何輸入引數,但卻只有一個函數傳回值 (return value) ● C 語言有一項特殊的規定,任何未宣告資料型態的函數,其傳回值皆被預設為 int 型態 ● C++ 語言規定: 所有的函數都應該指定引數及傳回值資料型態 ,所以該加上的 #include <stdio.h> 或 #include <conio.h> 等決不可少 ●有一種特殊的資料型態稱為 void,意思是 “不指定”資料型態。如果某一個函數只是進行一些列印、繪圖、音樂等動作,不需要傳回任何值,就可以指定其傳回值為 void 型態

【範例 6-2-1】 p1/2 設計一個函數 abs,傳入一個整數值,傳回它的絕對值。設計一個簡單的程式,測試 abs 函數的效果。 6 int abs ( n ) 7 int n; 8 { 9 if (n < 0) 10 return -n; 11 else 12 return n; 13 }

【範例 6-2-1】 p2/2 15 main() 16 { 17 int num, value; 18 16 { 17 int num, value; 18 19 printf("Enter an integer : "); 20 scanf("%d",&num); 21 value = abs( num ); 22 printf("absolute value of %d is %d\n",num,value); 23 }

【範例 6-2-2】 p1/2 6 main() 7 { 8 int sum( int ); // update for C++ 設計一個函數 sum,傳入一個整數值 n,傳回 1+2+....+n 的值。並設計一個簡單的程式,測試 sum 函數的效果。 6 main() 7 { 8 int sum( int ); // update for C++ 9 int num; 10 11 printf("Enter an positive integer : "); 12 scanf("%d",&num); 13 printf("sum of 1+2+...+%d is %d\n", num, sum(num) ); 14 }

【範例 6-2-2】 p2/2 15 int sum ( n ) // this is for K&R C 16 int n; //int sum (int n)for ANSI C 17 { 18 int value=0, i; 19 20 for (i=1; i<=n; i++) 21 value += i; 22 return value; 23 }

遞迴函數 (Recursive Function) 遞迴函數是一種特殊的函數,在函數的定義時呼叫函數本身 遞迴函數的設計,必注意兩個要點: 1. 何時終止遞迴的條件。 2. 每次函數呼叫自己時輸入引數的 "降格"。

【範例 6-3-1】 設計一個階乘函數 fac,傳入一個整數 n,傳回 1*2*...*n (也就是 n!) 的值,請使用遞迴 (recursive) 的方式來設計此函數。 n! = n * (n-1)! 0! = 1 16 long fac ( int n ) 17 { 18 if (n <= 1) return 1; 19 20 return n*fac(n-1) ; 21 }

【範例 6-3-2】非遞迴 n! = n*(n-1)*(n-2)* …*1 16 long fac ( int n ) 17 { 17 { 18 long product = 1L; 19 20 while (n > 1) 21 { 22 product *= n; 23 n--; 24 } 25 return product;

【範例 6-3-3】p1/2 Fibonacci 數列是個著名的數列,由 1,1,2,3,5,8,13,..... 所構成,其法則是第 n 個數由前兩數 (第 n-1 個和第 n-2 個)相加而得。試使用遞迴的方式,設計一個函數 fib,傳入整數 n,傳回第 n 個Fibonacci數的數值。 Fn=Fn-1+Fn-2 F0=1 F1=1 16 int fib ( int n ) 17 { 18 if (n <= 1) return 1; 19 20 return fib(n-1)+fib(n-2);

【範例 6-3-3】p2/2 6 main() 7 { 8 int fib( int ); 9 int num; 10 7 { 8 int fib( int ); 9 int num; 10 11 printf("Enter a positive integer : "); 12 scanf("%d",&num); 13 printf("fib(%d) = %d\n", num, fib(num)); 14 }

變數的類別 ●所謂的變數 (variable),是指記憶體中某一個儲存資料的地方,如果儲存的是整數資料,就稱為整數變數,如果是浮點數資料,就稱為浮點數變數,依此類推。例如,宣告 int a; 說明變數 a 是一個整數變數,這是依照其資料型態 (data type) 來分,不同的資料型態會影響所佔據的記憶體大小 ●變數名稱,是程式中用來指明那個變數;變數的位址,是指變數在記憶體中被安排的地址;變數的值,是指那個記憶體位址中所儲存的資料值:變數的資料型態,必須在宣告變數時指定

全域變數與區域變數 ●區域 (local) 變數,就是指這個變數是定義在某個函數之內,它的勢力範圍 (scope) 只涵蓋這函數的區域之內。只有這個函數內的程式片段能夠使用到這個內在變數,其他的函數包括主程式在內,都不能存取到這個變數 ●全域 (global) 變數,則是指這個變數是定義在所有函數之外,並不屬於任何特定的函數。有點類似教室的公佈欄,任何學生(函數)都看得到它,可以對它進行讀寫的控制,而內在變數就像學生筆記本的資料,只有擁有者才看得到。所有函數都可以直接取到全域變數 ●函數和外在變數一樣,都具有全域的性質

【範例 6-4-1】 p1/2 6 int ball; /* global ball */ 7 int i; /* global i */ 9 main() 10 { 11 int k; 12 13 ball = 0; 14 k = ++ball; 15 printf("main() : ball=%d\n",ball); 16 printf("main() : k=%d\n",k); 17 add1(); 18 doubleball(); 19 }

【範例 6-4-1】 p2/2 21 add1() 22 { 23 int i=0; /* local i */ 24 25 ball++; 22 { 23 int i=0; /* local i */ 24 25 ball++; 26 i++; 27 printf("add1() : ball=%d\n",ball); 28 printf("add1() : i=%d\n",i); 29 } 31 doubleball() 32 { 33 int ball=99; /* local ball */ 34 int k=ball+1; 35 36 ball *= 2; 37 k++; 38 printf("doubleball() : ball=%d\n",ball); 39 printf("doubleball() : k=%d\n",k); 40 }

【範例 6-4-1】執行結果 main() : ball=1 main() : k=1 add1() : ball=2 add1() : i=1 doubleball() : ball=198 doubleball() : k=101

自動變數與靜態變數 ●宣告 auto (自動變數) 是指那個變數所佔據的記憶體位置,會在函數執行時自動被安排出來,結束執行時自動被收回 ●宣告為 static (靜態變數) 的變數,是指那個變數的值是靜態不動的,變數的內容值會一直保存,每次執行函數時,上次的變數值仍然存在 ●如果將 static 宣告用於某函數內的區域變數,那麼,雖然這個變數的值會一直保存,但是不會被其他函數看到。 因此 static 變數比 auto 變數,具有較長的生命期 (life time ) ●如果區域變數不指定 auto 或 static,就被認為是自動變數 ,所以 auto 通常是被省略的

static 宣告 ●將 static 宣告用於某函數內的區域變數,那麼,雖然這個變數的值會一直保存,但是不會被其他函數看到

register 宣告與 extern 宣告 ●register 宣告用於通知編譯程式,說明這個變數會使用頻繁,儘可能把這些 register 變數放到 CPU 的暫存器中,以加快程式的執行,但是編譯程式卻不一定會接受這一點要求 ●extern 宣告是說明某個函數內所使用特定的變數或函數,是定義這個函數之外的,對全域變數而言,加上 extern 宣告,通常是指這個檔案中使用到這個全域變數或函數,而這個全域變數或函數,是定義在其他檔案之中 。否則,程式連結 (link) 時,就會被系統察覺出來,發出錯誤訊息 (undefined)

全域變數的 extern 宣告 ●全域變數的宣告 (declaration) 與定義 (definition) 之間的區別是相當重要的,宣告說明了變數的型別,而定義不但含有宣告的意味,更會為這個變數實際上安排所應佔的記憶體位置,來儲存其資料。任何全域變數,可能在數個檔案中用 extern 宣告,但只能有一個定義,否則就會出現 redefine 的錯誤訊息

巨集(macro) 巨集 (macro) 是程式中的常數、字串、或是一段程式,為了能方便地重覆使用,或是讓程式更能望文生義,所採取的指令代換寫法。巨集定義的格式如下:   #define 名稱 代換內容  意思是請編譯程式在進行編譯前,先將程式所有出現這個名稱的部份,都用 “代換內容” 來取代 例如: #define PI 3.1416  這個巨集指令是指示編譯程式將目前所編譯的原始程式中,所有出現 PI的地方,全部換成 3.1416。如此,原始程式就不必直接寫出數值 3.1416,而用符號名稱 PI 來撰寫,這樣較能清楚地表現程式所使用"圓周率的"的意義

函數與巨集 巨集指令也可以帶參數,例如 #define abs(x) ((x)>=0)﹖(x):-(x) 是將程式中的 巨集指令也可以帶參數,例如  #define abs(x) ((x)>=0)﹖(x):-(x)  是將程式中的  a=abs(p+q);  自動代換成  a=((p+q)>=0)﹖(p+q):-(p+q); 程式片段的巨集定義看起來和函數很像,但是他們是不一樣的。函數呼叫時,是跳到那個函數程式所在位址去執行,原始程式只編譯成一個函數呼叫的機器指令。而巨集的呼叫,是將那個名稱及參數,"展開" 成所定義的程式片段,安插在所呼叫的地方,所以如果呼叫多次程式會變得較長,所產生的可執行檔會較大。但是,因為省略了函數呼叫及返回時的處理動作,所以執行速度較快

常用的 ANSI C函數 ●使用系統提供的函數時,應注意函數原型所引用的標頭檔 (.h),所傳入的引數個數與資料型態,以及函數傳回值的資料型態。例如,使用求正弦(sine)值的函數,其用法如下:  #include <math.h> double sin(double x); ●ANSI C 所包括的函數名稱和用法,可以在網際網路上很容易搜尋到,例如: 在 Google 搜尋ANSI C function可以找到 http://cermics.enpc.fr/~ts/C/FUNCTIONS/function.ref.html