C語言程序設(shè)計教程(修訂本)第5章模塊設(shè)計.ppt_第1頁
C語言程序設(shè)計教程(修訂本)第5章模塊設(shè)計.ppt_第2頁
C語言程序設(shè)計教程(修訂本)第5章模塊設(shè)計.ppt_第3頁
C語言程序設(shè)計教程(修訂本)第5章模塊設(shè)計.ppt_第4頁
C語言程序設(shè)計教程(修訂本)第5章模塊設(shè)計.ppt_第5頁
已閱讀5頁,還剩34頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

第5章 模塊設(shè)計,5.1 模塊的實現(xiàn)函數(shù) 5.2 模塊間的參數(shù)傳遞 5.3 模塊的遞歸調(diào)用 5.4 程序舉例 5.5 編譯預(yù)處理,5.1 模塊的實現(xiàn)函數(shù),5.1.1 函數(shù)的概念 在C語言中,函數(shù)分為以下兩種。 (1)標準庫函數(shù) 這種函數(shù)用戶不必定義,但可直接使用。例如scanf() , printf() , fabs() , sqrt() ,exp(),sin(),cos()等都是C語言中常用的庫函數(shù)。 (2)用戶自己定義的函數(shù) 這種函數(shù)用以解決用戶的專門問題,一般由用戶自己編寫。,返回目錄,例5.1 從鍵盤輸入兩個正整數(shù)m與n(mn),求 的值(即求 )。 其C程序如下: #include “stdio.h“ main() /*主函數(shù)*/ int m,n; int p(); /*說明本函數(shù)中要調(diào)用的函數(shù)p()是整型*/ scanf(“%d,%d“,&m,&n); if (mn) printf(“%dn“,p(m)/p(mn); else printf(“mn ! n“); int p(k) /*計算階乘值的函數(shù)*/ int k; int s,i; s1; for (i1; ik; ii1) ss*i; return(s); ,下面對函數(shù)作幾點說明: (1)一個完整的C程序可以由若干個函數(shù)組成,其中必須有一個且只能有一個主函數(shù)main()。 (2)一個完整C程序中的所有函數(shù)可以放在一個文件中,也可以放在多個文件中。 在編譯命令行中鍵入各個函數(shù)所在的文件名(各文件名之間用空格分隔)。 在主函數(shù)中用 #include 語句將各函數(shù)所在的文件包含進來。 (3)C語言中的函數(shù)沒有從屬關(guān)系,各函數(shù)之間互相獨立,可以互相調(diào)用。,5.1.2 函數(shù)的定義 在C語言中,函數(shù)定義的一般形式為 類型標識符 函數(shù)名(形參表列) 形參類型說明 說明部分 語句部分 ,在定義C函數(shù)時要注意以下幾點。 (1)函數(shù)類型標識符同變量類型說明符,它表示返回的函數(shù)值類型。 (2)如果省略函數(shù)的類型標識符,則默認為是int型。 (3)C語言允許定義空函數(shù)。如 dummy() ,(4)函數(shù)中返回語句的形式為 return(表達式); 或 return 表達式; (5)如果“形參表列”中有多個形式參數(shù),則它們之間要用“,”分隔。 (6)C語言允許在形參表中直接對形參的類型進行說明。,5.1.3 函數(shù)的調(diào)用 函數(shù)調(diào)用的一般形式為 函數(shù)名(實參表列) (1)函數(shù)調(diào)用可以出現(xiàn)在表達式中(有函數(shù)值返回);也可以單獨作為一個語句(無函數(shù)值返回)。 (2)實參表中的各實參可以是表達式,但它們的類型和個數(shù)應(yīng)與函數(shù)中的形參一一對應(yīng)。 (3)在調(diào)用函數(shù)中,通常要對被調(diào)用函數(shù)的返回值類型進行說明(一般在調(diào)用函數(shù)的函數(shù)體中的說明部分),包括函數(shù)類型、函數(shù)名和一對圓括號。,例5.2 下列程序的功能是計算輸出一個圓臺兩底面積之和。 #include “stdio.h“ main() double r1,r2; double q(); printf(“input r1 ,r2: “); scanf(“%lf,%lf“,&r1,&r2); printf(“s%fn“,q(r1,r2); double q(x,y) double x,y; double s; s3.1415926*(x*xy*y); return(s); ,但C語言規(guī)定,在以下幾種情況下可以不在調(diào)用函數(shù)中對被調(diào)用函數(shù)作類型說明: 被調(diào)用函數(shù)為整型或字符型,自動按整型處理。 被調(diào)用函數(shù)的定義出現(xiàn)在調(diào)用函數(shù)之前。 在調(diào)用函數(shù)之前已經(jīng)由別的函數(shù)(它可能也要調(diào)用該被調(diào)用函數(shù))對被調(diào)用函數(shù)作了類型說明。 (4)C語言雖不允許嵌套定義函數(shù),但可以嵌套調(diào)用函數(shù)。,5.2 模塊間的參數(shù)傳遞,5.2.1 形參與實參的結(jié)合方式 1地址結(jié)合 所謂地址結(jié)合,是指在一個模塊調(diào)用另一個模塊時,并不是將調(diào)用模塊中的實參值直接傳送給被調(diào)用模塊中的形參,而只是將存放實參的地址傳送給形參。 2數(shù)值結(jié)合 所謂數(shù)值結(jié)合,是指調(diào)用模塊中的實參地址與被調(diào)用模塊中的形參地址是互相獨立的,在一個模塊調(diào)用另一個模塊時,直接將實參值傳送給形參被存放在形參地址中。,返回目錄,例5.3 分析下列C程序: void swap(x,y) int x,y; int t; tx; xy; yt; return; #include “stdio.h“ main() int x,y; scanf(“x%d,y%d“,&x,&y); swap(x,y); printf(“x%d,y%dn“,x,y); ,在這個程序中共有兩個函數(shù)。在主函數(shù)中分別為整型變量x與y輸入數(shù)據(jù),然后調(diào)用函數(shù)swap(x,y)。而函數(shù)swap(x,y)的功能是實現(xiàn)變量x值與y值的交換。但在實際運行該程序時,如果從鍵盤輸入 x6,y8 則輸出的結(jié)果為 x6,y8 即沒有達到交換的目的。這是因為在主函數(shù)中調(diào)用函數(shù)swap()時,只是將實參x和y的值分別傳遞給了swap()函數(shù)中的形參x和y,但由于主函數(shù)中的實參x和y與函數(shù)swap()中的形參x和y在計算機中的存儲地址是不同的,因此,在函數(shù)swap()中雖然交換了形參x與y的值,但實參x與y的值實際上沒有改變,即它們沒有被交換。,由此可以看出,在形參與實參為數(shù)值結(jié)合的情況下,實參與形參在計算機內(nèi)存中的存儲地址不是同一個,因此,即使在被調(diào)用函數(shù)中改變了形參值,調(diào)用函數(shù)中的實參值也是不會被改變的。,5.2.2 局部變量與全局變量 1局部變量 在函數(shù)內(nèi)部定義的變量稱為局部變量。函數(shù)內(nèi)部定義的變量只在該函數(shù)范圍內(nèi)有效,因此,不同函數(shù)中的局部變量可以重名,互不混淆。 2全局變量 在函數(shù)外定義的變量稱為全局變量。,除非十分必要,一般不提倡使用全局變量,其原因有以下幾點: 由于全局變量屬于程序中的所有函數(shù),因此,在程序的執(zhí)行過程中,全局變量都需要占用存儲空間,即使實際正在執(zhí)行的函數(shù)中根本用不著這些全局變量,它們也要占用存儲空間。 在函數(shù)中使用全局變量后,要求在所有調(diào)用該函數(shù)的調(diào)用程序中都要使用這些全局變量,從而會降低函數(shù)的通用性。 在函數(shù)中使用全局變量后,使各函數(shù)模塊之間的互相影響比較大,從而使函數(shù)模塊的“內(nèi)聚性”差,而與其他模塊的“耦合性”強。 在函數(shù)中使用全局變量后,會降低程序的清晰性,可讀性差。,5.2.3 動態(tài)存儲變量與靜態(tài)存儲變量 1用戶程序的存儲分配 一般來說,用戶程序在計算機中的存儲分配如圖5.1所示。,圖5.1 用戶程序在計算機中的存儲分配,其中: 程序區(qū)用于存放程序; 靜態(tài)存儲區(qū)是在程序開始執(zhí)行時就分配的固定存儲單元,如全局變量; 動態(tài)存儲區(qū)是在函數(shù)調(diào)用過程中進行動態(tài)分配的存儲單元,如函數(shù)形參、自動變量、函數(shù)調(diào)用時的現(xiàn)場保護和返回地址等。,2變量的存儲類型 數(shù)據(jù)類型:如整型(int)、實型(float)、字符型(char)、雙精度型(double)等。 數(shù)據(jù)的存儲類型:分為自動類型(auto)、靜態(tài)類型(static)、寄存器類型(register)、外部類型(extern)。,例5.4 計算并輸出15的階乘值。其C程序如下: int fac(n) int n; static int f1; ff*n; return(f); #include “stdio.h“ main() int i; for (i1; i5; ii1) printf(“%d!%dn“,i,fac(i); ,下面對靜態(tài)存儲變量作幾點說明: 形參不能定義成靜態(tài)類型。 對局部靜態(tài)變量賦初值是在編譯時進行的,在調(diào)用時不再賦初值;而對自動變量賦初值是在調(diào)用時進行的,每次調(diào)用將重新賦初值。 定義局部靜態(tài)變量時若不賦初值,則在編譯時將自動賦初值0;但在定義自動變量時若不賦初值,則其初值為隨機值。 若無多大必要,盡量不用局部靜態(tài)變量。,3外部變量 全局變量如果在文件開頭定義,則在整個文件范圍內(nèi)的所有函數(shù)都可以使用該變量。 一般來說,全局變量有以下幾種用法: 在同一文件中,為了使全局變量定義點之前的函數(shù)中也能使用該全局變量,則應(yīng)在函數(shù)中用extern加以說明。 使一個文件中的函數(shù)也能用另一個文件中的全局變量。 利用靜態(tài)外部變量,使全局變量只能被本文件中的函數(shù)引用。,5.2.4 內(nèi)部函數(shù)與外部函數(shù) 在C語言中,函數(shù)可以分為內(nèi)部函數(shù)與外部函數(shù)。只能被本文件中其他函數(shù)調(diào)用的函數(shù)稱為內(nèi)部函數(shù),內(nèi)部函數(shù)又稱為靜態(tài)函數(shù)。 定義內(nèi)部函數(shù)的形式如下: static 類型標識符 函數(shù)名(形參表) 定義外部函數(shù)的形式如下: extern 類型標識符 函數(shù)名(形參表),5.3 模塊的遞歸調(diào)用,人們在解決一些復(fù)雜問題時,為了降低問題的復(fù)雜程度(如問題的規(guī)模等),一般總是將問題逐層分解,最后歸結(jié)為一些最簡單的問題。,返回目錄,例5.5 編寫一個C函數(shù),對于輸入的參數(shù)n,依次打印輸出自然數(shù)1到n。 這是一個很簡單的問題,實際上不用遞歸就能解決,其C函數(shù)如下: #include “stdio.h“ wrt(int n) int k; for (k1;kn;k) printf(“%dn“,k); return; ,解決這個問題還可以用以下的遞歸函數(shù)來實現(xiàn): #include “stdio.h“ wrt1(int n) if (n!0) wrt1(n1); printf(“%dn“,n); return; ,自己調(diào)用自己的過程稱為遞歸調(diào)用過程。在C語言中,自己調(diào)用自己的函數(shù)稱為遞歸函數(shù)。 遞歸分為直接遞歸與間接遞歸兩種。 所謂直接遞歸,是指直接調(diào)用函數(shù)本身。,5.4 程序舉例,例5.6 編寫一個函數(shù),其功能是判斷給定的正整數(shù)是否是素數(shù),若是素數(shù)則返回函數(shù)值1,否則返回函數(shù)值0。 其C函數(shù)如下: #include “math.h“ sushu(int n) int k,i,flag; ksqrt(double)n); i2; flag0; while (ik)&(flag0) if (n%i0) flag1; ii1; return(!flag); ,返回目錄,例5.8 Hanoi塔問題。 相傳古代印度有一座Bramah廟,廟中有三根插在黃銅板上的寶石柱,在其中的一根柱子上放了64個金盤子,大盤在下,小盤在上,稱為Hanoi塔。有一天,廟里的和尚們想把這些盤子從一根柱子上移到另一根柱子上,規(guī)定每次只允許移動一個盤子,并且,在移動過程中都不允許出現(xiàn)大盤子壓在小盤子上面的現(xiàn)象,但在移動盤子的過程中可以利用三根柱子中的任何一根。 為了使問題具有普遍性,假設(shè)圓盤數(shù)為n,按直徑從小到大依次編號為1,2,n;三根柱子的名稱分別為X,Y,Z。開始時,n個圓盤按從大到小的順序(即下面放大圓盤,上面放小圓盤)放在X柱子上,現(xiàn)在要將X柱子上的n個圓盤移到Z柱子上,其移動的原則如上所述。這個問題稱為n階Hanoi塔問題。,可以寫出C程序如下: #include “stdio.h“ main() int n; char xX,yY,zZ; void hanoi(); printf(“input n“); scanf(“%d“,&n); hanoi(n,x,y,z); void hanoi(n,x,y,z) int n; char x,y,z; void move();,if (n1) move(x,n,z); else hanoi(n1,x,z,y); move(x,n,z); hanoi(n1,y,x,z); return; void move(x,n,z) int n; char x,z; printf(“%c(%d)%cn“,x,n,z); ,5.5 編譯預(yù)處理,編譯預(yù)處理功能是C語言的一個重要特點。所謂編譯預(yù)處理,是指C語言編譯系統(tǒng)首先對程序模塊中的編譯預(yù)處理命令進行處理。 C語言提供的編譯預(yù)處理命令主要有以下3種: (1)宏定義; (2)文件包含命令; (3)條件編譯命令。 編譯預(yù)處理命令一般是在函數(shù)體的外面。正確使用編譯預(yù)處理命令,可以編寫出易于調(diào)試、易于移植的程序模塊。,返回目錄,5.5.1 文件包含命令 文件包含是指一個源文件可以將另一個指定的源文件包括進來。 文件包含命令的一般形式為 #include 文件名 或 #include “文件名“ 其功能是將指定文件中的全部內(nèi)容讀到該命令所在的位置后一起被編譯。,在使用文件包含命令時,要注意以下幾個問題: (1)當#include命令指定的文件中的內(nèi)容改變時,包含這個文件的所有源文件都應(yīng)該重新進行編譯處理; (2)一個#include命令只能指定一個被包含文件,如果需要包含多個文件,則要用多個#include命令實現(xiàn); (3)被包含的文件應(yīng)該是源文件,不能是經(jīng)編譯后的目標文件; (4)文件包含可以嵌套使用,即被包含的文件中還可以使用#include命令; (5)由#include命令所指定的文件中可以有任何語言成分,因此,通??梢詫⒔?jīng)常使用的、具有公用性質(zhì)的符號常量、帶參數(shù)的宏定義以及外部變量等集中起來放在這種文件中,以盡量避免一些重復(fù)操作。,5.5.2 條件編譯命令 C語言的編譯預(yù)處理程序提供了條件編譯能力,以便使同一個源程序在不同的編譯條件下能夠產(chǎn)生不同的目標代碼文件。 1#ifdef,#else,#endif 其一般形式為 #ifdef 標識符 程序段1 #else 程序段2 #endif 其作用是,如果“標識符”已經(jīng)定義過(一般是指用#define命令定義),則程序段1參加編譯,而程序段2不參加編譯;否則程序段2參加編譯,而程序段1不參加編譯。,2#i

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論