版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第C語言函數(shù)超詳細(xì)講解下篇目錄前言函數(shù)的聲明和定義函數(shù)聲明函數(shù)定義舉例簡單的求和函數(shù)把加法單獨(dú)改寫成函數(shù)添加函數(shù)聲明帶頭文件和函數(shù)聲明靜態(tài)庫(.lib)的生成靜態(tài)庫文件的使用方法函數(shù)遞歸什么是遞歸?遞歸的兩個(gè)必要條件練習(xí)1一般方法遞歸的方法練習(xí)2一般方法遞歸方法練習(xí)3一般方法遞歸方法練習(xí)4一般方法遞歸方法遞歸與迭代遞歸隱藏的問題如何改進(jìn)選遞歸還是迭代總結(jié)
前言
緊接上文,繼續(xù)學(xué)習(xí)函數(shù)相關(guān)內(nèi)容。
函數(shù)的聲明和定義
函數(shù)聲明
告訴編譯器有一個(gè)函數(shù)叫什么,參數(shù)是什么,返回類型是什么。但是具體是不是存在,函數(shù)聲明決定不了函數(shù)的聲明一般出現(xiàn)在函數(shù)的使用之前。要滿足先聲明后使用函數(shù)的聲明一般要放在頭文件中的
函數(shù)定義
函數(shù)的定義是指函數(shù)的具體實(shí)現(xiàn),交待函數(shù)的功能實(shí)現(xiàn)
舉例
簡單的求和函數(shù)
一般寫簡單的求和函數(shù),求和功能直接寫在main()函數(shù)了。
//簡單的求和函數(shù)
intmain()
inta=10;
intb=20;
intsum=a+b;
printf("%d\n",sum);
return0;
把加法單獨(dú)改寫成函數(shù)
把加法功能單獨(dú)寫成一個(gè)函數(shù),放在主函數(shù)前面。如果將函數(shù)add放在主函數(shù)后面,則會(huì)報(bào)錯(cuò),因?yàn)槌绦蜃陨隙逻M(jìn)行的,主函數(shù)執(zhí)行后,發(fā)現(xiàn)add函數(shù)未定義,找不到。
//之前的有函數(shù)的寫法.函數(shù)放在前面
intadd(intx,inty)
returnx+y;
intmain()
inta=10;
intb=20;
intsum=add(a,b);
printf("%d\n",sum);
return0;
添加函數(shù)聲明
intadd(intx,inty);//函數(shù)的聲明
intmain()
inta=10;
intb=20;
intsum=add(a,b);
printf("%d\n",sum);
return0;
intadd(intx,inty)//定義放在主函數(shù)后面,需要先聲明
returnx+y;
帶頭文件和函數(shù)聲明
實(shí)際上,當(dāng)函數(shù)代碼較多時(shí),一般采用模塊化編程,每個(gè)函數(shù)實(shí)現(xiàn)功能盡量單一,函數(shù)間要低耦合、高內(nèi)聚。因此,針對上面的加單的加法函數(shù),用帶頭文件的寫法重寫一遍。
先定義源文件test.c、源文件add.c和頭文件add.h
//源文件test.c
#include"add.h"
intmain()
inta=10;
intb=20;
intsum=add(a,b);
printf("%d\n",sum);
return0;
//源文件add.c
intadd(intx,inty)//定義放在主函數(shù)后面,需要先聲明
returnx+y;
//頭文件add.h
intadd(intx,inty);//函數(shù)的聲明
靜態(tài)庫(.lib)的生成
當(dāng)編程寫了一個(gè)減法的函數(shù)給別人用,但是又不想把源碼直接分享給別人,這時(shí)候就可以將代碼編譯成靜態(tài)庫(就是.lib文件)。
靜態(tài)庫的特點(diǎn):將函數(shù)編譯成靜態(tài)庫,別人可以正常使用封裝好的代碼,但是又看不到源碼。
下面舉例說明,如何生成靜態(tài)庫(.lib):
新建VS工程,新建源文件sub.c和頭文件sub.h,編寫一個(gè)減法函數(shù)sub
//源文件sub.c
intsub(intx,inty)//函數(shù)定義需要先聲明
returny-x;
//頭文件sub.h
intsub(intx,inty);
依次點(diǎn)擊解決方案資源管理器項(xiàng)目名稱右鍵選屬性,彈出對話框。
然后依次點(diǎn)擊配置屬性常規(guī)項(xiàng)目默認(rèn)值配置類型下拉菜單選擇靜態(tài)庫(.lib)應(yīng)用確定。
接著點(diǎn)擊生成生成解決方案。
最終會(huì)在工程文件夾下的Debug文件夾看到靜態(tài)庫.lib文件。
用記事本打開靜態(tài)庫,可以看到是亂碼。
靜態(tài)庫文件的使用方法
接下來說明如何使用別人或者自己生成好的靜態(tài)庫文件:
(1)將函數(shù)對應(yīng)的同名頭文件.h文件和同名靜態(tài)庫.lib拷貝至自己的工程文件中。
(2)在頭文件中添加上t頭文件sub0119.h
(3)在源文件中添加減法頭文件引用和靜態(tài)庫的引用,
#include"add.h"http://加法頭文件
#include"sub0119.h"http://減法頭文件
#pragmacomment(lib,"sub0119.lib")//靜態(tài)庫必須加上
(4)程序運(yùn)行時(shí),會(huì)通過上面的引用將生成的靜態(tài)庫加載進(jìn)來。在主函數(shù)直接使用減法函數(shù)sub即可。
//帶頭文件的寫法
intmain()
inta=10;
intb=20;
intsum=add(a,b);//一般的函數(shù)調(diào)用
intsubnum=sub(a,b);//使用靜態(tài)庫
printf("%d\n",sum);
printf("%d\n",subnum);
return0;
運(yùn)行程序見下圖:
函數(shù)遞歸
什么是遞歸?
遞歸做為一種算法在程序設(shè)計(jì)語言中廣泛應(yīng)用。一個(gè)過程或函數(shù)在其定義或說明中有直接或間接調(diào)用自身的一種方法它通常把一個(gè)大型復(fù)雜的問題層層轉(zhuǎn)化為一個(gè)與原問題相似的規(guī)模較小的問題來求解只需少量的程序就可描述出解題過程所需要的多次重復(fù)計(jì)算,大大地減少了程序的代碼量遞歸的主要思考方式在于:把大事化小,將問題轉(zhuǎn)化為可以重復(fù)有限次的小問題解決
遞歸的兩個(gè)必要條件
存在限制條件,當(dāng)滿足這個(gè)限制條件的時(shí)候,遞歸便不再繼續(xù)每次遞歸調(diào)用之后越來越接近這個(gè)限制條件
練習(xí)1
接受一個(gè)整型值(無符號(hào)),按照順序打印它的每一位。
輸入:1234,輸出1234
一般方法
voidprint(num)//自定義打印函數(shù)
intarr[10]={0};//定義數(shù)組
for(inti=0;ii++)
{//將數(shù)字存放在數(shù)組里
arr[i]=num%10;//取數(shù)字最后一位
num=num/10;//取整數(shù)
for(inti=3;ii--)
{//倒著打印
printf("%d",arr[i]);
intmain()
intnum=1234;
print(num);
return0;
遞歸的方法
分析:打印1234可以分解成下圖那樣拆解,分別把不同位上的數(shù)字取出,最終把數(shù)字拆解剩最后一位時(shí),開始打?。?/p>
print(1234),數(shù)字大于9表明數(shù)字還不是個(gè)位數(shù),于是將1234拆解成123和4,分別通過取余和取模操作。把取余的123再次傳給函數(shù)printprint(123),數(shù)字大于9表明數(shù)字還不是個(gè)位數(shù),于是將123拆解成12和3,分別通過取余和取模操作,把取余的12再次傳給函數(shù)printprint(12),數(shù)字大于9表明數(shù)字還不是個(gè)位數(shù),于是將12拆解成1和2,分別通過取余和取模操作,把取余的1再次傳給函數(shù)printprint(1),數(shù)字小于9表明數(shù)字是個(gè)位數(shù),也就是分解到最后一步了,這就是遞歸的限制條件,于是將1取模操作,打印出來
代碼如下所示:
voidprint(intnum)
if(num9)
print(num/10);//取余
printf("%d",num%10);//取模
intmain()
intnum=1234;
print(num);
return0;
通過調(diào)試,我們分析整個(gè)遞歸程序的運(yùn)行邏輯見下圖,紅色圓圈的1234表示程序的執(zhí)行順序:
第一次調(diào)用函數(shù)print,此時(shí)num=1234,n9,滿足if條件,執(zhí)行print(123),調(diào)用函數(shù)print自身第二次調(diào)用函數(shù)print,此時(shí)num=123,n9,滿足if條件,執(zhí)行print(12),調(diào)用函數(shù)print自身第三次調(diào)用函數(shù)print,此時(shí)num=12,n9,滿足if條件,執(zhí)行print(1),調(diào)用函數(shù)print自身第四次調(diào)用函數(shù)print,此時(shí)num=1,n9,不滿足if條件,執(zhí)行printf(%d,num%10),此時(shí)num=1,打印1
此時(shí)函數(shù)已經(jīng)拆解到最后一層了,函數(shù)執(zhí)行結(jié)束返回到上一次調(diào)用的地方,綠色圓圈的1234表示程序的返回順序:
在綠色圓圈1處,函數(shù)printf打印1后,將會(huì)返回到上一次調(diào)用print的地方,即綠色圓圈2在綠色圓圈2處,if語句已經(jīng)執(zhí)行完畢,按順序執(zhí)行printf(%d,num%10),此時(shí)num=12,打印2。接著將會(huì)返回到上一次調(diào)用print的地方,即綠色圓圈3處在綠色圓圈3處,if語句已經(jīng)執(zhí)行完畢,按順序執(zhí)行printf(%d,num%10),此時(shí)num=123,打印3。接著將會(huì)返回到上一次調(diào)用print的地方,即綠色圓圈4處在綠色圓圈4處,if語句已經(jīng)執(zhí)行完畢,按順序執(zhí)行printf(%d,num%10),此時(shí)num=1234,打印4。接著將會(huì)返回到上一次調(diào)用print的地方,即主函數(shù)main中。
在函數(shù)運(yùn)行過程中,每調(diào)用一次函數(shù),在內(nèi)存棧中就會(huì)開辟空間存放num的值,如下面藍(lán)色方框顯示,第一次調(diào)用函數(shù)存放的1234在最底層,以此類推,1是最后調(diào)用函數(shù)存放的,就在最上面。
在函數(shù)返回時(shí),看綠色圓圈1234,num的值就從上向下取值,
在綠色圓圈1處,num數(shù)值為1。打印1后,函數(shù)運(yùn)行結(jié)束,存放1的空間就銷毀了此時(shí)返回到綠色圓圈2里,num數(shù)值為12,打印2后,函數(shù)運(yùn)行結(jié)束,存放12的空間也銷毀了此時(shí)返回到綠色圓圈3里,num數(shù)值為123,打印3后,函數(shù)運(yùn)行結(jié)束,存放123的空間也銷毀了此時(shí)返回到綠色圓圈2里,num數(shù)值為1234,打印4后,函數(shù)運(yùn)行結(jié)束,存放1234的空間也銷毀了
運(yùn)行結(jié)果見下圖:
練習(xí)2
編寫函數(shù)不允許創(chuàng)建臨時(shí)變量,求取字符串的長度
//編寫函數(shù)不允許創(chuàng)建臨時(shí)變量,求取字符串的長度
voidgetlen(char*arr)
intcount=0;//計(jì)數(shù)
while(*arr!='\0')
count++;//計(jì)數(shù)加1
arr++;//地址移動(dòng)到下一個(gè)字符
printf("%d",count);
intmain()
chararr[]="abcd";
getlen(arr);//數(shù)組名就是首元素地址
return0;
遞歸方法
分析:自定義函數(shù)getlen,計(jì)算字符串a(chǎn)bcd,字符串以\0結(jié)尾,這是隱藏的,實(shí)際字符串為abcd\0自定義函數(shù)可以分解成下圖那樣拆解,每次取出一個(gè)字符,最終把字符都取完,返回值:
getlen(abcd),判斷字符是不是\0,不是,于是將getlen(abcd)拆解成1+getlen(bcd)getlen(bcd),判斷字符是不是\0,不是,于是將getlen(bcd)拆解成1+getlen(cd)getlen(cd),判斷字符是不是\0,不是,于是將getlen(cd)拆解成1+getlen(d)getlen(d),判斷字符是不是\0,不是,于是將getlen(d)拆解成1+getlen(\0),已經(jīng)到字符串結(jié)尾了getlen(\0),判斷字符是不是\0,是,于是返回值0,代表字符串結(jié)束了,這就是遞歸的限制條件
下面是實(shí)現(xiàn)代碼:
//遞歸方法
intgetlen(char*arr)
if(*arr!=0)
arr++;
return1+getlen(arr);
return0;//等于0,字符串結(jié)束了,返回0
intmain()
chararr[]="abcd";
intsz=getlen(arr);
printf("%d",sz);
return0;
程序運(yùn)行結(jié)果見下圖,紅色路線是遞歸按順序調(diào)用函數(shù),綠色的路線是遞歸達(dá)到限制條件后,返回值
練習(xí)3
求n的階乘。(不考慮溢出)
//求n的階乘
voidfact(intn)
intnum=1;
for(inti=1;ii++)
num=num*i;
printf("%d",num);
intmain()
fact(3);//階乘
return0;
分析:自定義函數(shù)fact,求n的階乘。自定義函數(shù)可以分解成下圖那樣拆解:
fact(n)=n!=n*(n-1)1=nfact(n-1),fact(n-1)=(n-1)!=(n-1)*1=(n-1)*fact(n-2),依次類推,fact(2)=2!=2*fact(1),判斷n已經(jīng)推到1了,返回fact(1)=1,這就是遞歸的限制條件。
//遞歸方法
intfact(intn)
if(n=1)
returnn*fact(n-1);
n--;
else
return1;
intmain()
intnum=fact(3);//階乘
printf("%d",num);
return0;
運(yùn)行結(jié)果見下圖:
練習(xí)4
求第n個(gè)斐波那契數(shù)。(不考慮溢出)
//一般方法
voidfib(intn)
intnum1=1;
intnum2=1;
intnum3=0;
for(inti=1;i=(n-2);i++)
num3=num1+num2;
num1=num2;
num2=num3;
printf("%d",num3);//輸出5
intmain()
fib(5);//第五個(gè)斐波那契數(shù)列是5
return0;
分析:自定義函數(shù)fib,求第n個(gè)斐波那契數(shù)列。自定義函數(shù)可以分解成下圖那樣拆解:
fib(1)=1,fib(2)=1fib(3)=fib(2)+fib(1),fib(4)=fib(3)+fib(2),依次類推,fib(n)=fib(n-1)+fib(n-2),求fib(6),就往前遞推,fib(6)=fib(5)+fib(4)一直推到fib(3)=fib(2)+fib(1),fib(1),fib(2)為已知值,數(shù)列推到此結(jié)束了,直接給返回值就行,這就是遞歸的限制條件。
//遞歸方法方法
intfib(intn)
if(n=2)
return1;
returnfib(n-1)+fib(n-2);
intmain()
intnum=fib(5);
printf("%d",num);
return0;
遞歸與迭代
遞歸隱藏的問題
在前面小節(jié)練習(xí)4中,發(fā)現(xiàn)有一個(gè)問題,舉例fib(6)說明,下面是計(jì)算fib(6)時(shí)用的遞歸方法,分析會(huì)發(fā)現(xiàn)fib(3)居然重復(fù)計(jì)算了3次,如果計(jì)算fib(40)時(shí),這樣的重復(fù)計(jì)算會(huì)更多,大量的重復(fù)計(jì)算勢必會(huì)降低計(jì)算速度。
通過程序來驗(yàn)證一樣,計(jì)算fib(6)時(shí),fib(3)總共計(jì)算了幾次:
intcount=0;//全局變量
intfib(intn)
if(n==3)
count++;//計(jì)算fib(3)計(jì)算了多少次
if(n=2)
return1;
returnfib(n-1)+fib(n-2);
intmain()
intnum=fib(6);
printf("%d\n",num);
printf("%d\n",count);
return0;
結(jié)果如下所示:fib(6)=8,fib(3)總共計(jì)算了3次:**
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 道路景觀照明設(shè)計(jì)方案
- 婦幼保健院醫(yī)藥費(fèi)用透明化方案
- 消防演練機(jī)制構(gòu)建方案
- 人防工程通道標(biāo)識(shí)設(shè)置方案
- 婦幼保健院急救知識(shí)普及方案
- 水閘機(jī)電設(shè)備維修保養(yǎng)方案
- 工地施工心理健康評估方案
- 2026年廣東茂名市高三高考一模英語試卷試題(含答案詳解)
- 川教版六年級(jí)英語上冊Unit X詞匯深度學(xué)習(xí)與結(jié)構(gòu)化應(yīng)用設(shè)計(jì)方案
- 跨學(xué)科視域下“校園碳中和”行動(dòng)方案設(shè)計(jì)-以二氧化碳性質(zhì)與轉(zhuǎn)化的深度學(xué)習(xí)為例
- 2025年上交所金融筆試題目及答案
- 服務(wù)外包人員保密管理制度(3篇)
- 2026中國電信四川公用信息產(chǎn)業(yè)有限責(zé)任公司社會(huì)成熟人才招聘備考題庫及答案詳解(奪冠系列)
- 成都高新區(qū)桂溪街道公辦幼兒園招聘編外人員考試備考題庫及答案解析
- 2025年醫(yī)院病歷管理操作規(guī)范
- 2026云南保山電力股份有限公司校園招聘50人筆試備考題庫及答案解析
- GB 4053.2-2025固定式金屬梯及平臺(tái)安全要求第2部分:斜梯
- 2026屆上海市長寧區(qū)市級(jí)名校高一上數(shù)學(xué)期末學(xué)業(yè)質(zhì)量監(jiān)測模擬試題含解析
- 2026年煙草公司筆試綜合試題及考點(diǎn)實(shí)操指引含答案
- 九年級(jí)寒假期末總結(jié)課件
- 壓鑄機(jī)作業(yè)人員安全培訓(xùn)課件
評論
0/150
提交評論