版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
第三章
函數(shù)東南大學(xué)
生物科學(xué)與醫(yī)學(xué)工程學(xué)院夏小俊東南大學(xué)生物科學(xué)與醫(yī)學(xué)工程學(xué)院夏小俊C++中的函數(shù)函數(shù)的概念與自定義函數(shù)函數(shù)的調(diào)用和聲明變量的作用域與生存期函數(shù)的遞歸與嵌套函數(shù)的其它特性編譯預(yù)處理C++中的函數(shù)函數(shù)的概念與自定義函數(shù)函數(shù)的調(diào)用和聲明變量的作3.1函數(shù)的概念與意義任何c++程序由至少一個函數(shù)(function)組成,其中main函數(shù)是必不可少的。函數(shù)除了是程序的基本組成部分之外,更重要的是可以完成特定的功能。為了完成特定的功能,函數(shù)需要數(shù)據(jù)的輸入(參數(shù)),并給出數(shù)據(jù)的結(jié)果(返回值)。通過編寫和調(diào)用函數(shù)可以簡化程序邏輯,提高編碼效率。3.1函數(shù)的概念與意義任何c++程序由至少一個函數(shù)(fun子模塊1子模塊2子模塊n功能模塊1功能模塊2功能模塊n……………………軟件項目C++程序C++函數(shù)搭積木子模塊1子模塊2子模塊n功能模塊1功能模塊2功能模塊n………系統(tǒng)函數(shù)與自定義函數(shù)之前用過的sqrt()等函數(shù)并不需要我們?nèi)ゾ帉懞退伎紝崿F(xiàn)。類似這樣由系統(tǒng)提供的函數(shù),我們稱為系統(tǒng)函數(shù)或庫函數(shù)。使用系統(tǒng)函數(shù)可以大大提高我們的編程效率,但它并不能覆蓋所有的需求。因此我們需要學(xué)習(xí)自己編寫函數(shù),也就是自定義函數(shù)。編寫自定義函數(shù)是結(jié)構(gòu)化(模塊化)程序設(shè)計的主要步驟。系統(tǒng)函數(shù)與自定義函數(shù)之前用過的sqrt()等函數(shù)并不需要我們函數(shù)的參數(shù)和返回值回憶之前使用函數(shù)的例子,如sqrt()。使用該函數(shù)時,需要一個輸入的值,并得到對應(yīng)的輸出,如y=sqrt(x)。所以對于函數(shù)sqrt,需要一個類型為double的參數(shù)(輸入),并提供一個類型為double的返回值(輸出)。函數(shù)的參數(shù)和返回值回憶之前使用函數(shù)的例子,如sqrt()。自定義函數(shù)的三部曲分析函數(shù)的參數(shù)(個數(shù)、類型)分析函數(shù)的返回值(類型)實現(xiàn)從參數(shù)得到返回值的過程自定義函數(shù)的三部曲分析函數(shù)的參數(shù)(個數(shù)、類型)分析函數(shù)的返回第一個自定義函數(shù)max函數(shù)功能:求兩個整數(shù)當(dāng)中較大的數(shù)。函數(shù)邏輯:使用判斷語句即可。參數(shù)分析:需要兩個參數(shù),都是整數(shù)類型。返回值分析:結(jié)果返回一個整數(shù)。第一個自定義函數(shù)max函數(shù)功能:求兩個整數(shù)當(dāng)中較大的數(shù)。自定義函數(shù)的語法格式返回值類型函數(shù)名(函數(shù)參數(shù)列表)//函數(shù)頭 { //函數(shù)體
return返回值; }函數(shù)參數(shù):數(shù)量為任意個,如果為0可以省略;返回值說明:只能為0個或1個,用關(guān)鍵詞return實現(xiàn)。如果沒有返回值,返回類型用void表示。自定義函數(shù)的語法格式返回值類型函數(shù)名(函數(shù)參數(shù)列表)//第一個自定義函數(shù)max
intmax(inta,intb)//每一個參數(shù)獨立 {
intc=a>b?a:b;
returnc;//通過該語句返回結(jié)果 }第一個自定義函數(shù)max intmax(inta,in例:無參無返回值函數(shù)print
voidprint(void)//參數(shù)的void可省略 {
cout<<"*********"<<endl;
cout<<"*example*"
<<endl;cout<<"*********"<<endl; }//本函數(shù)僅僅實現(xiàn)打印的功能,無數(shù)據(jù)處理例:無參無返回值函數(shù)print voidprint(vo例:求最大公約數(shù)的函數(shù)gcd函數(shù)功能:求兩個整數(shù)的最大公約數(shù)。函數(shù)邏輯:使用遞推算法(歐幾里得算法)或窮舉法皆可。參數(shù)分析:需要兩個參數(shù),都是整數(shù)類型。返回值分析:結(jié)果返回一個整數(shù)。例:求最大公約數(shù)的函數(shù)gcd函數(shù)功能:求兩個整數(shù)的最大公約數(shù)遞推法實現(xiàn)函數(shù)gcd
intgcd(inta,intb)//注意分析返回和參數(shù)類型 {
intc=a%b;//c是a除以b的余數(shù)
while(c!=0)//歐幾里得算法遞推求解 { a=b; b=c; c=a%b; }
returnb;//返回最后的結(jié)果 }遞推法實現(xiàn)函數(shù)gcd intgcd(inta,int窮舉法實現(xiàn)函數(shù)gcd
intgcd(inta,intb)//與上例相同 {
intc=a<b?a:b;//二者中較小的數(shù)
while(a%c!=0||b%c!=0)//嘗試 --c;
returnc;//得到結(jié)果 }窮舉法實現(xiàn)函數(shù)gcd intgcd(inta,int函數(shù)定義小結(jié)1、分析清楚函數(shù)所需的參數(shù)和能提供的返回值至關(guān)重要。2、在函數(shù)實現(xiàn)過程中需要的輔助變量,不能作為參數(shù)來使用,只能定義在函數(shù)的內(nèi)部。3、遇到return語句之后函數(shù)自動結(jié)束,因此一般將return語句放在函數(shù)的最后。4、思考和嘗試將常用算法改造為函數(shù)實現(xiàn),如判斷某數(shù)是否為素數(shù)、完全數(shù)等,并體會這樣做的好處。函數(shù)定義小結(jié)1、分析清楚函數(shù)所需的參數(shù)和能提供的返回值至關(guān)重3.2函數(shù)的調(diào)用和聲明主調(diào)函數(shù)將參數(shù)傳遞給自定義函數(shù)運行自定義函數(shù)體自定義函數(shù)將返回值回傳給主調(diào)函數(shù)3.2函數(shù)的調(diào)用和聲明主調(diào)函數(shù)將參數(shù)傳遞給自定義函數(shù)運行自函數(shù)的調(diào)用過程主調(diào)函數(shù)將參數(shù)(實際參數(shù))傳遞給自定義函數(shù),并暫停主調(diào)函數(shù)的運行;自定義函數(shù)根據(jù)得到的參數(shù)(形式參數(shù))值進行計算,并得出返回值結(jié)果;自定義函數(shù)將返回值回傳給主調(diào)函數(shù),結(jié)束自定義函數(shù)并繼續(xù)主調(diào)函數(shù)的運行。函數(shù)的調(diào)用過程主調(diào)函數(shù)將參數(shù)(實際參數(shù))傳遞給自定義函數(shù),并函數(shù)的三種調(diào)用情況系統(tǒng)函數(shù):包含所在的頭文件自定義函數(shù):定義之前,可直接調(diào)用自定義函數(shù):定義之后,需補充聲明函數(shù)的三種調(diào)用情況系統(tǒng)函數(shù):包含所在的頭文件自定義函數(shù):定義函數(shù)的聲明從結(jié)構(gòu)化程序設(shè)計的角度,通常是先調(diào)用后定義。而使用函數(shù)聲明,符合由粗到精的思維方式,又滿足了語法要求。函數(shù)聲明是將函數(shù)頭添加分號而構(gòu)成的語句,并且參數(shù)名可以省略。部分函數(shù)聲明示例
intmax(inta,intb); voidprint(void);
intgcd(int,int);//這里省略了參數(shù)名函數(shù)的聲明從結(jié)構(gòu)化程序設(shè)計的角度,通常是先調(diào)用后定義。而使用例:函數(shù)先定義后調(diào)用
intmax(inta,intb) {
intc=a>b?a:b; returnc;}
intmain(){
doublex=5.2,y=3.9; cout<<max(5,3);//實參是常量 cout<<max(x,y);//實參是變量,且兼容 cout<<max(x+y,x-y);//實參是表達式且兼容
return0;}例:函數(shù)先定義后調(diào)用 intmax(inta,int intmax(inta,intb);//本聲明必不可少!
intmain(){ intx=5,y=3; cout<<max(5,3);//實參是常量 cout<<max(x,y);//實參是變量 cout<<max(x+y,x-y);//實參是表達式
return0;}
intmax(inta,intb) {
intc=a>b?a:b; returnc; }例:函數(shù)先調(diào)用后定義 intmax(inta,intb);//本聲明函數(shù)的參數(shù)傳遞(傳值調(diào)用)兩種參數(shù):實際參數(shù)(實參)和形式參數(shù)(形參)。傳遞過程是:先計算實參表達式的值,再將該值傳遞給對應(yīng)的形參變量。實參和形參的個數(shù)和排列順序應(yīng)一一對應(yīng),并且對應(yīng)參數(shù)應(yīng)類型匹配(賦值兼容)。實參可以是常量、變量或表達式,形參只能是變量。函數(shù)的參數(shù)傳遞(傳值調(diào)用)兩種參數(shù):實際參數(shù)(實參)和形式參實參與形參的單向傳遞如前所述,在函數(shù)調(diào)用的過程中,實參將值傳遞給形參。形參具備自己的存儲空間,和實參的關(guān)系是單向傳遞關(guān)系。對形參的賦值不會影響對應(yīng)的實參!除了這種單向的傳值調(diào)用之外,第5章還將介紹雙向的傳引用調(diào)用方式。實參與形參的單向傳遞如前所述,在函數(shù)調(diào)用的過程中,實參將值傳例:用函數(shù)實現(xiàn)數(shù)據(jù)交換
voidmyswap(int
,
int);//全局函數(shù)聲明
int
main(){
int
a
,
b; cin>>a>>b; cout<<"main:"<<a<<''<<b<<endl; myswap(a,b);//傳值
cout<<"main:"<<a<<''<<b<<endl;}例:用函數(shù)實現(xiàn)數(shù)據(jù)交換 voidmyswap(int,例:用函數(shù)實現(xiàn)數(shù)據(jù)交換voidmyswap(intx,inty){cout<<"myswap:"<<x<<''<<y<<endl;
intt=x;x=y;y=t; cout<<"myswap:"<<x<<''<<y<<endl;}例:用函數(shù)實現(xiàn)數(shù)據(jù)交換voidmyswap(intx,函數(shù)myswap運行結(jié)果分析
輸入兩整數(shù):35 main:35//輸出原始的結(jié)果 myswap:35//實參將值傳遞給形參 myswap:53//形參的交換成功 main:35
//實參的交換失??!函數(shù)myswap運行結(jié)果分析 輸入兩整數(shù):35函數(shù)返回值return表達式;用來返回函數(shù)的結(jié)果。如果該函數(shù)的返回類型不為void,那么函數(shù)的調(diào)用可以組成函數(shù)調(diào)用表達式參與運算。
例:cout<<max(a,b); max(max(a,b),c);如果該函數(shù)的返回類型為void,那么函數(shù)的調(diào)用只能加上分號成為函數(shù)語句。
例:print();函數(shù)返回值return表達式;用來返回函數(shù)的結(jié)果。return語句的操作本質(zhì)當(dāng)函數(shù)中運行到return語句的時候,將return后面表達式的值傳給指定類型的臨時變量;臨時變量僅在函數(shù)表達式內(nèi)有效,因此函數(shù)表達式一般不為左值,如max(a,b)=2是非法的;如果return后面表達式的類型和函數(shù)定義的返回類型不一致,以定義類型為準(zhǔn)進行轉(zhuǎn)換。
return語句的操作本質(zhì)當(dāng)函數(shù)中運行到return語句的時例:三角形面積求解函數(shù)float
TriangleArea(floata,float
b,floatc){
if((a+b<=c)||(a+c<=b)||(b+c<=a)) return-1;
floats=(a+b+c)/2;
return
sqrt(s*(s-a)*(s-b)*(s-c))
;}例:三角形面積求解函數(shù)floatTriangleArea(
intmain(){
floata,b,c,area; cout<<"輸入三角形三邊a,b,c:"<<endl; cin>>a>>b>>c;
area=TriangleArea(a,b,c);
if(area==-1) cout<<"不能構(gòu)成三角形!"<<endl;
else
cout<<"面積為:"<<area<<endl;
return
0;} intmain(){3.3變量的作用域和生存期變量除了具備類型、名字和值之外,還有空間和時間上的特性,也被稱為變量的作用域和生存期。根據(jù)作用域和生存期的不同,可對變量進行不同形式的分類。3.3變量的作用域和生存期變量除了具備類型、名字和值之外,C++的內(nèi)存分布代碼區(qū):存放程序代碼指令堆區(qū):存儲動態(tài)數(shù)據(jù)棧區(qū):存放局部變量全局?jǐn)?shù)據(jù)區(qū):存放全局和靜態(tài)變量C++的內(nèi)存分布代碼區(qū):存放程序代碼指令堆區(qū):存儲動態(tài)數(shù)據(jù)棧變量的存儲機制(*)代碼區(qū)(Codearea):存放程序代碼,即程序中各個函數(shù)的代碼塊;全局?jǐn)?shù)據(jù)區(qū)(Dataarea):存放全局?jǐn)?shù)據(jù)和靜態(tài)數(shù)據(jù);分配該區(qū)時內(nèi)存全部清零,變量的所有字節(jié)自動初始化為零。棧區(qū)(Stackarea):存放局部變量,如函數(shù)中的變量等;分配棧區(qū)時不處理內(nèi)存,即變量取隨機值。堆區(qū),自由存儲區(qū)(Freestorearea):存放與指針相關(guān)的動態(tài)數(shù)據(jù)。變量的存儲機制(*)代碼區(qū)(Codearea):存放程序代變量的作用域與生存期C++中的變量除了有數(shù)據(jù)類型的區(qū)別之外,還具備作用域(空間)和生存期(時間)的屬性。根據(jù)作用域的不同,將變量分為全局變量和局部變量。根據(jù)生存期的不同,將變量分為靜態(tài)變量和動態(tài)變量。變量的作用域與生存期C++中的變量除了有數(shù)據(jù)類型的區(qū)別之外,全局變量如果一個變量定義的位置不在任何函數(shù)(復(fù)合語句)內(nèi),則該變量成為全局變量。全局變量的作用域:由定義處開始,到所在文件尾部結(jié)束,因此也稱為文件作用域。一般情況下,將全局文件定義在文件的開頭部分,則所有函數(shù)中都可以對全局變量進行讀寫。全局變量如果一個變量定義的位置不在任何函數(shù)(復(fù)合語句)內(nèi),則例:全局變量的使用
intn=100;
voidfunc(){ n*=2; }
intmain() { n*=2; cout<<n<<endl;//輸出200 func(); cout<<n<<endl;//輸出400
return0; }例:全局變量的使用 intn=100;全局變量的說明全局變量可以被多個函數(shù)同時使用,因此可以用來做數(shù)據(jù)交換和共享的用途(例如:用來統(tǒng)計遞歸函數(shù)的運行次數(shù))。全局變量的使用應(yīng)盡量謹(jǐn)慎,過多地使用容易導(dǎo)致邏輯和流程的混亂。全局變量的存儲地點在內(nèi)存的全局?jǐn)?shù)據(jù)區(qū),如不賦初始值則自動初始化為0。全局變量的說明全局變量可以被多個函數(shù)同時使用,因此可以用來做局部變量之前所有的變量都是局部變量,其特點是變量定義在某個特定的函數(shù)內(nèi)。與函數(shù)的情況類似,如果一個變量定義在某復(fù)合語句(塊)內(nèi),則該變量成為此復(fù)合語句的局部變量。局部變量的作用域:從變量定義開始,到所在的函數(shù)(復(fù)合語句)的尾部結(jié)束,也稱為塊域。局部變量的存儲地點在內(nèi)存的棧區(qū)。局部變量之前所有的變量都是局部變量,其特點是變量定義在某個特作用域的覆蓋問題問:屬于不同函數(shù)的局部變量允許重名嗎?全局變量和局部變量可以重名嗎?不同層次的局部變量可以重名嗎?答:都允許。在作用域覆蓋的區(qū)域內(nèi),遵循“局部優(yōu)先”的規(guī)則。另外,如果局部變量覆蓋了全局變量,可以使用域作用符::調(diào)用同名全局變量。作用域的覆蓋問題問:屬于不同函數(shù)的局部變量允許重名嗎?全局變例:變量的作用域覆蓋
intn=100;
int
main(){inti=200,j=300; cout<<n<<'\t'<<i<<'\t'<<j<<endl; { inti=500,j=600,n;n=i+j; cout<<n<<'\t'<<i<<'\t'<<j<<endl;
cout<<::n<<endl;//輸出全局變量n
} n=i+j; //修改全局變量 cout<<n<<'\t'<<i<<'\t'<<j<<endl;
return0; }例:變量的作用域覆蓋 intn=100;作用域的總結(jié)根據(jù)變量定義時的位置不同,將其分為全局變量和局部變量。全局變量可以被所有函數(shù)(塊)訪問,而局部變量只能在該函數(shù)(塊)內(nèi)被訪問。全局變量和局部變量可以重名,并遵循局部優(yōu)先的規(guī)則。還有一種作用域:局部聲明作用域,其作用范圍僅限聲明語句內(nèi),因此可省略其參數(shù)名。作用域的總結(jié)根據(jù)變量定義時的位置不同,將其分為全局變量和局部變量的生存期動態(tài)變量:當(dāng)程序運行至變量所在的函數(shù)(塊)的時候,系統(tǒng)對其進行空間分配;當(dāng)所在的函數(shù)(塊)運行結(jié)束時,系統(tǒng)收回其存儲空間。之前使用的局部變量一般就屬于動態(tài)變量。靜態(tài)變量:當(dāng)程序開始運行的時候,變量即被創(chuàng)建,并一直生存至程序的結(jié)束。之前的全局變量即為靜態(tài)變量。另可改造普通局部變量的屬性,使其成為靜態(tài)局部變量。
不同生存期的變量,用存儲類型的不同來體現(xiàn)。變量的生存期動態(tài)變量:當(dāng)程序運行至變量所在的函數(shù)(塊)的時候變量的存儲類型變量定義的完整方式
存儲類型
數(shù)據(jù)類型
變量名=初始值;C++中支持4種不同的存儲類型:auto、register、extern和static。auto類型是局部變量的默認(rèn)存儲類型,extern是全局變量的默認(rèn)存儲類型。說明:最新版本的C++當(dāng)中對auto的定義已經(jīng)有所變化!變量的存儲類型變量定義的完整方式變量的存儲類型auto:普通的局部變量都屬于auto類型,也稱為自動變量,屬于默認(rèn)類別因此可省略。
例:intc和auto
intc是等價的。register:用該類型修飾的變量稱為寄存器變量,其使用方式與auto變量幾乎一致,區(qū)別在于其存儲的位置在CPU的寄存器當(dāng)中。(不可尋址,但已不推薦使用)auto和register變量統(tǒng)稱動態(tài)變量。變量的存儲類型auto:普通的局部變量都屬于auto類型,也變量的存儲類型static:用static修飾的變量具備靜態(tài)屬性,可分為局部靜態(tài)變量和全局靜態(tài)變量。局部靜態(tài)變量的作用域不變。當(dāng)其所在的塊第一次被執(zhí)行時,系統(tǒng)在全局?jǐn)?shù)據(jù)區(qū)開辟其空間,直到整個程序結(jié)束才釋放。局部靜態(tài)變量具有局部作用域,但卻具有全局生命期。局部靜態(tài)變量如果不初始化,系統(tǒng)初始化為0。變量的存儲類型static:用static修飾的變量具備靜態(tài)例:局部靜態(tài)變量
int
st(){
static
intt=100;//僅執(zhí)行一次! t++;returnt;}
intat(){ intt=100;//自動變量
t++;returnt;}
intmain(){ inti;
for(i=0;i<5;i++)cout<<at()<<'\t'; cout<<endl;
for(i=0;i<5;i++)cout<<st()<<'\t';cout<<endl;
return0;}例:局部靜態(tài)變量 intst(){ staticint變量的存儲類型extern:用extern修飾的變量也稱為外部變量,是全局變量的默認(rèn)存儲類型。外部變量具備靜態(tài)變量的生存期屬性,即程序開始時分配空間,程序結(jié)束時其空間被銷毀。這里“外部”的含義是指全局變量可以被同工程下的其他文件調(diào)用,其方法是用extern語句進行聲明即可。變量的存儲類型extern:用extern修飾的變量也稱為外例:外部變量的使用,文件1
voidfun2();//外部函數(shù)聲明
intn; //全局變量定義
intmain(){ n=1; fun2(); //fun2()定義在文件2中 cout<<″n=″<<n<<endl;
return0;}例:外部變量的使用,文件1 voidfun2();//外例:外部變量的使用,文件2
extern
int
n;
//外部變量聲明
void
fun2() {
//fun2()被文件1調(diào)用 n=3; }
運行結(jié)果:n=3例:外部變量的使用,文件2 externintn;//外部變量的定義與聲明(*)用extern修飾符既可以聲明外部變量,也可以定義外部變量。定義外部變量需要分配空間,而聲明變量的作用是拓寬其作用域。外部變量的定義和聲明的區(qū)別(*):跨文件時,省略extern的為定義語句,顯式書寫的為聲明語句;跨文件時,如同時顯式書寫extern,有初始化的為定義語句,無初始化的為聲明語句;在單文件內(nèi),也可以用extern聲明語句,拓寬外部變量的作用域。
外部變量的定義與聲明(*)用extern修飾符既可以聲明外部extern的用法對比(*)externinta=3;//此處是定義,但不推薦externinta;//此處是聲明,不能單獨使用inta;//此處是定義,等價于externinta=0inta=0;//效果同上extern的用法對比(*)靜態(tài)全局變量全局變量本已經(jīng)具備靜態(tài)屬性:存放在全局?jǐn)?shù)據(jù)區(qū)內(nèi),生存期限為整個程序期間,并默認(rèn)初始化為0等。用static修飾全局變量,其作用是將該變量的作用域限定在文件內(nèi),不能為其他文件調(diào)用。總結(jié):用static修飾局部變量和全局變量的意義和作用是完全不同的。靜態(tài)全局變量全局變量本已經(jīng)具備靜態(tài)屬性:存放在全局?jǐn)?shù)據(jù)區(qū)內(nèi),作用域和生存期內(nèi)容總結(jié)根據(jù)變量定義的位置,區(qū)分為局部變量和全局變量。局部變量屬于某個塊,全局變量屬于某個文件。根據(jù)變量的生存期限,區(qū)分為動態(tài)變量和靜態(tài)變量。動態(tài)變量的生存期為其所屬的塊的運行期間,而靜態(tài)變量的生存期則大大延長且默認(rèn)初始化為0。作用域和生存期內(nèi)容總結(jié)根據(jù)變量定義的位置,區(qū)分為局部變量和全作用域和生存期內(nèi)容總結(jié)局部變量的存儲類型屬性默認(rèn)為動態(tài)(auto),但可以用static修飾為靜態(tài)局部變量,其作用是延長其生存期。對靜態(tài)局部變量的使用理解是本節(jié)需要重點考察的內(nèi)容。全局變量的存儲類型屬性默認(rèn)為外部(extern)變量,其性質(zhì)是靜態(tài)的且默認(rèn)可以被別的文件調(diào)用??梢杂胹tatic修飾為靜態(tài)全局變量,其意義是限定只能在該文件內(nèi)使用。作用域和生存期內(nèi)容總結(jié)局部變量的存儲類型屬性默認(rèn)為動態(tài)(au作用域和生存期概念總結(jié)概念作用域生存期說明普通局部變量所在的塊當(dāng)塊運行的時候適用大多數(shù)變量,也稱自動(auto)變量。靜態(tài)局部變量所在的塊第一次運行至程序結(jié)束存儲類型static普通全局變量定義至文件結(jié)束整個程序可被其他文件引用,稱普通外部(extern)變量靜態(tài)全局變量定義至文件結(jié)束整個程序只能在本文件使用,也稱靜態(tài)外部(extern)變量作用域和生存期概念總結(jié)概念作用域生存期說明普通局部變量所在的3.4函數(shù)的嵌套和遞歸在C++中所有的函數(shù)地位是平等的,也就是說不允許嵌套定義,即將函數(shù)A定義在函數(shù)B當(dāng)中。嵌套調(diào)用是允許的,也就是在函數(shù)A中調(diào)用在函數(shù)B。main函數(shù)的特權(quán):1)不允許被其他函數(shù)調(diào)用,2)是程序運行的起點和終點。3.4函數(shù)的嵌套和遞歸在C++中所有的函數(shù)地位是平等的,也函數(shù)的遞歸如果在定義函數(shù)A中的過程中調(diào)用函數(shù)A,則稱為直接遞歸調(diào)用;如果在定義函數(shù)A中調(diào)用函數(shù)B,在定義函數(shù)B中調(diào)用函數(shù)A,則稱為間接遞歸。遞歸的思想在計算機科學(xué)當(dāng)中非常重要,在生活當(dāng)中也有著非常廣泛的應(yīng)用,也是哲學(xué)中“整體與局部”辯證關(guān)系的體現(xiàn)。函數(shù)的遞歸如果在定義函數(shù)A中的過程中調(diào)用函數(shù)A,則稱為直接遞遞歸算法的概念遞歸是一種描述問題的方法,或稱算法。遞歸的思想可以簡單地描述為“自己調(diào)用自己”。遞歸算法的概念遞歸是一種描述問題的方法,或稱算法。例:用遞歸來實現(xiàn)階乘求解
intfac(intn) {
if(n==0||n==1)//遞歸終止條件
return1;
else
returnn*fac(n-1);//遞歸進行條件 }例:用遞歸來實現(xiàn)階乘求解 intfac(intn)fac函數(shù)的運行分析以fac(5)為例: 1)n=5,返回的結(jié)果為5*fac(4)。在fac(4)得出結(jié)果前,函數(shù)無法結(jié)束,程序轉(zhuǎn)入執(zhí)行fac(4)。 2)n=4,返回的結(jié)果為4*fac(3)。在fac(3)得出結(jié)果前,函數(shù)無法結(jié)束,程序轉(zhuǎn)入執(zhí)行fac(3)。 …… 5)n=1,此時得出結(jié)果為1,至此分解部分結(jié)束,遞歸終止。fac函數(shù)的運行分析以fac(5)為例:fac函數(shù)的運行分析 6)在確認(rèn)fac(1)的值之后,fac(2)的結(jié)果也可以確定為2*1=2。 7)在確認(rèn)fac(2)的值之后,fac(3)的結(jié)果也可以確定為3*2=6。 …… 9)在確認(rèn)fac(4)的值之后,fac(5)的結(jié)果最終確定為5*24=120,此時綜合部分結(jié)束,運行完畢。fac函數(shù)的運行分析 6)在確認(rèn)fac(1)的值之后,fa例:遞歸函數(shù)求解費波納切數(shù)列
intfib(intn)//求解第n項的數(shù)列值 {
if(n==1||n==2)//遞歸終止條件
return1;
else
returnfib(n-1)+fib(n-2);//遞歸條件 }//自行嘗試分析fib(5)的運行過程例:遞歸函數(shù)求解費波納切數(shù)列 intfib(intn)遞歸函數(shù)的使用說明遞歸函數(shù)的執(zhí)行分為“遞推”和“回歸”兩個過程。這兩個過程由遞歸終止條件控制,即逐層遞推,直至遞歸終止條件,然后逐層回歸。編寫遞歸函數(shù)的大致模式:首先判斷遞歸終止條件,如果不終止則展開遞歸條件。遞歸函數(shù)容易編寫且可讀性高,但運行效率極低(空間和時間開銷都很大),應(yīng)避免隨意使用。遞歸函數(shù)的使用說明遞歸函數(shù)的執(zhí)行分為“遞推”和“回歸”兩個過例:用遞歸函數(shù)分解整數(shù)voidbackward(intn){
cout<<n%10; if(n<10)
return; else
backward(n/10);}例:用遞歸函數(shù)分解整數(shù)voidbackward(intn例:分解函數(shù)的其他寫法
voidbackward(intn) {
if(n>0) { cout<<n%10; backward(n/10); }}例:分解函數(shù)的其他寫法 voidbackward(int進一步理解遞歸
voidbackward(intn) {
if(n>0) { backward(n/10); //這兩句的順序相反 cout<<n%10; //有什么影響嗎? }}//如調(diào)用backward(123)就顯示123進一步理解遞歸 voidbackward(intn)例:用函數(shù)實現(xiàn)進制轉(zhuǎn)化
voidtrans(intn,intmod)//將n轉(zhuǎn)換為mod進制 {
if(n>0) { trans(n/mod,mod); cout<<hex<<n%mod;//假定不超過16進制 } }例:用函數(shù)實現(xiàn)進制轉(zhuǎn)化 voidtrans(intn,i例:漢諾塔問題有A、B、C三根柱子,A柱上有n個大小不等的盤子,大盤在下,小盤在上。要求將所有盤子由A柱搬動到C柱上,每次只能搬動一個盤子,搬動過程中可以借助任何一根柱子,但必須滿足大盤在下,小盤在上。打印出搬動的步驟。A柱B柱C柱例:漢諾塔問題有A、B、C三根柱子,A柱上有n個大小不等的盤例:漢諾塔問題1、A柱只有一個盤子的情況:A柱C柱;2、A柱有兩個盤子的情況:小盤A柱B柱,大盤A柱C柱,小盤B柱C柱。3、A柱有n個盤子的情況:將此問題看成上面n-1個盤子和最下面第n個盤子的情況。n-1個盤子A柱B柱,第n個盤子A柱C柱,n-1個盤子B柱C柱。問題轉(zhuǎn)化成搬動n-1個盤子的問題,同樣,將n-1個盤子看成上面n-2個盤子和下面第n-1個盤子的情況,進一步轉(zhuǎn)化為搬動n-2個盤子的問題,……,類推下去,一直到最后成為搬動一個盤子的問題。例:漢諾塔問題1、A柱只有一個盤子的情況:A柱C柱;例:漢諾塔問題1、n-1個盤子A柱B柱,借助于C柱;2、第n個盤子A柱C柱;3、n-1個盤子B柱C柱,借助于A柱;其中步驟1和步驟3繼續(xù)遞歸下去,直至搬動一個盤子為止。由此,可以定義兩個函數(shù),一個是遞歸函數(shù),命名為hanoi(intn,charsource,chartemp,chartarget),實現(xiàn)將n個盤子從源柱source借助中間柱temp搬到目標(biāo)柱target;另一個命名為move(charsource,chartarget),用來輸出搬動一個盤子的提示信息。例:漢諾塔問題1、n-1個盤子A柱B柱,借助于C柱;
voidmove(char
source,chartarget){ cout<<source<<"->"<<target<<endl;}
voidhanoi(intn,charsource,chartemp,char
target){ if(n==1)move(source,target);
else{
hanoi(n-1,source,target,temp);//將n-1個盤子搬到中間柱
move(source,target);
//將最后一個盤子搬到目標(biāo)柱
hanoi(n-1,temp,source,target);//將n-1個盤子搬到目標(biāo)柱
}}
intmain(){
intn; cout<<"輸入盤子數(shù):"<<endl; cin>>n; hanoi(n,'A','B','C');
return0;} voidmove(charsource,charta例:遞歸算法求解公約數(shù)
intcgd(intx,inty) {
if(x%y==0)
returny;
returncgd(y,x%y); }例:遞歸算法求解公約數(shù) intcgd(intx,int遞推算法和遞歸函數(shù)一般情況下,遞推算法都可以改造為遞歸函數(shù)來完成,如求解費波納切數(shù)列或求解公約數(shù)。反之則未必可行。遞推算法效率極高,但可讀性較差;遞歸函數(shù)可讀性一般都很好,但運行效率很差。在實際工程應(yīng)用中,盡量避免使用遞歸的辦法。參考:豐田公司的教訓(xùn)/bbs/viewthread.php?tid=19640112遞推算法和遞歸函數(shù)一般情況下,遞推算法都可以改造為遞歸函數(shù)來3.6函數(shù)的其它特性:重載函數(shù)的重載是指一組函數(shù),它們名字相同而參數(shù)不同(個數(shù)或類型不同)。重載是類的實現(xiàn)當(dāng)中的必備功能,也是編寫參數(shù)化和大規(guī)模程序的基本要求。僅返回類型不同,不能構(gòu)成重載。3.6函數(shù)的其它特性:重載函數(shù)的重載是指一組函數(shù),它們名字重載問題的示例考慮如下的三個函數(shù)聲明: intsum(inta,intb); doublesum(doublea,doubleb); float
sum(floata,floatb,floatc);分析:這三個函數(shù)功能相近,所以取了同樣的名字;但它們各自的參數(shù)不同,這樣系統(tǒng)才能決定匹配哪個函數(shù)去運行。重載問題的示例考慮如下的三個函數(shù)聲明:函數(shù)重載的匹配規(guī)則當(dāng)某個函數(shù)中調(diào)用到重載函數(shù)時,編譯器會根據(jù)實參的類型去對應(yīng)地調(diào)用相應(yīng)的函數(shù)。
匹配過程按如下步驟進行: 1、如果有嚴(yán)格匹配的函數(shù),就調(diào)用該函數(shù); 2、如果個數(shù)相同,類型不同則進行轉(zhuǎn)換,轉(zhuǎn)換時盡量按照類型精度升檔進行(*)。 3、通過用戶定義的轉(zhuǎn)換尋求匹配。函數(shù)重載的匹配規(guī)則當(dāng)某個函數(shù)中調(diào)用到重載函數(shù)時,編譯器會根函數(shù)重載的匹配選擇(*)doublesum(doublex,doubley) { cout<<"double"; returnx+y; }intsum(intx,inty) { cout<<"int"; returnx+y; }函數(shù)重載的匹配選擇(*)doublesum(double函數(shù)重載的匹配選擇(*)cout<<sum(1.1f,2.2f);//調(diào)用doublecout<<sum(1.1,2.2);//調(diào)用doublecout<<sum(1,2);//調(diào)用intcout<<sum('a','b');//調(diào)用int函數(shù)重載的匹配選擇(*)cout<<sum(1.1f,2.2函數(shù)的其它特性:缺省參數(shù)缺省參數(shù)指在定義函數(shù)時為形參指定缺省值(默認(rèn)值)。這樣的函數(shù)在調(diào)用時,對于缺省參數(shù),可以給出實參值,也可以不給出參數(shù)值。如果給出實參,將實參傳遞給形參進行調(diào)用,如果不給出實參,則按缺省值進行調(diào)用。函數(shù)的其它特性:缺省參數(shù)缺省參數(shù)指在定義函數(shù)時為形參指定缺省例:函數(shù)的缺省參數(shù)
voiddelay(int
loops=5){ //延時函數(shù),默認(rèn)延時5個時間單位
for(;loops>0;loops--); }
intmain(){ delay(3); cout<<“延時3個時間單位"<<endl; delay(); //等同于delay(5) cout<<“延時5個時間單位"<<endl;
return0; }例:函數(shù)的缺省參數(shù) voiddelay(intloops缺省參數(shù)的注意事項缺省參數(shù)可以有多個,但所有缺省參數(shù)必須放在參數(shù)表的右側(cè),即先定義所有的非缺省參數(shù),再定義缺省參數(shù)。這是因為在函數(shù)調(diào)用時,參數(shù)自左向右逐個匹配,當(dāng)實參和形參個數(shù)不一致時只有這樣才不會產(chǎn)生二義性。在同一個作用域中一個參數(shù)只能被指定一次缺省值。如果同時存在聲明和定義,則缺省值只能寫在聲明當(dāng)中(定義時不能再寫,即
溫馨提示
- 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)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 職業(yè)健康促進公平性與可持續(xù)發(fā)展策略-1
- 職業(yè)健康與員工職業(yè)發(fā)展路徑的醫(yī)學(xué)倫理考量
- 西安2025年陜西西安信息職業(yè)大學(xué)教職工招聘筆試歷年參考題庫附帶答案詳解
- 肇慶2025年廣東肇慶市招聘村助理204人筆試歷年參考題庫附帶答案詳解
- 玉溪2025年云南玉溪易門縣面向縣外選調(diào)教師筆試歷年參考題庫附帶答案詳解
- 深圳廣東深圳市第七高級中學(xué)招聘專任教師及教輔人員筆試歷年參考題庫附帶答案詳解
- 河源2025年秋季廣東河源紫金縣招聘教師218人筆試歷年參考題庫附帶答案詳解
- 柳州2025年廣西柳州市魚峰區(qū)招聘中小學(xué)教師8人筆試歷年參考題庫附帶答案詳解
- 新鄉(xiāng)2025年河南新鄉(xiāng)市市直部分事業(yè)單位招聘教師256人筆試歷年參考題庫附帶答案詳解
- 徐州2025年江蘇徐州沛縣職業(yè)教育學(xué)校招聘編制教師20人筆試歷年參考題庫附帶答案詳解
- 零缺陷培訓(xùn)教學(xué)課件
- 孕婦營養(yǎng)DHA課件
- 2026年餐飲企業(yè)稅務(wù)合規(guī)培訓(xùn)課件與發(fā)票管理風(fēng)控方案
- 2025年及未來5年市場數(shù)據(jù)中國蓖麻油行業(yè)投資潛力分析及行業(yè)發(fā)展趨勢報告
- 2025年湖北煙草專賣局真題試卷及答案
- 2025-2026學(xué)年廣東省廣州113中學(xué)八年級(上)期中語文試卷
- 浙江省臺金七校聯(lián)盟2025-2026學(xué)年高一上學(xué)期11月期中聯(lián)考語文試題含答案
- 兒科皮膚病科普
- 高二年級上冊物理期末試卷
- 生物質(zhì)發(fā)電安全運行方案
- 2025-2026學(xué)年高考二輪化學(xué)精準(zhǔn)復(fù)習(xí):電解質(zhì)溶液(課件)
評論
0/150
提交評論