版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
第六章函數(shù)目錄/Contents函數(shù)定義、函數(shù)調(diào)用、函數(shù)原型、函數(shù)的參數(shù)傳遞與返回值函數(shù)封裝,函數(shù)復用,函數(shù)設計的基本原則,程序的健壯性遞歸函數(shù)和函數(shù)的遞歸調(diào)用變量的作用域與存儲類型,全局變量、自動變量、靜態(tài)變量、寄存器變量模塊化程序設計方法◆當一個程序的代碼量達到數(shù)千行以上時,所有的代碼都放在main函數(shù)中嗎?如何進行團隊合作?◆所有代碼放在一個文件中,如何進行團隊合作?◆調(diào)試良好的代碼如何被其他程序使用呢?◆當一個問題的規(guī)模很大時,應該采用什么樣的方法來解決它呢?問題的提出模塊化程序設計思想分而治之函數(shù)把較大的任務分解成若干個較小的任務,并提煉出公用任務信息隱藏設計良好的函數(shù)可把具體操作細節(jié)對外界隱藏起來,從而使整個程序結(jié)構(gòu)清楚使用函數(shù)時,用戶不用知道函數(shù)內(nèi)部是如何運作的,只按照我們的需要和它的參數(shù)形式調(diào)用它即可函數(shù)的定義■函數(shù)是C語言中模塊化程序設計的最小單位,用來實現(xiàn)各種不同的功能。每個函數(shù)可看作是一個程序模塊?!瞿K化程序設計如同制造機器,函數(shù)相當于機器的“零部件”
-先將這些“零部件”單獨設計、調(diào)試和測試好,接著進行組裝,最后進行綜合測試。
-這些“零部件”既可以是自己設計的,也可以是別人設計好的,還可以是現(xiàn)成的標準產(chǎn)品。■若干個函數(shù)可以合成一個“模塊”■一個C程序由一個或若干個源文件組成■一個源文件由一個或多個函數(shù)組成函數(shù)的定義■一般來說,函數(shù)是各自獨立、平等的,沒有高低貴賤之分。
-main()稍稍特殊一點,
-程序的執(zhí)行從main()的入口地址開始-在函數(shù)體中順序、循環(huán)、遞歸、迭代地調(diào)用各個函數(shù),調(diào)用其他函數(shù)后程序執(zhí)行流程返回main函數(shù)
-在main()的出口結(jié)束程序的運行函數(shù)的分類■標準庫函數(shù)
-ANSI/ISOC定義的標準庫函數(shù)符合標準的C語言編譯器必須提供這些函數(shù)函數(shù)的行為也要符合ANSI/ISOC的定義-第三方庫函數(shù)由其他廠商自行開發(fā)的C語言函數(shù)庫不在標準范圍內(nèi),能擴充C語言的功能(圖形、網(wǎng)絡、數(shù)據(jù)庫等)■自定義函數(shù)
-自己定義的函數(shù)包裝后,也可成為函數(shù)庫,供別人使用函數(shù)的分類返回值類型
函數(shù)名(類型形式參數(shù)1,類型形式參數(shù)2,…)←函數(shù)頭部{
聲明語句序列
執(zhí)行語句序列}函數(shù)的定義函數(shù)體函數(shù)體的定界符void函數(shù)名(void)←函數(shù)頭部{
聲明語句序列
執(zhí)行語句序列}函數(shù)體函數(shù)定義【例6.1】
編寫一個函數(shù)計算整數(shù)x的n次冪
。/*函數(shù)功能:用迭代法計算x的n次冪。
函數(shù)參數(shù):整型變量x表示底數(shù),整型變量n表示冪指數(shù)。
函數(shù)返回值:返回x的n次冪的值。*/longPower(intx,intn) /*函數(shù)定義*/{ inti; longresult=1; for(i=0;i<n;i++) { result=result*x;/*計算x的n次冪*/ } returnresult;/*將result的值作為函數(shù)的返回值返回*/}返回值類型函數(shù)名說明函數(shù)的功能形參表,函數(shù)入口函數(shù)內(nèi)部可以定義只能自己使用的變量,稱內(nèi)部變量返回值作為函數(shù)調(diào)用表達式的值函數(shù)調(diào)用◆有返回值時:◆無返回值時函數(shù)名(實參表列);
返回值=函數(shù)名(實參表列);函數(shù)調(diào)用#include<stdio.h>intmain(){intp,q;longret;printf("pleaseinputtwointegers:");scanf("%d%d",&p,&q);ret=Power(p,q);printf("ret=%ld",ret);return0;}函數(shù)原型聲明#include<stdio.h>longPower(intx,intn);intmain(){intp,q;longret;printf("pleaseinputtwointegers:");scanf("%d%d",&p,&q);ret=Power(p,q);printf("ret=%ld",ret);return0;}末尾有一個分號,聲明時不要省略形參和返回值的類型longPower(intx,intn){ inti; longresult=1; for(i=0;i<n;i++) { result=result*x; } returnresult;}函數(shù)定義函數(shù)定義指函數(shù)功能的確立指定函數(shù)名、函數(shù)類型、形參及類型、函數(shù)體等是完整獨立的單位
函數(shù)聲明是對函數(shù)名、返回值類型、形參類型的說明不包括函數(shù)體是一條語句,以分號結(jié)束,只起一個聲明作用函數(shù)聲明與函數(shù)定義的區(qū)別函數(shù)封裝與防御性編程■函數(shù)封裝(Encapsulation)使得外界對函數(shù)的影響僅限于入口參數(shù),而函數(shù)對外界的影響僅限于一個返回值。【例6.2】
試編寫一個函數(shù),從鍵盤輸入整數(shù)n,計算n!,并編寫測試程序。longFac(intn){ inti; longresult=1; for(i=2;i<=n;i++) { result=result*i; } returnresult;}#include<stdio.h>longFac(intn);intmain(){ intm; longret; printf("pleaseinputm:"); scanf("%d",&m); ret=Fac(m); /*調(diào)用階乘計算函數(shù)*/ printf("%d!=%ld",m,ret); /*輸出語句*/ return0;}防御性編程■函數(shù)具有遇到不正確使用或非法數(shù)據(jù)輸入時保護自己避免出錯的能力。在函數(shù)的入口處增加對入口參數(shù)的合法性檢查,是一種增強程序健壯性的有效方法。/*用迭代法計算n的階乘*/longFac(intn){ inti; longresult=1; if(n<0) { printf("inputdataerror!\n"); } else { for(i=2;i<=n;i++) { result=result*i; } returnresult; }}#include<stdio.h>longFac(intn);intmain(){ intm; longret; printf("pleaseinputm:"); scanf("%d",&m); ret=Fac(m); if(ret==-1) printf("inputdataerror!\n"); else printf(“%d!=%ld",m,ret); return0;}/*用迭代法計算n的階乘*/longFac(intn){ inti; longresult=1; if(n<0) { return-1; } else { for(i=2;i<=n;i++) { result=result*i; } returnresult; }}防御性編程#include<stdio.h>unsignedlongFac(unsignedintn);intmain(){ intm; longret; printf("pleaseinputm:"); scanf("%d",&m); ret=Fac(m); if(ret==-1) printf("inputdataerror!\n"); else printf(“%d!=%ld",m,ret); return0;}/*用迭代法計算n的階乘*/unsignedlongFac(unsignedintn){ unsignedinti; unsignedlongresult=1; if(n<0) { return-1; } else { for(i=2;i<=n;i++) { result=result*i; } returnresult; }}傳入負數(shù)的實參時Fac()會返回-1嗎?存在死代碼的原因何在?防御性編程如何修改程序去除冗余代碼?如何保證不會傳入負數(shù)實參?#include<stdio.h>unsignedlongFac(unsignedintn);intmain(){ intm; longret; printf("pleaseinputm:"); scanf("%d",&m); ret=Fac(m); if(ret==-1) printf("inputdataerror!\n"); else printf(“%d!=%ld",m,ret); return0;}unsignedlongFac(unsignedintn){ unsignedinti; unsignedlongresult=1; for(i=2;i<=n;i++) { result=result*i; } returnresult;}運行結(jié)果:pleaseinputm(m>0):-1pleaseinputm(m>0):55!=120防御性編程【例6.3】
編寫程序,實現(xiàn)組合數(shù)的計算。unsignedlongFac(unsignedintn){ unsignedinti; unsignedlongresult=1; for(i=2;i<=n;i++) { result=result*i; } returnresult;}#include<stdio.h>unsignedlongFac(unsignedintn);intmain(){intm,k;unsignedlongret;do{printf("pleaseinputm,k(m>=k>0):");scanf("%d%d",&m,&k);}while(m<k||m<=0||k<0);ret=Fac(m)/(Fac(k)*Fac(m-k));printf("ret=%lu\n",ret);return0;}函數(shù)設計原則①函數(shù)的規(guī)模要?。虎诤瘮?shù)的功能要單一,不要設計多功能的函數(shù);③在函數(shù)的接口中清楚地定義函數(shù)的行為;④在函數(shù)的入口處,對參數(shù)的有效性進行檢查;⑤應檢查某些敏感性操作;⑥不能主觀地認為調(diào)用一個函數(shù)總會成功,要考慮如果調(diào)用失敗,應該如何處理。函數(shù)嵌套調(diào)用嵌套調(diào)用:在調(diào)用一個函數(shù)的過程中,又調(diào)用另一個函數(shù)C語言規(guī)定函數(shù)不能嵌套定義,但可以嵌套調(diào)用,函數(shù)是相互平行的遞歸函數(shù)■目標:將A上的盤子全部移到B上■規(guī)則:每次只能移動一個盤子,不允許大盤子放在小盤子上第一步:A→B
第二步:A→CABCn=3【例6.4】漢諾塔問題遞歸函數(shù)ABC
第三步:B→C第四步:A→Bn=3遞歸函數(shù)ABC
第五步:C→A第六步:C→Bn=3遞歸函數(shù)ABCn更大些怎么辦?
第七步:A→Bn=3遞歸函數(shù)第1步:將問題簡化假設A桿上只有2個圓盤,即漢諾塔有2層,n=2將1號圓盤從A移到C將2號圓盤從A移到B將1號圓盤從C移到BABC第2步:對于一個有n(n>1)個圓盤的漢諾塔,將n個圓盤分為兩部分:上面n-1個圓盤和最下面的n號圓盤。將“上面n-1個圓盤”看成一個整體將n-1個圓盤從A移到C將n號圓盤從A移到B將n-1個圓盤從C移到BACB遞歸函數(shù)遞歸函數(shù)設計2個函數(shù):將n個圓盤借助C從A移到B
將一個圓盤從A移到B
ACB將n-1個圓盤從A移到C將n號圓盤從A移到B將n-1個圓盤從C移到BHanoi(intn,chara,charb,charcMove(intn,chara,charb);step1Hanoi(n-1,a,c,b)step2Move(n,a,b)Step3Hanoi(n-1,c,b,a)遞歸函數(shù)遞歸方法的基本原理將一個復雜問題逐步分解并最終簡化為一個顯而易見的小問題這個小問題的解決,意味著整個復雜問題的解決
遞歸函數(shù)遞歸函數(shù)【例6.5】
編寫程序,用遞歸法計算整數(shù)x的n次冪xn。longPower(intx,intn) /*函數(shù)定義*/{if(n==0)return1;elsereturnx*Power(x,n-1);}一般情況基線情況遞歸函數(shù)遞歸調(diào)用應該能夠在有限次數(shù)內(nèi)終止遞歸遞歸調(diào)用若不加以限制,將無限循環(huán)調(diào)用必須在函數(shù)內(nèi)部加控制語句,僅當滿足一定條件時,遞歸終止,稱為條件遞歸任何一個遞歸調(diào)用程序必須包括兩部分遞歸循環(huán)繼續(xù)的過程遞歸調(diào)用結(jié)束的過程
if(遞歸終止條件成立)
return遞歸公式的初值;elsereturn遞歸函數(shù)調(diào)用返回的結(jié)果值;
遞歸函數(shù)每個遞歸函數(shù)必須至少有一個基線條件一般情況必須最終能簡化為基線條件遞歸層數(shù)太多易導致??臻g溢出后果很嚴重,程序被異常中止優(yōu)點:從編程角度來看,比較直觀、精煉,邏輯清楚符合人的思維習慣,逼近數(shù)學公式的表示尤其適合非數(shù)值計算領域hanoi塔,騎士游歷、八皇后問題(回溯法)缺點:增加了函數(shù)調(diào)用的開銷,每次調(diào)用都需要進行參數(shù)傳遞、現(xiàn)場保護等耗費更多的時間和棧空間應盡量用迭代形式替代遞歸形式遞歸與迭代的比較變量的作用域與存儲類型什么是變量的作用域?指在源程序中定義變量的位置及其能被讀寫訪問的范圍分為局部變量全局變量局部變量指在函數(shù)或語句塊內(nèi)定義的變量形參也是局部變量特點生存期是該語句塊,進入語句塊時獲得內(nèi)存,僅能由語句塊內(nèi)語句訪問,退出語句塊時釋放內(nèi)存,不再有效定義時不會自動初始化,除非程序員指定初值并列語句塊各自定義的同名變量互不干擾形參和實參可以同名在所有函數(shù)之外定義的變量生存期是整個程序,從程序運行起占據(jù)內(nèi)存,程序運行過程中可隨時訪問,程序退出時釋放內(nèi)存有效范圍是從定義變量的位置開始到本程序結(jié)束全局變量變量的存儲類型指數(shù)據(jù)在內(nèi)存中存儲的方式即編譯器為變量分配內(nèi)存的方式,它決定變量的生存期變量定義格式:存儲類型數(shù)據(jù)類型變量名;C語言的存儲類別auto型(自動變量)static型(靜態(tài)變量)extern型(外部變量)register型(寄存器變量)變量的存儲類型■變量的生成期:決定何時“生”,何時“滅”靜態(tài)存儲區(qū)中的變量:與程序“共存亡”動態(tài)存儲區(qū)中的變量:與所在函數(shù)“共存亡”寄存器中的變量:同動態(tài)存儲區(qū)自動變量與靜態(tài)變量auto
數(shù)據(jù)類型變量名;auto體現(xiàn)在進入函數(shù)/語句塊時自動申請內(nèi)存,退出時自動釋放內(nèi)存動態(tài)局部變量,缺省的存儲類型靜態(tài)變量static
數(shù)據(jù)類型變量名;在語句塊/函數(shù)內(nèi)聲明的靜態(tài)局部變量,其生存期為整個程序生存期為整個程序運行期間自動變量與靜態(tài)變量#include<stdio.h>intf(inta);intmain(){ inta=2,i; for(i=0;i<3;i++) { printf("%d\t",F(a)); } printf("\n"); return0;}intF(inta){ autointb=0; staticintc=3; b++; c++; returna+b+c;}靜態(tài)變量僅初始化一次,變量的值可保存到下次進入函數(shù),使函數(shù)具有記憶功能運行結(jié)果:789自動變量與靜態(tài)變量#include<stdio.h>intf(inta);intmain(){ inta=2,i; for(i=0;i<3;i++) { printf("%d\t",F(a)); } printf("\n"); return0;}intF(inta){ autointb=0; intc=3; b++; c++; returna+b+c;}運行結(jié)果:777靜態(tài)局部變量和全局變量自動初始化為0值。自動變量不初始化時,值是隨機值寄存器變量寄存器CPU內(nèi)部容量有限、但速度極快的存儲器
register
類型名變量名;
使用頻率比較高的變量聲明為register
,可使程序更小、執(zhí)行速度更快現(xiàn)代編譯器有能力自動把普通變量優(yōu)化為寄存器變量,并且可以忽略用戶的指定所以一般無需特別聲明變量為register
變量的作用域與存儲類型小結(jié)全局變量靜態(tài)外部變量(只限本文件使用)外部變量
(非靜態(tài)外部變量允許其他文件引用)局部變量
自動變量,(離開函數(shù),值就消失)寄存器變量(離開函數(shù),值就消失)定義點之前使用,需用extern聲明靜態(tài)局部變量(離開函數(shù),值仍保留)動態(tài)局部變量模塊化程序設計功能分解自頂向下、逐步求精的過程模塊分解的基本原則保證模塊的相對獨立性——高聚合、低耦合模塊的實現(xiàn)細節(jié)對外不可見——信息隱藏外部:關心做什么;內(nèi)部:關心怎么做設計好模塊接口接口指羅列出一個模塊的所有的與外部打交道的變量等定義好后不要輕易改動在模塊開頭(文件的開頭)進行函數(shù)聲明模塊化程序設計逐步求精(StepwiseRefinement)由不斷的自底向上修正所補充的自頂向下(Top-down)的程序設計方法模塊化程序設計模塊各司其職每個模塊只負責一件事情,它可以更專心便于進行單個模塊的設計、開發(fā)、調(diào)試、測試和維護等工作一個模塊一個模塊地完成,最后再將它們集成開發(fā)人員各司其職按模塊分配任務,職責明確并行開發(fā),縮短開發(fā)時間什么時候需要模塊化?某一功能,如果重復實現(xiàn)3遍以上,即應考慮模塊化,將它寫成通用函數(shù),并向小組成員發(fā)布模塊化程序設計模塊化的優(yōu)點——復用構(gòu)建新的軟件系統(tǒng)可以不必每次從零做起,直接使用已有的經(jīng)過反復驗證的軟構(gòu)件,組裝或加以合理修改后成為新的系統(tǒng),提高軟件生產(chǎn)率和程序質(zhì)量在其他函數(shù)的基礎上構(gòu)造程序拿來拿去主義,指盡可能復用其他人現(xiàn)成的模塊不是人類懶惰的表現(xiàn),而是智慧的表現(xiàn)一般要靠日積月累才能建立可以被復用的軟件庫前期投入多,缺乏近期效益,大部分公司都注重近期效益,是為了生存,所以軟件復用對公司來說不是最高優(yōu)先級【例6.6】模塊化設計拋硬幣游戲猜硬幣正反面,10次猜不對就猜下一個數(shù)模塊分解過程開始結(jié)束初始化退出處理主功能為程序運行所做的準備工作在退出前要做的事情,如打印結(jié)果、資源釋放等自底向上自頂向下的模塊化程序設計模塊化設計拋硬幣游戲開始結(jié)束生成硬幣猜正反面intmain(){intcoin;charreply;srand((unsigned)time
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 山東力明科技職業(yè)學院《食品貯藏與保鮮》2023-2024學年第一學期期末試卷
- 山東經(jīng)貿(mào)職業(yè)學院《教師口語一》2023-2024學年第一學期期末試卷
- 山東交通職業(yè)學院《廣告策劃與設計》2023-2024學年第一學期期末試卷
- 山東華宇工學院《數(shù)值計算方法》2023-2024學年第一學期期末試卷
- 山東海事職業(yè)學院《土地調(diào)查與評價》2023-2024學年第一學期期末試卷
- 山東管理學院《化工環(huán)保與安全》2023-2024學年第一學期期末試卷
- 山東工業(yè)職業(yè)學院《教育學(英語)》2023-2024學年第一學期期末試卷
- 2024年年園區(qū)物業(yè)合作協(xié)議書
- 幼兒侏羅紀主題課程設計
- 旋流沉砂池課程設計
- 第二屆全國技能大賽珠寶加工項目江蘇省選拔賽技術工作文件
- 淮陰工學院《供應鏈管理3》2022-2023學年第一學期期末試卷
- 2025年計算機等級考試一級計算機基礎及MS Office應用試卷及解答參考
- 小學五年級上冊語文 第一單元 語文要素閱讀(含解析)
- 2024年廣東公需科目答案
- ABB工業(yè)機器人基礎知識
- 中國校服產(chǎn)業(yè)挑戰(zhàn)與機遇分析報告 2024
- 監(jiān)理企業(yè)技術管理制度
- 2022版義務教育物理課程標準
- 山東省日照市2023-2024學年七年級上學期期末數(shù)學試題(含答案)
- 上海華東師大二附中2025屆高一數(shù)學第一學期期末檢測試題含解析
評論
0/150
提交評論