




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、信息科學與工程學院計算機系信息科學與工程學院計算機系卡米力卡米力C程序設計程序設計(第三版)(第三版) 學好程序設計語言的唯一途徑學好程序設計語言的唯一途徑是上機練習。是上機練習。你的編程能力與你在計算機上你的編程能力與你在計算機上投入的時間成正比。投入的時間成正比。 課程要求課程要求 課前請做好預習課前請做好預習 保持課堂安靜,頭腦清醒,思維活躍保持課堂安靜,頭腦清醒,思維活躍 做好課堂筆記做好課堂筆記 認真、獨立、按時完成并提交作業認真、獨立、按時完成并提交作業 重視上機實踐,有效利用寶貴的上機時重視上機實踐,有效利用寶貴的上機時間間7.1 為什么要用函數為什么要用函數 7.2怎樣定義函數
2、怎樣定義函數7.3調用函數調用函數7.4 對被調用函數的聲明和函數原型對被調用函數的聲明和函數原型 7.5 函數的嵌套調用函數的嵌套調用7.6函數的遞歸調用函數的遞歸調用 7.7數組作為函數參數數組作為函數參數7.8局部變量和全局變量局部變量和全局變量7.9變量的存儲方式和生存期變量的存儲方式和生存期 7.10 關于變量的聲明和定義關于變量的聲明和定義7.11 內部函數和外部函數內部函數和外部函數 第第7章章 函數函數 7.1 為什么要用函數為什么要用函數問題:問題:如果程序的功能比較多,規模比較大,如果程序的功能比較多,規模比較大,把所有代碼都寫在把所有代碼都寫在main函數中,就會使函數中
3、,就會使主函數變得龐雜、頭緒不清,閱讀和維主函數變得龐雜、頭緒不清,閱讀和維護變得困難護變得困難。有時程序中要多次實現某一功能,就需有時程序中要多次實現某一功能,就需要多次重復編寫實現此功能的程序代碼要多次重復編寫實現此功能的程序代碼,這使程序冗長,不精煉這使程序冗長,不精煉。 解決的方法:解決的方法: 用用模塊化程序設計的思路模塊化程序設計的思路采用采用“組裝組裝”的辦法簡化程序設計的過的辦法簡化程序設計的過程程事先編好一批實現各種不同功能的函數事先編好一批實現各種不同功能的函數把它們保存在函數庫中把它們保存在函數庫中,需要時需要時直接用直接用.函數就是功能函數就是功能:函數函數就是就是用來
4、用來完成完成特定的功能特定的功能的代碼的代碼函數名就是給該函數名就是給該( (函數函數) )功能起的名字功能起的名字函數的名字應反映其代表的功能函數的名字應反映其代表的功能函數名應該遵循函數名應該遵循“見名知意見名知意”。在設計一個較大的程序時,在設計一個較大的程序時,往往把它分往往把它分為為若干個程序模塊,若干個程序模塊,每一個模塊包括每一個模塊包括一一個或多個函數個或多個函數,每個函數實現一個特定每個函數實現一個特定的功能的功能。程序可由一個主函數和若干個其他函程序可由一個主函數和若干個其他函數構成數構成;主函數調用其他函數,主函數調用其他函數,其他函數也可以其他函數也可以互相調用互相調用
5、;同一個函數可以被一個或多個函數調用同一個函數可以被一個或多個函數調用任意多次任意多次。由主函數調用其他函數,由主函數調用其他函數,其他函數也可以互相調其他函數也可以互相調用。用。同一個函數可以被一個或多個函數調用任意同一個函數可以被一個或多個函數調用任意多次。多次。在程序開發中,在程序開發中,常將一些常用的功能模塊常將一些常用的功能模塊編寫成編寫成函數,函數,放在公共函數庫中放在公共函數庫中供大家選用。供大家選用。圖圖7-1 7-1 函數之間的調用關系示意圖函數之間的調用關系示意圖例例7.1 7.1 輸出一行信息,用函數調用來實現輸出一行信息,用函數調用來實現# include void m
6、ain() void printstar(); / *函數函數printstar的聲明的聲明 * / void print_message(); /* 函數函數print_message的聲明的聲明 */ printstar(); /* 調用自定義函數調用自定義函數printstar */ print_message(); /* 調用自定義函數調用自定義函數print_message */ printstar(); /* 調用自定義函數調用自定義函數printstar */ void printstar() *printstar函數的定義函數的定義* printf(* * * * * * *
7、* * * * * *n);void print_message() printf(How do you do!n); 解題思路:解題思路:在輸出的文字上下分在輸出的文字上下分別有一行別有一行“*”號,顯然不必重復號,顯然不必重復寫這段代碼,用一個函數寫這段代碼,用一個函數print_star來實現輸出一行來實現輸出一行“*”號的功能。號的功能。再寫一個再寫一個print_message函數來函數來輸出中間一行文字信息用主函數輸出中間一行文字信息用主函數分別調用這兩個函數分別調用這兩個函數。#include int main() void print_star(); void print_me
8、ssage(); print_star(); print_message(); print_star(); return 0; void print_star() printf(“*n”); void print_message() printf(“ How do you do!n”); 聲明函數聲明函數定義函數定義函數函數的調用函數的調用(1)一個一個C程序程序由一個或多個由一個或多個程序模塊組成程序模塊組成,每一個程序模塊每一個程序模塊作為一個源程序文件作為一個源程序文件。對較大的程序,對較大的程序,一般不希望把所有內容全放一般不希望把所有內容全放在一個文件中,在一個文件中,而是將他們分別
9、放在若干個而是將他們分別放在若干個源文件中,源文件中,再由若干源程序文件再由若干源程序文件組成一個組成一個C C程程序。序。這樣便于分別編寫、這樣便于分別編寫、分別編譯,提高調試效分別編譯,提高調試效率。率。一個源程序文件可以為多個一個源程序文件可以為多個C C程序公用。程序公用。(2) 一個源程序文件一個源程序文件由一個由一個或或多個函數多個函數以以及其他有關內容及其他有關內容(如命令行、數據定義等)(如命令行、數據定義等)組成。組成。一個源程序文件一個源程序文件是一個編譯單位,是一個編譯單位,在程序編在程序編譯時譯時是以源程序文件為單位是以源程序文件為單位進行編譯的,進行編譯的,而而不是以
10、函數為單位不是以函數為單位進行編譯的。進行編譯的。(3)C程序的執行程序的執行是是從從main函數開始函數開始的,的,如是在如是在main函數中函數中調用其他函數,調用其他函數,在調用后在調用后流程返回到流程返回到main函數,函數,在在main函數中函數中結束整個程序的運行。結束整個程序的運行。(4) 所有函數都是平行的,所有函數都是平行的,即在定義即在定義函數時是分別進行的,函數時是分別進行的,是互相獨立的。是互相獨立的。一個函數一個函數并不從屬于另一函數,并不從屬于另一函數,即函數即函數不能嵌套定義。不能嵌套定義。函數間可以互相調用,函數間可以互相調用,但不能調用但不能調用main函數。
11、函數。main函數是函數是系統調用的。系統調用的。(5)從用戶使用的角度看,函數有兩種:)從用戶使用的角度看,函數有兩種: 標準函數,即庫函數。標準函數,即庫函數。這是由系統提供的,這是由系統提供的,用戶不必自己定義這些用戶不必自己定義這些函數,函數,可以直接使用它們??梢灾苯邮褂盟鼈儭撜f明,應該說明,不同的不同的C系統提供的庫函數的系統提供的庫函數的數數量量和和功能功能會有一些不同會有一些不同。 用戶自己定義的函數。用戶自己定義的函數。用以解決用戶的專用以解決用戶的專門需要。門需要。(6) 從函數的形式看,函數分兩類:從函數的形式看,函數分兩類:無參函數。無參函數。如例如例7.1中的中的
12、printstar和和print_message就是就是無參函數。無參函數。在調用無參函數時,在調用無參函數時,主調函數主調函數不向不向被調用函被調用函數數傳遞數據。傳遞數據。無參函數無參函數一般用來執行一般用來執行指定的指定的一組操作。一組操作。void print_message() *定義定義print_message函數函數* printf(How do you do!n); 有參函數。有參函數。在調用函數時,在調用函數時,主調函數主調函數在調用在調用被調用函數被調用函數時,時,通過參數通過參數向被調用函數向被調用函數傳遞數據,一般傳遞數據,一般情況下,情況下,執行被調用函數時執行被調
13、用函數時會得到一個函數會得到一個函數值,值,供主調函數使用。供主調函數使用。例如:例如:int max(int x,int y) int z; / *函數體中的聲明部分函數體中的聲明部分* z=xy?x:y ; / *函數體中的執行語句函數體中的執行語句* return(z); 形式參數形式參數7.2.1. 為什么要定義函數為什么要定義函數C語言要求,在程序中用到的所有函數,必語言要求,在程序中用到的所有函數,必須須“先定義,后使用先定義,后使用”。例如,例如,想調用想調用max函數函數來求出兩個數中的大來求出兩個數中的大者,者,必須事先定義要調用的必須事先定義要調用的max函數,即函數,即指
14、指定定函數函數名字名字、函數、函數返回值類型返回值類型、函數實現的、函數實現的功能功能以及以及參數的個數與類型參數的個數與類型,將這些信息通,將這些信息通知編譯系統。知編譯系統。定義函數應包括以下幾個內容:定義函數應包括以下幾個內容: 指定函數的名字指定函數的名字,以便以后按名調用,以便以后按名調用; 指定函數類型指定函數類型,即函數返回值的類型,即函數返回值的類型; 指定函數參數的名字和類型指定函數參數的名字和類型,以便在調用,以便在調用函數時向它們傳遞數據函數時向它們傳遞數據; 指定函數的功能。指定函數的功能。這是最重要的,這是在這是最重要的,這是在函數體中解決的函數體中解決的。對于對于庫
15、函數,庫函數,程序設計者只需用程序設計者只需用#include指指令令把有關的頭文件把有關的頭文件包含到本文件模塊中即可包含到本文件模塊中即可.在有關的頭文件中包括了對函數的聲明,例在有關的頭文件中包括了對函數的聲明,例如,在程序中若用到數學函數如,在程序中若用到數學函數(sqrt,fabs),則在源文件的開頭寫上:,則在源文件的開頭寫上: #include當然,當然,程序設計者需要在程序中自己定義想程序設計者需要在程序中自己定義想用的用的而庫函數并沒有提供的函數而庫函數并沒有提供的函數1. 定義無參函數定義無參函數在定義函數時要用在定義函數時要用“類型名類型名”指定函數值的指定函數值的類型,
16、類型,即函數帶回來的值的類型。即函數帶回來的值的類型。例例7.中的中的printstar和和print_message函數函數都是都是無參函數無參函數,函數名后面的括號中是空的,函數名后面的括號中是空的( void ),沒有任何參數。),沒有任何參數。定義無參函數的格式:定義無參函數的格式:定義無參函數的一般形式為定義無參函數的一般形式為:類型名類型名 函數名函數名(void) 函數體函數體 類型名類型名 函數名函數名() 函數體函數體 包括聲明部分包括聲明部分和語句部分和語句部分例例 無參函數無參函數 printstar( ) printf(“*n”); 或或 printstar(void
17、) printf(“*n”); 定義函數時要用定義函數時要用“類型名類型名”指定函數值的類型,指定函數值的類型,即函數即函數帶回來的值的類型帶回來的值的類型.函數名后函數名后的的void表示空,即函數無參數表示空,即函數無參數定義有參函數的一般形式為定義有參函數的一般形式為:返回值類型返回值類型函數名函數名(形式參數表列形式參數表列) 聲明部分聲明部分 語句部分語句部分 函數體函數體例如:例如:int max(int x,int y) int z; /聲明部分聲明部分 z=xy?x:y ; /執行部分執行部分 return(z); 花括號內是函數體,它包括聲明部分和語句部分?;ɡㄌ杻仁呛瘮刁w,
18、它包括聲明部分和語句部分。在聲明部分定義在聲明部分定義所用的變量,所用的變量,此外此外對將要調用的函數作聲明對將要調用的函數作聲明。在函數體的語句中求出的值(為在函數體的語句中求出的值(為x與與y中大者);中大者);return(z)的作用的作用是將是將z的值作為函數值帶回到主調函數中。的值作為函數值帶回到主調函數中。return后面的括弧中的后面的括弧中的值值(z)作為函數帶回的值(或稱函數返回值)。作為函數帶回的值(或稱函數返回值)。在函數定義時已指定在函數定義時已指定max函數為整型,在函數體中定義函數為整型,在函數體中定義z為整型,為整型,二者是一致的二者是一致的,將,將z作為函數作為
19、函數max的值帶回調用函數。的值帶回調用函數。如果在定義函數時如果在定義函數時不指定函數類型不指定函數類型,系統會隱含指定函數類型為,系統會隱含指定函數類型為int型型。因此上面定義的因此上面定義的max函數左端的函數左端的int可以省寫可以省寫.這是一個求這是一個求x和和y二者中大者的函數,二者中大者的函數,笫笫1行第一個關鍵字行第一個關鍵字int表示函數值是表示函數值是整的。整的。max為函數名。括號中有兩為函數名。括號中有兩個形式參數個形式參數x和和y,它們都是整型的。,它們都是整型的。在調用此函數時,主調函數把實際在調用此函數時,主調函數把實際參數的值傳遞給被調用函數中的形參數的值傳遞
20、給被調用函數中的形式參數式參數x和和y。3. 空函數空函數調用此函數時,什么工作也不做,沒有任何調用此函數時,什么工作也不做,沒有任何實際作用。實際作用。在主調函數中寫上在主調函數中寫上“dummy();”表明表明“這這里要調用一個函數里要調用一個函數”,而現在這個函數沒有而現在這個函數沒有起作用,起作用,等以后擴充函數功能時補充上。等以后擴充函數功能時補充上。 例如:例如:void dummy( ) 定義空函數的一般形式為定義空函數的一般形式為:返回值類型函數名()返回值類型函數名() /函數體為空函數體為空 在程序設計中在程序設計中往往根據需要確定若干模往往根據需要確定若干模塊,塊, 分別
21、由一些分別由一些函數來實現。函數來實現。 而在第一階段而在第一階段只設計最基本的模塊,只設計最基本的模塊, 其其他一些次要功能他一些次要功能或或錦上添花錦上添花的功能的功能則在則在以后以后需要時需要時陸續補上。陸續補上。在編寫程序的開始階段,在編寫程序的開始階段,可以在將來準備擴可以在將來準備擴充功能的地方充功能的地方寫上一個空函數寫上一個空函數(函數名取將(函數名取將來采用的實際函數名來采用的實際函數名(如用(如用merge()()、matproduct()()、oncatenate()()、shell()()等,分別代表合并、矩陣相乘、字符串連接、等,分別代表合并、矩陣相乘、字符串連接、希
22、爾法排序等),希爾法排序等),只是這些函數未編好,只是這些函數未編好,先先占一個位置,以后用一個編好的函數代替它。占一個位置,以后用一個編好的函數代替它。這樣做,程序的結構清楚,可讀性好,這樣做,程序的結構清楚,可讀性好,以后以后擴充新功能方便,對程序結構影響不大。擴充新功能方便,對程序結構影響不大。空空函數在程序設計中常常是有用的。函數在程序設計中常常是有用的。 7.3 函數調用函數調用定義函數的目的就是為了調用此函數,以得定義函數的目的就是為了調用此函數,以得到預期的結果。到預期的結果。7.3.1 函數調用的形式函數調用的形式調用一個函數的方法很簡單調用一個函數的方法很簡單,如:如: pr
23、int_star(); /調用無參函數調用無參函數 c=max(a,b); /調用有參函數調用有參函數函數調用形式:函數調用形式: 函數名(實參表列);函數名(實參表列);如果是調用如果是調用無參函數無參函數,則,則“實參表列實參表列”可以可以沒有,但括號不能省略沒有,但括號不能省略;如果實參表列如果實參表列包含多個實參包含多個實參,則各參數間用,則各參數間用逗號隔開逗號隔開。按函數調用按函數調用在程序中出現的形式和位置來在程序中出現的形式和位置來分分,可以有以下,可以有以下3種函數調用方式種函數調用方式:1. 函數調用語句函數調用語句把函數調用單獨作為一個語句把函數調用單獨作為一個語句。例如
24、:例如: printf_star();這時不要求函數帶回值,只要求函數完成一這時不要求函數帶回值,只要求函數完成一定的操作定的操作。2. 函數表達式函數表達式函數調用出現在另一個表達式中函數調用出現在另一個表達式中。例如:例如:c=max(a,b); 。c=max(a,b); 是一次函數調用,它是賦值表是一次函數調用,它是賦值表達式中的一部分。達式中的一部分。這時要求函數帶回一個確定的值以參加表達這時要求函數帶回一個確定的值以參加表達式的運算式的運算。3. 函數參數函數參數函數調用作為另一函數調用時的實參函數調用作為另一函數調用時的實參。例如:例如: mmax(a,max(b,c);其中其中m
25、ax(b,c)是一次函數調用,是一次函數調用,它的值作為它的值作為max另一次調用的實參另一次調用的實參。經過賦值后,。經過賦值后,m的的值是值是a,b,c三者中的最大者,三者中的最大者,又如:又如:printf(“%d”,max(a , b); 也是把也是把max(a , b)作作為為printf函數的一個參數。函數的一個參數。 7.3.2 函數調用時的數據傳遞函數調用時的數據傳遞1. 形式參數和實際參數形式參數和實際參數在調用函數時,在調用函數時,大多數情況下,大多數情況下,主調函數主調函數和和被調用函數被調用函數之間之間有數據傳遞關系。有數據傳遞關系。 這就是這就是前面提到的前面提到的有
26、參函數。有參函數。 在定義函數時在定義函數時函數名后面函數名后面括號中的變量名括號中的變量名 稱為稱為“形式參數形式參數”(簡稱(簡稱“形參形參”);); 在主調函數中在主調函數中調用一個函數調用一個函數時,時,函數名后函數名后 面括號中的參數面括號中的參數(可以是一個表達式可以是一個表達式)稱為稱為 “實際參數實際參數”(簡稱(簡稱“實參實參”)。)。 實參可以是常量、變量或表達式實參可以是常量、變量或表達式。 在不同的函數之間在不同的函數之間傳遞數據時傳遞數據時,可以可以使用的法:使用的法: 參數:參數:通過形式參數和實際參數通過形式參數和實際參數 返回值:返回值:用用return語句返回
27、計算結果語句返回計算結果 全局變量:全局變量:外部變量外部變量函數參數及其傳遞方式:函數參數及其傳遞方式:形參與實參:形參與實參: 實際參數:實際參數:調用函數時調用函數時函數名后面函數名后面 括號中的括號中的變量名。變量名。 形式參數:形式參數:定義函數時定義函數時函數名后面函數名后面 括號中的括號中的變量名。變量名。 函數參數傳遞方式:函數參數傳遞方式:函數調用時函數調用時將將 實參值實參值傳遞給傳遞給形參。形參。2. 實參和形參間的數據傳遞實參和形參間的數據傳遞在調用函數過程中,在調用函數過程中,系統會把實參的值傳系統會把實參的值傳遞給被調用函數的形參遞給被調用函數的形參,或者說,或者說
28、,形參從形參從實參得到一個值實參得到一個值。該值在函數調用期間有效,該值在函數調用期間有效,可以參加可以參加被調被調函數中的運算函數中的運算。在調用函數過程中發生的在調用函數過程中發生的實參與形參間的實參與形參間的數據傳遞數據傳遞,稱為,稱為虛實結合虛實結合。例例7.2 輸入兩個整數,要求輸出其中值較大輸入兩個整數,要求輸出其中值較大者。要求用函數來找到大數。者。要求用函數來找到大數。解題思路:解題思路:1)函數名應是函數名應是見名知意見名知意,今定名為,今定名為max;2) 由于給定的兩個數是整數,返回主調函數由于給定的兩個數是整數,返回主調函數 的值的值(即較大數)(即較大數)應該是整型應
29、該是整型。3) max函數應當有兩個參數,以便從主函函數應當有兩個參數,以便從主函數接收兩個整數,數接收兩個整數,因此因此參數的類型應當參數的類型應當是整型是整型先編寫先編寫max函數:函數:int max(int x,int y) /函數的定義,函數的定義,x和和y是形參是形參 int z; z=xy?x:y; return(z); 在在max函數上面,函數上面,再編寫主函數再編寫主函數#include int main() int max(int x,int y); /函數的聲明函數的聲明 int a,b,c; printf(“two integer numbers: ); scanf(“
30、%d,%d”,&a,&b); c=max( a , b ); /函數的調用,函數的調用,實參可以是實參可以是常量常量變量變量或表達式或表達式 printf(“max is %dn”,c); #include int main() int max(int x,int y); /函數的聲明函數的聲明 int a,b,c; printf(“two integer numbers: ); scanf(“%d,%d”,&a,&b); c=max( a , b ); /函數的調用,函數的調用,實參可以是實參可以是常量常量變量變量或表或表達式達式 printf(“max is
31、 %dn”,c); int max(int x,int y) /函數的定義,函數的定義,x和和y是形參是形參 int z; z=xy?x:y; return(z); 在調用此函數時,主調函數把實在調用此函數時,主調函數把實參的值傳遞給參的值傳遞給max函數中的形參函數中的形參x和和y,實現了參數值的傳遞,實現了參數值的傳遞,把二者組合為一個程序文件,主函數在前面,把二者組合為一個程序文件,主函數在前面,max函數在下面。函數在下面。如:文件名為如:文件名為ka1.c說明:說明:在笫在笫2行的行的int表示函數值是整的。表示函數值是整的。主主函數中給出了被調用函數函數中給出了被調用函數max的聲
32、明,的聲明,max為函數名。為函數名。括號中有兩個括號中有兩個int型的形式型的形式參數參數x和和y。用。用c=max(a,b);調用了調用了max函數函數這時在這時在max函數中得到了要處理的函數中得到了要處理的兩個數據,得到的最大值返回給兩個數據,得到的最大值返回給c注意:注意:1) 實參可以是常量、變量或表達式,如:實參可以是常量、變量或表達式,如:max(3,a+b),但要求它們有確定的值;但要求它們有確定的值; 在函數調用時在函數調用時將實參的值傳遞給形參。將實參的值傳遞給形參。2) 實參與形參的類型應相同實參與形參的類型應相同或賦值兼容。或賦值兼容。例例7.2中實參和形參的類型相同
33、,都是中實參和形參的類型相同,都是int 型型,這是合法的,這是合法的 ;如果實參為如果實參為int型而形參型而形參x為為float型,或者相型,或者相反,則按不同類型數值的賦值規則進行轉換反,則按不同類型數值的賦值規則進行轉換.例如,實參例如,實參a為為float型變量,其值為型變量,其值為3.5,而而形參形參x為為int型,型,則在傳遞時先將實數則在傳遞時先將實數3.5轉換轉換成成3,然后送到形參,然后送到形參x。char型和型和int型通用型通用.main() int a,b,c; scanf(%d,%d,&a,&b); c=max(a,b); printf(Max is
34、 %d,c);max(int x, int y) /函數定義函數定義 int z; z=xy?x:y; return(z);形參形參實參實參(max 函數)函數)c=max(a , b);(main 函數)函數)max( int x, int y ) int z; z=xy?x:y; return(z); 實參和形參間的數據傳遞實參和形參間的數據傳遞void main() int x, y, z;int max( int a,int b );printf(請輸入兩個整數:請輸入兩個整數:n);scanf(“%d%d”,&x,&y); z=max( x , y ); printf
35、(“max=%dn”,z);int max( int a , int b ) int c; c=ab ? a : b; return c; 實參與形參,參數傳遞實參與形參,參數傳遞:x 3y 5zabc 5355 求兩個數中的最大數:求兩個數中的最大數:在定義函數中在定義函數中指定的形參,指定的形參,在未出現在未出現函數函數調用調用時,時,它們并不占它們并不占內存中的存儲單元。內存中的存儲單元。只有在發生只有在發生函數調用時函數調用時,函數函數max中的中的形參形參才被分配內存單元。才被分配內存單元。在調用結束后,在調用結束后,形參所占的內存單元形參所占的內存單元也也被釋放。被釋放。 7.3.
36、3 函數調用的過程函數調用的過程2a3bxy23實參實參形參形參調用函數時將實參對應的值傳遞給形參,調用函數時將實參對應的值傳遞給形參,如圖如圖7.3所示,實參的值為所示,實參的值為2,把把2傳遞給相應傳遞給相應的形參的形參x,這時形參,這時形參x就得到值就得到值2,同理,形同理,形參參y得到值得到值3。#include int main() int max(int x,int y); /函數的聲明函數的聲明 int a,b,c; printf(“two integer numbers: ); scanf(“%d,%d”,&a,&b); c=max( a , b ); /函數的
37、調用函數的調用 printf(“max is %dn”,c); int max(int x,int y) /函數的定義函數的定義 int z; z=xy?x:y; return(z); 在執行在執行max函數期間,函數期間,由于形參已經有值由于形參已經有值,就可以利用形參進行有關的運算就可以利用形參進行有關的運算(例如,(例如,x和和y比較,把最大值賦給比較,把最大值賦給z等)等)。#include int main() int max(int x,int y); /函數的聲明函數的聲明 int a,b,c; printf(“two integer numbers: ); scanf(“%d,
38、%d”,&a,&b); c=max( a , b ); /函數的調用函數的調用 printf(“max is %dn”,c); int max(int x,int y) /函數的定義函數的定義 int z; z=xy?x:y; return(z); 通過通過return語句將函數值帶回到主函數。語句將函數值帶回到主函數。例例7.2中在中在return語句中語句中指定的返回值是指定的返回值是z,這個,這個z就是就是函函數數max的返回值的返回值。執行執行return語句就把這個函數返語句就把這個函數返回值帶回主函數回值帶回主函數main。注意:注意:返回值返回值z的類型與的類型與
39、max函數的類型一致。函數的類型一致。若函數不需要返回值,若函數不需要返回值,則則不需要不需要return語句,語句,這時函數類型應定義為這時函數類型應定義為 main() int max(int x,int y); /函數的聲明函數的聲明 int a,b,c; scanf(“%d,%d”,&a,&b); c=max( a , b ); /函數的調用函數的調用 printf(“max is %dn”,c); int max(int x,int y) /函數的定義函數的定義 int z; z=xy?x:y; return(z); 函數函數調用結束,調用結束,則則形
40、參單元被釋放形參單元被釋放。注意:注意:實參單元仍保留并維持原值,實參單元仍保留并維持原值,實參的實參的值并值并沒有改變沒有改變。如果在執行一個被調用函數時,如果在執行一個被調用函數時,若若形參的值形參的值發生改變發生改變,則則不會改變主調函數的實參的值不會改變主調函數的實參的值.例如:形參在執行例如:形參在執行max函數的過程中,形參函數的過程中,形參x,y的值變為的值變為10和和15,但但a和和b的值仍為的值仍為2和和3,這是因為,這是因為實參與形參在內存中占用不同實參與形參在內存中占用不同的存儲單元。的存儲單元。2a3bxy1015實參實參形參形參/例子例子 函數參數為普通變量時形參對實
41、參的影響函數參數為普通變量時形參對實參的影響 void main() int swap(int x,int y); /被調用函數被調用函數swap的聲明的聲明 int a,b,result; printf(請輸入需要交換的兩個整數請輸入需要交換的兩個整數:n); scanf(a=%d,b=%d,&a,&b); printf(交換之前的值是交換之前的值是:a=%d, b=%dn,a,b); swap(a,b); /swap函數的調用函數的調用printf(返回到返回到main函數后的最終交換結果是函數后的最終交換結果是:a=%d, b=%dn,a,b); int swap(int
42、 x,int y) /swap函數的定義函數的定義 int temp; temp=x; x=y; y=temp;printf(在在swap函數中兩個數交換的結果是函數中兩個數交換的結果是:a=%d, b=%dn,x,y); 在語言中,在語言中,實參實參向向形參的形參的數據傳遞是數據傳遞是“值值傳遞傳遞”,單向傳遞,單向傳遞,只由只由實參實參傳給傳給形參形參,而而不不能能由形參傳回來給實參。由形參傳回來給實參。在內存中,在內存中,實參單元實參單元與與形參單元形參單元是不同的單是不同的單元。元。 c=max(a , b ); (main 函數)函數)max(int x, int y) int z;
43、 z=xy?x:y; return(z); (max 函數)函數)2a3bxy1015實參實參形參形參【例例】 編寫求任意數之冪的程序編寫求任意數之冪的程序即求即求xn。分析:分析:在前面已給出了求在前面已給出了求x的的n次方的函數次方的函數power(),所以只要在主函數中,所以只要在主函數中,輸入輸入x和和n的值,的值,并作為并作為power()的參數,的參數,加上調用加上調用power(x,n) 語句即可,語句即可,完整的程序清單如下:完整的程序清單如下:#include void power(float x,int n) ;/*函數說明函數說明*/ void main( ) float
44、 x; int n; printf(“輸入輸入x=? n=? n”); scanf(“%f%d”,&x,&n); power(x,n); /*函數調用函數調用*/ void power(float x,int n) /*函數定義函數定義*/ int i; double p=1.0; for (i=1,p=1;i=n;i+) p *= x; /* xn=x*x*x.*x 即即n次連乘次連乘 */ printf(“%f的的%d次方次方=%fn”,x,n,p); 7.3.4 函數的返回值函數的返回值通常,希望通過函數調用通常,希望通過函數調用使主調函數能得到使主調函數能得到一個確定的
45、值,一個確定的值,這就是這就是函數的返回值。函數的返回值。例如例如:例例7.2中,中,c=max(2,3) ; 的值是的值是3; c=max(5,2); 的值是的值是5。賦值語句賦值語句將這個函數值將這個函數值3或或5賦給變量賦給變量c。例如:例如: c=max(5,2);main()() int max(int x,int y); int a,b,c;scanf(d,d,a,b);); cmax(a,b);); /*函數的調用函數的調用*/ printf(ax isd,c);); max(int x,int y) * 定義有參函數定義有參函數max* int z zxy?x y; retur
46、n(z);); return語句將被調用函數語句將被調用函數中的一個確定值帶回主調中的一個確定值帶回主調函數中去。函數中去。見圖見圖8.2中從中從return語句返回的箭頭。語句返回的箭頭。關于函數返回值的一些說明:關于函數返回值的一些說明: 函數的返回值函數的返回值是通過函數中的是通過函數中的return語句語句獲得的獲得的。 return語句將語句將被調用函數中的一個被調用函數中的一個確定確定值值帶回主調函數中去。帶回主調函數中去。見圖見圖7.2中從中從return語句返回的箭頭。語句返回的箭頭。如果需要如果需要從被調用函數從被調用函數帶回一個函數值供主帶回一個函數值供主調函數使用,調函數
47、使用,被調用函數中被調用函數中必須包含必須包含return語句。語句。如果不需要如果不需要從被調用函數從被調用函數帶回函數值帶回函數值可以不可以不要要return語句。語句。一個函數中一個函數中可以有一個以上的可以有一個以上的return語句,語句,執行到哪一個執行到哪一個return語句,語句,哪一個語句起作哪一個語句起作用。用。return語句后面的括弧語句后面的括弧也可以不要,如也可以不要,如: “ return z; ” 等價于等價于 “ return (z);); ” max(int x,int y)return(xy?x y););return后面的值后面的值可以是一個表達式可以是
48、一個表達式。例如,例例如,例7.2中的函數中的函數max可以改寫成:可以改寫成:這樣的函數更為簡短,只用一個這樣的函數更為簡短,只用一個return語句語句就把就把求值求值和和返回返回都解決了。都解決了。函數的返回值函數的返回值應當屬于應當屬于某一個確定的類型,某一個確定的類型,在定義函數時在定義函數時指定函數指定函數返回值的類型。返回值的類型。例如例如:下面是下面是3個函數的首行:個函數的首行:int max(float x,float y) /* 函數值為整型函數值為整型 */char letter(char c1,char c2) /* 函數值為字符型函數值為字符型 */ double
49、min(int x,int y) /* 函數值為雙精度型函數值為雙精度型 */在在C語言中,語言中,凡不加類型說明凡不加類型說明的函數,的函數,自動自動按整型按整型(int)處理。)處理。例例7.2中的中的max函數函數首行的函數類型首行的函數類型int可以可以省寫,省寫,用用TC 2.0編譯程序時編譯程序時能通過能通過,但用,但用TC+ 3.0編譯程序時編譯程序時不能通過,不能通過,因為因為C+要要求求所有函數所有函數都必須指定都必須指定函數類型。函數類型。因此因此,建議在定義時建議在定義時對所有函數對所有函數都指定都指定函數類函數類型。型。在定義函數時在定義函數時指定的指定的函數類型函數類
50、型一般應該一般應該和和return語句中的語句中的表達式類型表達式類型一致。一致。如果函數值的類型如果函數值的類型和和return語句中表達式的語句中表達式的值值不一致,不一致,則則以函數類型以函數類型為準。為準。對數值型數據,對數值型數據,可以自動進行類型轉換可以自動進行類型轉換。即即函數類型函數類型決定決定返回值的類型返回值的類型。 例例 7.3 返回值類型與函數類型不同返回值類型與函數類型不同#includevoid main() int max(float x,float y); float a,b; int c; printf(請輸入請輸入2個實數:個實數:n); scanf(%f,
51、%f,&a,&b); c=max(a,b); printf(max is %dn,c); int max(float x,float y) float z; z=xy?x:y; return(z);自定義函數自定義函數max定義為定義為int型,型,而而return語句中的語句中的z為為float型,型,類型不一致,類型不一致,按按上述規定上述規定,先將先將z轉換成轉換成int型,型,然后然后max(x,y)帶回一帶回一個個整型值整型值2返回主調函數返回主調函數main。如果將如果將main函數中的函數中的c定定義為義為float型,型,用用%f格式輸格式輸出,出,也是輸出也是
52、輸出2.000000。因為調用因為調用max函數得到的函數得到的是是2,然后把,然后把2賦給賦給float型型的的c則得到則得到2.000000。對于對于不帶回值的函數,不帶回值的函數,應當用應當用“void”定定義函數為義函數為“無類型無類型”(或稱或稱“空類型空類型”)。)。這樣,這樣,系統就保證系統就保證不使函數帶回任何值不使函數帶回任何值,即即禁止在調用函數中禁止在調用函數中使用使用被調用函數的返回值。被調用函數的返回值。此時此時在函數體中在函數體中不得出現不得出現return語句。語句。7.4 對被調用函數的聲明和函數原型對被調用函數的聲明和函數原型 在一個函數中調用另一個函數在一個
53、函數中調用另一個函數需要具備如下需要具備如下條件條件:(1) 被調用函數必須是已經定義的函數被調用函數必須是已經定義的函數(是(是庫庫 函數或用戶自己定義的函數)函數或用戶自己定義的函數);(2) 如果使用庫函數,應該在本文件開頭如果使用庫函數,應該在本文件開頭加加相相 應的應的#include指令指令將調用有關庫函數時將調用有關庫函數時所所 需用到的信息包含到本文件中來需用到的信息包含到本文件中來。例如:。例如: #include如果如果不包含不包含文件中的信息,在程文件中的信息,在程序中序中就就無法使用無法使用輸入輸出庫中的函數。輸入輸出庫中的函數。若使用數學庫函數中的函數若使用數學庫函數
54、中的函數,則使用:,則使用: #include(3) 如果使用如果使用自己定義的函數自己定義的函數,而該函數的而該函數的位位置在調用它的函數置在調用它的函數(main函數函數)后面后面(在同(在同一個文件中)一個文件中),應該,應該在主函數中給出在主函數中給出被被調用函數的調用函數的聲明聲明。聲明的作用是:聲明的作用是:把函數名,函數參數的個把函數名,函數參數的個數和參數類型等信息數和參數類型等信息通知編譯系統通知編譯系統,以,以便在遇到函數調用時,便在遇到函數調用時,編譯系統能正確編譯系統能正確識別函數識別函數并檢查并檢查調用是否合法調用是否合法。 如果使用如果使用自己定義的函數自己定義的函
55、數,而該函數而該函數的位的位置在調用它的函數置在調用它的函數(main函數函數)之前之前,則在則在主函數中不需要給出主函數中不需要給出被調用函數的被調用函數的聲明聲明。函數的定義:函數的定義:對函數功能的確立,對函數功能的確立,包括指包括指定定函數的返回值類型,函數名、形參及其函數的返回值類型,函數名、形參及其類型、函數體等,類型、函數體等,它是一個完整的、獨立它是一個完整的、獨立的函數單位;的函數單位;函數的聲明:函數的聲明:把函數的返回值類型,函數名,把函數的返回值類型,函數名, 函數參數后面加分號,函數參數后面加分號,即函數定義中的第即函數定義中的第1行行(函數首部)(函數首部)加一個分
56、號加一個分號,就成了函數原,就成了函數原型或型或函數的聲明函數的聲明。例例7.4 輸入兩個實數,用一個函數求出它們輸入兩個實數,用一個函數求出它們之和。之和。解題思路:解題思路:用用add函數實現。首先要定義函數實現。首先要定義add函數,它為函數,它為float型,它應有兩個參數,型,它應有兩個參數,也應為也應為float型。型。分別編寫分別編寫add函數和函數和main函數,它們組成一函數,它們組成一個源程序文件個源程序文件。由于由于main函數的位置在函數的位置在add函數之前函數之前,因此因此在在main函數中對函數中對add函數進行聲明函數進行聲明。注意:注意:在在main函數中函數
57、中要要給出給出add函數函數的的聲明聲明#include int main() float add(float x, float y); float a,b,c; printf(Please enter a and b:); scanf(%f,%f,&a,&b); c=add(a,b); printf(sum is %fn,c); return 0;float add(float x,float y) float z; z=x+y; return(z); 對對add函數聲明函數聲明:函數定義:函數定義中的首行加分號中的首行加分號由于被調用由于被調用函數函數add的定義在的定義在
58、main函數的函數的下面下面,因此在,因此在main函函數中數中必須給出該函數必須給出該函數的聲明的聲明。add函數函數的定義:的定義:包括包括函數的返回值類型,函數的返回值類型,函數名、形參及其類函數名、形參及其類型、函數體。型、函數體。函數的首行加分號函數的首行加分號函數的聲明。函數的聲明。 為什么要用函數的首部來作為函數的聲明?為什么要用函數的首部來作為函數的聲明?這是為了便于對函數調用的合法性進行檢查這是為了便于對函數調用的合法性進行檢查.因為在函數的首部包含了因為在函數的首部包含了檢查調用函數是否檢查調用函數是否合法的基本信息合法的基本信息(它包括了函數的返回值類(它包括了函數的返回
59、值類型、函數名、函數的參數個數、參數類型和型、函數名、函數的參數個數、參數類型和參數順序),參數順序),在檢查函數調用時要求在檢查函數調用時要求函數名、函數名、函數類型、參數個數和參數順序函數類型、參數個數和參數順序必須與必須與函數函數聲明一致聲明一致,實參類型必須與函數聲明中的形實參類型必須與函數聲明中的形參類型相同參類型相同,否則就按出錯處理,否則就按出錯處理,這樣就能這樣就能保證函數的正確調用。保證函數的正確調用。函數原型的一般形式有兩種函數原型的一般形式有兩種:如:如: float add(float x, float y); 或者或者 float add(float, float);
60、實際上,在函數聲明中的形參名可以省寫,實際上,在函數聲明中的形參名可以省寫,而只寫形參的類型,而只寫形參的類型,這是因為:這是因為:編譯系統只編譯系統只關心和檢查參數個數和參數類型,關心和檢查參數個數和參數類型,而不檢查而不檢查參數名參數名,因為在調用函數時只要求,因為在調用函數時只要求保證實參保證實參類型與形參類型一致類型與形參類型一致,而不必考慮形參名是,而不必考慮形參名是什么。什么。若函數聲明放在文件的開頭,若函數聲明放在文件的開頭,這時下面的所這時下面的所有函數都可以使用此函數。有函數都可以使用此函數。函數類型函數類型 函數名函數名(參數類型參數類型1,參數類型,參數類型2);函數類型函數類型 函數名函數名(參數類型參數類型1,參數名,參數名1,參數類型,參數類型2,參數名,參數名2); 如果使用如果使用用戶自己定義的函數,用戶自己定義的函數,而該函數而該函數 的位置的
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 陵園墓地代理合作協議范本
- 家庭護理員居間服務合同
- 【小學 三年級數學】三年級下冊數學口算試題
- 舞臺布景設計與制作合同樣本
- 2024泰安市工程職業中等專業學校工作人員招聘考試及答案
- 2024泌陽縣中等職業技術學校工作人員招聘考試及答案
- 2024湖南省郴州市第一職業中等專業學校工作人員招聘考試及答案
- 2024河北省唐縣職業技術教育中心工作人員招聘考試及答案
- 大型倉儲設施消防工程合同書
- 物業服務公司員工安全合同責任書模板
- 2024年新人教版六年級數學上冊《教材練習2練習二 附答案》教學課件
- 【核心素養目標】六年級科學下冊(蘇教版)4.13 潔凈的水域(教案)
- 北師大版心理健康一年級下冊《珍愛生命》教案
- 中考英語688高頻詞大綱詞頻表
- 黑龍江省齊齊哈爾市2024年中考數學試卷【附真題答案】
- 2024年廣東省中考生物試卷附答案
- 2024年江蘇省宿遷市泗陽縣中考物理一模試卷含詳解
- 新生兒嗆奶窒息的應急預案及處理
- 2024年全國國家版圖知識競賽題庫及答案(中小學組)
- 《給教師的100條建議》讀書交流會省公開課金獎全國賽課一等獎微課獲獎課件
- (正式版)QBT 8015-2024 熟制松籽和仁
評論
0/150
提交評論