程序設(shè)計(jì)基礎(chǔ):ch09 再論函數(shù)_第1頁
程序設(shè)計(jì)基礎(chǔ):ch09 再論函數(shù)_第2頁
程序設(shè)計(jì)基礎(chǔ):ch09 再論函數(shù)_第3頁
程序設(shè)計(jì)基礎(chǔ):ch09 再論函數(shù)_第4頁
程序設(shè)計(jì)基礎(chǔ):ch09 再論函數(shù)_第5頁
已閱讀5頁,還剩54頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、n函數(shù)函數(shù)參數(shù)參數(shù)n函數(shù)值函數(shù)值n作用域作用域n局部量和全局量局部量和全局量n遞歸程序設(shè)計(jì)遞歸程序設(shè)計(jì)n本章小結(jié)本章小結(jié)作業(yè)作業(yè): 9.8 9.11 習(xí)題集:習(xí)題集:P9116 練習(xí)練習(xí): 9.1 9.2 9.3 9.5 9.6 9.9 9.1 9.1 參數(shù)參數(shù)9.1.1 傳遞直線方程系數(shù)傳遞直線方程系數(shù)指針作參數(shù)指針作參數(shù) 第五章求三角形重心的例題第五章求三角形重心的例題5.2的程序,傳遞一個(gè)直線方程的程序,傳遞一個(gè)直線方程的兩個(gè)系數(shù)信息時(shí)讓人感到十分別扭,函數(shù)不能把多個(gè)計(jì)算結(jié)的兩個(gè)系數(shù)信息時(shí)讓人感到十分別扭,函數(shù)不能把多個(gè)計(jì)算結(jié)果帶回調(diào)用處,不得不使用全局變量。使用指針參數(shù)可以解決果帶回調(diào)

2、用處,不得不使用全局變量。使用指針參數(shù)可以解決這個(gè)問題。這個(gè)問題。float xa,ya,xb,yb,xc,yc; /分別保存三角形三個(gè)頂點(diǎn)點(diǎn)的分別保存三角形三個(gè)頂點(diǎn)點(diǎn)的X、Y方向坐標(biāo)方向坐標(biāo)float xd,yd,xe,ye ; /分別表示中點(diǎn)分別表示中點(diǎn)D、E坐標(biāo)坐標(biāo)float a1,b1,a2,b2,a,b;/分別表示中線分別表示中線AD、BE的方程系數(shù)的方程系數(shù), a、b臨時(shí)變量臨時(shí)變量float xo,yo;/重心重心O的坐標(biāo)的坐標(biāo)/* 求中線:參數(shù):三角形三個(gè)頂點(diǎn)求中線:參數(shù):三角形三個(gè)頂點(diǎn)r、s、t的的x、y坐標(biāo)坐標(biāo) */void lines( float xr,float yr

3、,float xs,float ys,float xt,float yt ,float *a,float *b) /6float xu,yu;/中點(diǎn)中點(diǎn)u坐標(biāo)坐標(biāo)/7xu=(xs+xt)/2; /求求st邊的中點(diǎn)邊的中點(diǎn)u/8yu=(ys+yt)/2;/9/求過求過r、u兩點(diǎn)的直線方程兩點(diǎn)的直線方程/10*a=(yr-yu)/(xr-xu); /計(jì)算系數(shù)計(jì)算系數(shù)a;用指針參數(shù)帶回主程序;用指針參數(shù)帶回主程序/11*b=yr - *a * xr ;/計(jì)算系數(shù)計(jì)算系數(shù)b;用指針參數(shù)帶回主程序;用指針參數(shù)帶回主程序/12/13void main(void) / 主函數(shù)主函數(shù)/14/ 輸入三個(gè)點(diǎn)的輸入

4、三個(gè)點(diǎn)的X、Y方向坐標(biāo)方向坐標(biāo) 346 360 416 108 116 212printf(please input xa,ya,xb,yb,xc,yc:n);/15scanf(%f%f%f %f%f%f,&xa,&ya,&xb,&yb,&xc,&yc);/16lines(xa,ya,xb,yb,xc,yc,&a1,&b1); /求求BC邊的中線邊的中線AD/17lines(xb,yb,xa,ya,xc,yc,&a2,&b2); /求求AC邊的中線邊的中線BE/19xo=(b2-b1)/(a1-a2); /求求AD

5、、BE交點(diǎn)交點(diǎn)O/21yo=a1*xo+b1;/22printf(“重心坐標(biāo):重心坐標(biāo):x=%10.3f y=%10.3f n”,xo,yo);/ 打印輸出打印輸出 /24運(yùn)行結(jié)果演示運(yùn)行結(jié)果演示 函數(shù)函數(shù)lines用指針參數(shù)用指針參數(shù)a 、b代替了原來的全局量和代替了原來的全局量和函數(shù)值來傳遞計(jì)算結(jié)果。函數(shù)值來傳遞計(jì)算結(jié)果。 在函數(shù)聲明中,增加形式參數(shù)在函數(shù)聲明中,增加形式參數(shù)a 、b ,并把它聲明成,并把它聲明成指針類型,構(gòu)成指針參數(shù)指針類型,構(gòu)成指針參數(shù) 在函數(shù)調(diào)用中,用變量的指針(地址)作實(shí)在參數(shù),在函數(shù)調(diào)用中,用變量的指針(地址)作實(shí)在參數(shù),對(duì)應(yīng)相應(yīng)形式參數(shù)。對(duì)應(yīng)相應(yīng)形式參數(shù)。 在函

6、數(shù)聲明中,對(duì)形式參數(shù)在函數(shù)聲明中,對(duì)形式參數(shù)a 、b以間接尋址方式以間接尋址方式賦值,把值直接送入實(shí)在參數(shù)指針?biāo)赶虻淖兞恐?。賦值,把值直接送入實(shí)在參數(shù)指針?biāo)赶虻淖兞恐小R院瘮?shù)調(diào)用lines(xa,ya,xb,yb,xc,yc,&a1,&b1)為例: 函數(shù)調(diào)用時(shí)實(shí)在參數(shù)把變量a1 、b1的指針分別送入形式參數(shù)a 、b中,因此a 、b分別指向a1 、b1; a1:a:b1:b: 函數(shù)內(nèi)部,以間接尋址方式賦值,分別通過函數(shù)內(nèi)部,以間接尋址方式賦值,分別通過*a 、*b把值送入把值送入a 、b所指的變量中,也就是所指的變量中,也就是a1 、b1中。中。 當(dāng)函數(shù)返回后,當(dāng)函數(shù)返回后,

7、a1 、b1中自然是函數(shù)內(nèi)部給它們賦的值中自然是函數(shù)內(nèi)部給它們賦的值 應(yīng)用指針參數(shù),其作用是相當(dāng)大的應(yīng)用指針參數(shù),其作用是相當(dāng)大的 由于在函數(shù)內(nèi)部,指針參數(shù)變量可以指向它的調(diào)用處由于在函數(shù)內(nèi)部,指針參數(shù)變量可以指向它的調(diào)用處(外層程序)的其它變量(外層程序)的其它變量 它起到了其它程序設(shè)計(jì)語言中變量參數(shù)的作用。它起到了其它程序設(shè)計(jì)語言中變量參數(shù)的作用?!纠纠?.2】指針作參數(shù)的作用】指針作參數(shù)的作用 對(duì)隨意輸入的兩個(gè)整數(shù),按由大到小的順序輸出。對(duì)隨意輸入的兩個(gè)整數(shù),按由大到小的順序輸出。函數(shù)函數(shù)swap的功能是交換兩個(gè)整數(shù)變量的值。的功能是交換兩個(gè)整數(shù)變量的值。void swap(int *

8、xx, int *yy) int temp; temp=*xx; *xx=*yy; *yy=temp; void main() int x,y; scanf(%d %d, &x,&y); if(xy) swap(&x,&y); printf(n%dt%dn,x,y);63yx23422340返回值返回值xx23462344yy234Atemp234Emainswap234023423 6 3 程序輸出:程序輸出:6 39.1.2 對(duì)任意數(shù)組排序?qū)θ我鈹?shù)組排序-數(shù)組作參數(shù)數(shù)組作參數(shù) 第六章已經(jīng)編寫過第六章已經(jīng)編寫過“數(shù)組排序數(shù)組排序”程序,但是都是使用全局量程序,

9、但是都是使用全局量傳遞計(jì)算結(jié)果數(shù)組,不能對(duì)任意數(shù)組進(jìn)行排序。使用數(shù)組參數(shù)可傳遞計(jì)算結(jié)果數(shù)組,不能對(duì)任意數(shù)組進(jìn)行排序。使用數(shù)組參數(shù)可以解決該問題。以解決該問題。 【例【例9.3】利用數(shù)組參數(shù)重寫第六章例】利用數(shù)組參數(shù)重寫第六章例6.5,用,用“主元排序主元排序”法對(duì)整數(shù)組進(jìn)行排序,使之能對(duì)任意整數(shù)數(shù)組排序。法對(duì)整數(shù)組進(jìn)行排序,使之能對(duì)任意整數(shù)數(shù)組排序。運(yùn)行結(jié)果演示運(yùn)行結(jié)果演示 在該程序中,把被排序數(shù)組和數(shù)組長度都作為函數(shù)的參數(shù)。在該程序中,把被排序數(shù)組和數(shù)組長度都作為函數(shù)的參數(shù)。調(diào)用時(shí),實(shí)在的被排序數(shù)組對(duì)應(yīng)形式參數(shù)調(diào)用時(shí),實(shí)在的被排序數(shù)組對(duì)應(yīng)形式參數(shù)a ;數(shù)組長度對(duì)應(yīng)形;數(shù)組長度對(duì)應(yīng)形式參數(shù)式參

10、數(shù) n 。n數(shù)組與指針有極其密切的關(guān)系數(shù)組與指針有極其密切的關(guān)系 數(shù)組作參數(shù),傳遞給形參的實(shí)際是實(shí)參數(shù)組的首地址數(shù)組作參數(shù),傳遞給形參的實(shí)際是實(shí)參數(shù)組的首地址 也就是把實(shí)參數(shù)組名的值送入形參中也就是把實(shí)參數(shù)組名的值送入形參中 在函數(shù)內(nèi),形參數(shù)組實(shí)際是使用實(shí)參數(shù)組名字開始的那片存儲(chǔ)區(qū)在函數(shù)內(nèi),形參數(shù)組實(shí)際是使用實(shí)參數(shù)組名字開始的那片存儲(chǔ)區(qū) 事實(shí)上事實(shí)上C是把數(shù)組參數(shù)當(dāng)作指針來處理的。是把數(shù)組參數(shù)當(dāng)作指針來處理的。n數(shù)組作參數(shù),形參是一指針類型變量數(shù)組作參數(shù),形參是一指針類型變量 實(shí)參數(shù)組名實(shí)際也是一個(gè)指針值實(shí)參數(shù)組名實(shí)際也是一個(gè)指針值 參數(shù)結(jié)合時(shí),把實(shí)參指針值送入形參參數(shù)結(jié)合時(shí),把實(shí)參指針值送入

11、形參 實(shí)際是把數(shù)組首地址送入指針變量中,然后形參指向?qū)崊?shù)組第一實(shí)際是把數(shù)組首地址送入指針變量中,然后形參指向?qū)崊?shù)組第一個(gè)元素個(gè)元素 上述例子中,經(jīng)過函數(shù)調(diào)用、參數(shù)結(jié)合后,形式參數(shù)上述例子中,經(jīng)過函數(shù)調(diào)用、參數(shù)結(jié)合后,形式參數(shù)x指向指向a0。nC參數(shù)都是值方式的參數(shù)都是值方式的 數(shù)組參數(shù)傳遞給函數(shù)的值不是整個(gè)數(shù)組的值,而是數(shù)組名的值,也數(shù)組參數(shù)傳遞給函數(shù)的值不是整個(gè)數(shù)組的值,而是數(shù)組名的值,也就是實(shí)參數(shù)組首地址就是實(shí)參數(shù)組首地址 在函數(shù)內(nèi)不給形參開辟數(shù)組存儲(chǔ)空間,只給它開辟一個(gè)指針空間在函數(shù)內(nèi)不給形參開辟數(shù)組存儲(chǔ)空間,只給它開辟一個(gè)指針空間 參數(shù)傳遞的是實(shí)參數(shù)組名字的指針值。參數(shù)傳遞的是實(shí)參

12、數(shù)組名字的指針值。 省略數(shù)組形式參數(shù)最外層的尺寸省略數(shù)組形式參數(shù)最外層的尺寸n最外層的尺寸對(duì)計(jì)算數(shù)組元素的地址不起作用,在對(duì)數(shù)組參數(shù)的形最外層的尺寸對(duì)計(jì)算數(shù)組元素的地址不起作用,在對(duì)數(shù)組參數(shù)的形式參數(shù)聲明時(shí),可以省略最外層尺寸。前述式參數(shù)聲明時(shí),可以省略最外層尺寸。前述f的函數(shù)定義說明符可以的函數(shù)定義說明符可以使用形式使用形式 int f ( float x )n這種形式的形式參數(shù)聲明與前邊所述形式等價(jià),形參的具體尺寸由這種形式的形式參數(shù)聲明與前邊所述形式等價(jià),形參的具體尺寸由函數(shù)調(diào)用時(shí)的實(shí)參數(shù)組決定。多維情況也是這樣。例如函數(shù)調(diào)用時(shí)的實(shí)參數(shù)組決定。多維情況也是這樣。例如 int q ( fl

13、oat y 20 )n聲明兩維數(shù)組參數(shù)聲明兩維數(shù)組參數(shù)y ,y每行每行20個(gè)元素,具體多少行由實(shí)參數(shù)數(shù)組個(gè)元素,具體多少行由實(shí)參數(shù)數(shù)組決定。設(shè)有聲明決定。設(shè)有聲明float u1020 , v1520 ;n則函數(shù)調(diào)用則函數(shù)調(diào)用q(u) ,進(jìn)入函數(shù)進(jìn)入函數(shù)q執(zhí)行時(shí)執(zhí)行時(shí) 形式參數(shù)形式參數(shù)y表記實(shí)在參數(shù)數(shù)組表記實(shí)在參數(shù)數(shù)組u ,它是,它是10行行20列的數(shù)組;列的數(shù)組; 而函數(shù)調(diào)用而函數(shù)調(diào)用q(v) ,進(jìn)入同一個(gè)函數(shù),進(jìn)入同一個(gè)函數(shù)q執(zhí)行時(shí),形參數(shù)執(zhí)行時(shí),形參數(shù)y表記實(shí)參表記實(shí)參數(shù)組數(shù)組v 是是15行行20列的數(shù)組。列的數(shù)組。 數(shù)組參數(shù)可以有各種變形數(shù)組參數(shù)可以有各種變形與數(shù)組初值一樣,省略尺寸的

14、只能是最外層,下述函數(shù)定與數(shù)組初值一樣,省略尺寸的只能是最外層,下述函數(shù)定義說明符都是錯(cuò)誤的。義說明符都是錯(cuò)誤的。 int r ( float z ) int s ( float z10 ) int t ( float z10 20 ) 形式參數(shù)用指針形式形式參數(shù)用指針形式n前述函數(shù)前述函數(shù)f的函數(shù)定義說明符還可以用形式的函數(shù)定義說明符還可以用形式 int f ( float *x )n這種形式的形式參數(shù)聲明與上述這種形式的形式參數(shù)聲明與上述1中形式等價(jià),形式參數(shù)的中形式等價(jià),形式參數(shù)的具體尺寸由函數(shù)調(diào)用時(shí)的實(shí)在參數(shù)數(shù)組決定。設(shè)有聲明具體尺寸由函數(shù)調(diào)用時(shí)的實(shí)在參數(shù)數(shù)組決定。設(shè)有聲明float

15、c20 , b15 ;n則函數(shù)調(diào)用則函數(shù)調(diào)用f(c) , 進(jìn)入函數(shù)進(jìn)入函數(shù) f 執(zhí)行時(shí),形式參數(shù)執(zhí)行時(shí),形式參數(shù)x表記實(shí)在參表記實(shí)在參數(shù)數(shù)組數(shù)數(shù)組c ,它是,它是20個(gè)元素的一維數(shù)組;個(gè)元素的一維數(shù)組;n而函數(shù)調(diào)用而函數(shù)調(diào)用f(b) ,進(jìn)入同一個(gè)函數(shù),進(jìn)入同一個(gè)函數(shù)f執(zhí)行時(shí),形式參數(shù)執(zhí)行時(shí),形式參數(shù)x表記表記實(shí)在參數(shù)數(shù)組實(shí)在參數(shù)數(shù)組b ,它是,它是15個(gè)元素的一維數(shù)組。個(gè)元素的一維數(shù)組。使用指針作實(shí)在參數(shù)使用指針作實(shí)在參數(shù)n上述,形參是一個(gè)指針,對(duì)應(yīng)實(shí)參數(shù)可以是數(shù)組;上述,形參是一個(gè)指針,對(duì)應(yīng)實(shí)參數(shù)可以是數(shù)組;n反之形參是數(shù)組,對(duì)應(yīng)實(shí)在參數(shù)也可以是指針。反之形參是數(shù)組,對(duì)應(yīng)實(shí)在參數(shù)也可以是指針

16、。n下述應(yīng)用是正確的下述應(yīng)用是正確的 float a15,b20; float *p ; int f ( float x ) . . . int q ( . ) . . . p = a ; /* 賦值后,指針賦值后,指針p就是數(shù)組就是數(shù)組a */ . f(p) . /* 以以p作實(shí)在參數(shù),函數(shù)作實(shí)在參數(shù),函數(shù)f內(nèi)內(nèi)x表記數(shù)組表記數(shù)組a */ p = b ; /* 賦值后,指針賦值后,指針p就是數(shù)組就是數(shù)組b */ . f(p) . /* 以以p作實(shí)在參數(shù),函數(shù)作實(shí)在參數(shù),函數(shù)f內(nèi)內(nèi)x表記數(shù)組表記數(shù)組b */ 形式參數(shù)和實(shí)在參數(shù)都使用指針形式形式參數(shù)和實(shí)在參數(shù)都使用指針形式n數(shù)組參數(shù)形式還可以是

17、形參和實(shí)參都使用指針形式數(shù)組參數(shù)形式還可以是形參和實(shí)參都使用指針形式n即形參是一個(gè)指針,對(duì)應(yīng)實(shí)參也是指針即形參是一個(gè)指針,對(duì)應(yīng)實(shí)參也是指針n下述應(yīng)用是正確的下述應(yīng)用是正確的 float a15,b20; float *p ; int f ( float *x ) . xi . int q ( . ) . . . p = a ; /* 賦值后,指針賦值后,指針p就是數(shù)組就是數(shù)組a */ . f(p) . /* 以以p作實(shí)在參數(shù),函數(shù)作實(shí)在參數(shù),函數(shù)f內(nèi)內(nèi)x表記數(shù)組表記數(shù)組a */ p = b ; /* 賦值后,指針賦值后,指針p就是數(shù)組就是數(shù)組b */ . f(p) . /* 以以p作實(shí)在參數(shù),

18、函數(shù)作實(shí)在參數(shù),函數(shù)f內(nèi)內(nèi)x表記數(shù)組表記數(shù)組b */ 【例【例9.4】編函數(shù),把給定數(shù)組中的】編函數(shù),把給定數(shù)組中的n個(gè)整數(shù)反序存放。個(gè)整數(shù)反序存放。void inv(int x,int n)int temp,i,j;for(i=0;i=(n-1)/2;i+)j=n-1-i;temp=xi;xi=xj;xj=temp; 設(shè)有聲明設(shè)有聲明int a10則可以用則可以用inv(a,10)調(diào)用該函數(shù)。若還有聲明和操作調(diào)用該函數(shù)。若還有聲明和操作int *ptrptr=a則也可以用則也可以用inv(ptr,10)調(diào)用該函數(shù)。調(diào)用該函數(shù)。 運(yùn)行結(jié)果演示運(yùn)行結(jié)果演示該函數(shù)還可以用指針形式編成:該函數(shù)還可以

19、用指針形式編成:void inv(int *x,int n)int temp,*i,*j; / j從后向前變化,從后向前變化,i從前向后變化從前向后變化for(i=x,j=x+n-1; i=x+(n-1)/2; i+,j-)temp = *i; / temp保存保存i所指數(shù)組元素所指數(shù)組元素xi的值的值*i = *j; / xj的值送入的值送入xi*j = temp; / 把把temp中保存的中保存的xi的值送入的值送入xj運(yùn)行結(jié)果演示運(yùn)行結(jié)果演示運(yùn)行結(jié)果演示運(yùn)行結(jié)果演示【例【例9.5】編函數(shù),從】編函數(shù),從n個(gè)整數(shù)中找出最大和最小的數(shù)。個(gè)整數(shù)中找出最大和最小的數(shù)。void max_min_v

20、alue(int x,int n,int *max,int *min)int *p;*max = *min = *x;/ 把把x0送入送入max、min所指變量中所指變量中for(p=x+1; p *max)/ 求極大值,求極大值,p指向當(dāng)前數(shù)組元素指向當(dāng)前數(shù)組元素*max = *p;/ max指向極大值單元指向極大值單元if (*p *min)/ 求極小值求極小值*min = *p;設(shè)有聲明設(shè)有聲明int a10,max_value,min_value;則可以用則可以用max_min_value (a,10, &max_value,&min_value);調(diào)用該函數(shù)。若還有聲

21、明和操作調(diào)用該函數(shù)。若還有聲明和操作int *ptr;ptr=a;則也可以用則也可以用max_min_value (ptr,10, &max_value,&min_value);調(diào)用該函數(shù)。調(diào)用該函數(shù)。 第八章例第八章例8.1中函數(shù)中函數(shù)searchbook在圖書卡片數(shù)組中檢索在圖書卡片數(shù)組中檢索某給定書號(hào)的卡片。需要向函數(shù)傳遞給定的書號(hào)信息,函數(shù)某給定書號(hào)的卡片。需要向函數(shù)傳遞給定的書號(hào)信息,函數(shù)searchbook采用參數(shù)方式獲取這些信息,定義形式是:采用參數(shù)方式獲取這些信息,定義形式是:void searchbook(struct bookcard no2) int k;

22、k=0; while ( k100) if ( (groupcardk.no.catalogue = no2.catalogue ) & (groupcardk.no.order= no2.order ) ) out_anser(&groupcardk) ; printf(“n search end! n”);其中形式參數(shù)其中形式參數(shù)no2是結(jié)構(gòu)體參數(shù)。在主函數(shù)是結(jié)構(gòu)體參數(shù)。在主函數(shù)main中調(diào)用該函數(shù)的函數(shù)調(diào)用形式是中調(diào)用該函數(shù)的函數(shù)調(diào)用形式是 searchcard(no1);把結(jié)構(gòu)體變量把結(jié)構(gòu)體變量no1的值傳遞給的值傳遞給no2。在函數(shù)內(nèi)部,。在函數(shù)內(nèi)部,no2具有主函數(shù)

23、中具有主函數(shù)中no1的值。參數(shù)的值。參數(shù)傳遞結(jié)束,進(jìn)入函數(shù)傳遞結(jié)束,進(jìn)入函數(shù)searchbook后,后,no2是函數(shù)是函數(shù)searchbook的一個(gè)局部變量,與的一個(gè)局部變量,與no1無無關(guān)了。在上述關(guān)了。在上述if語句中,語句中,no2.catalogue 、no2.order使用使用no1中傳遞過來的值。中傳遞過來的值。結(jié)構(gòu)體作參數(shù)與一般結(jié)構(gòu)體作參數(shù)與一般int、float等參數(shù)一樣,傳遞實(shí)在參數(shù)的值到形式參數(shù)中,在函等參數(shù)一樣,傳遞實(shí)在參數(shù)的值到形式參數(shù)中,在函數(shù)內(nèi)部,形式參數(shù)是函數(shù)的一個(gè)局部變量,與實(shí)在參數(shù)無關(guān)。數(shù)內(nèi)部,形式參數(shù)是函數(shù)的一個(gè)局部變量,與實(shí)在參數(shù)無關(guān)。 n在函數(shù)之間,通過

24、參數(shù)傳送結(jié)構(gòu)體值有兩種方法在函數(shù)之間,通過參數(shù)傳送結(jié)構(gòu)體值有兩種方法 用指向結(jié)構(gòu)體變量的指針作函數(shù)參數(shù)。用指向結(jié)構(gòu)體變量的指針作函數(shù)參數(shù)。 直接用結(jié)構(gòu)體變量作函數(shù)參數(shù)。直接用結(jié)構(gòu)體變量作函數(shù)參數(shù)。n剛剛介紹了第二中方式,第一種方式就是指針作函數(shù)參數(shù),剛剛介紹了第二中方式,第一種方式就是指針作函數(shù)參數(shù),只不過相應(yīng)指針是指向結(jié)構(gòu)體類型變量的指針。與指向其它只不過相應(yīng)指針是指向結(jié)構(gòu)體類型變量的指針。與指向其它類型變量的指針沒有任何區(qū)別。在類型變量的指針沒有任何區(qū)別。在9.1.2已經(jīng)介紹過,已經(jīng)介紹過,同時(shí)例同時(shí)例8.1中的函數(shù)中的函數(shù)out_anser已經(jīng)使用過這種方式。已經(jīng)使用過這種方式。 。函數(shù)

25、函數(shù)out_anser的定義說明符形式是:的定義說明符形式是: void out_anser( struct bookcard *card0 )形式參數(shù)形式參數(shù)card0是指針參數(shù),將指向是指針參數(shù),將指向struct bookcard類型變類型變量。函數(shù)調(diào)用量。函數(shù)調(diào)用 out_anser(&groupcardk)把結(jié)構(gòu)體變量把結(jié)構(gòu)體變量groupcardk的指針(地址)傳遞給的指針(地址)傳遞給card0,使使card0指向指向groupcardk。在函數(shù)內(nèi)部,用。在函數(shù)內(nèi)部,用card0訪問訪問groupcardk。 9.2 函數(shù)值函數(shù)值 9.2.1 打印月份名打印月份名返回指針

26、值的函數(shù)返回指針值的函數(shù) 解:該題目可以給出月份名字符串?dāng)?shù)組解:該題目可以給出月份名字符串?dāng)?shù)組name,用月份號(hào)直接,用月份號(hào)直接輸出。輸出。 現(xiàn)在換一種方式編該程序,用一個(gè)函數(shù)現(xiàn)在換一種方式編該程序,用一個(gè)函數(shù)month_name求相應(yīng)月求相應(yīng)月份的名字字符串,然后調(diào)用該函數(shù)求出名字后,再輸出。編出份的名字字符串,然后調(diào)用該函數(shù)求出名字后,再輸出。編出程序如下。程序如下。例例9.6 讀入月份數(shù),輸出該月份英文名稱讀入月份數(shù),輸出該月份英文名稱char *month_name(int);char *name=“illegal month”, “January”,”February”,”Marc

27、h”,”April”,”May”,”June”,“July”,”August”,”September”,”O(jiān)ctober”,”November”,”December”int main(void) int n; char *p; printf(“Input a number of a month:”); scanf(“%d”,&n); p = month_name(n); printf( “It is %sn”,p);char *month_name(int m) if (m12) return name0 ; else return namem;程序運(yùn)行結(jié)果程序運(yùn)行結(jié)果Input a

28、number of a month:2It is February 運(yùn)行結(jié)果演示運(yùn)行結(jié)果演示n函數(shù)返回類型不允許是數(shù)組類型和函數(shù)類型,除此之外允函數(shù)返回類型不允許是數(shù)組類型和函數(shù)類型,除此之外允許一切類型,當(dāng)然允許指針類型許一切類型,當(dāng)然允許指針類型n指針類型函數(shù)(帶回指針值的函數(shù))的函數(shù)定義說明符形指針類型函數(shù)(帶回指針值的函數(shù))的函數(shù)定義說明符形式是:式是: 類型名類型名 *函數(shù)名函數(shù)名( 形式參數(shù)表形式參數(shù)表 ) 例:例:float *f ( int x , int y ) f 是函數(shù)名;是函數(shù)名; x 和和 y 是兩個(gè)是兩個(gè) int 類型形參;類型形參; 該函數(shù)的返回類型是該函數(shù)的返回

29、類型是“ float * ” 即指向即指向 float 類型的指針。類型的指針。 可以這樣解釋該函數(shù)定義說明符??梢赃@樣解釋該函數(shù)定義說明符。按運(yùn)算符優(yōu)先級(jí)規(guī)定,按運(yùn)算符優(yōu)先級(jí)規(guī)定,“ * ” 的級(jí)別低于的級(jí)別低于 “()()”,f (int x, int y) 是一個(gè)函數(shù),它的類型是是一個(gè)函數(shù),它的類型是 “ float *”,即函數(shù)即函數(shù) f 的類型是的類型是 float 類型指針類型指針函數(shù)函數(shù)f 是返回指針值的函數(shù)。是返回指針值的函數(shù)。 在函數(shù)內(nèi),在函數(shù)內(nèi),return 語句后邊的表達(dá)式類型應(yīng)該是語句后邊的表達(dá)式類型應(yīng)該是 類型名類型名 *比如若有聲明比如若有聲明 float u ,

30、*v ;則,下述則,下述return語句都是正確的語句都是正確的return &u; rerurn v;而語句而語句 return u; 是錯(cuò)誤的。是錯(cuò)誤的。 C指針函數(shù)只允許返回全局變量指針、靜態(tài)變量指針、堆內(nèi)空間地指針函數(shù)只允許返回全局變量指針、靜態(tài)變量指針、堆內(nèi)空間地址,不允許把函數(shù)內(nèi)部聲明的局部變量指針(地址)作為返回值。址,不允許把函數(shù)內(nèi)部聲明的局部變量指針(地址)作為返回值。在例在例8-10中,如果把字符串?dāng)?shù)組中,如果把字符串?dāng)?shù)組name放在函數(shù)放在函數(shù)mp內(nèi)聲明就錯(cuò)了。內(nèi)聲明就錯(cuò)了。因?yàn)楹瘮?shù)內(nèi)部聲明的局部變量在棧區(qū)分配空間,函數(shù)調(diào)用結(jié)束時(shí),因?yàn)楹瘮?shù)內(nèi)部聲明的局部變量在棧區(qū)

31、分配空間,函數(shù)調(diào)用結(jié)束時(shí),釋放棧區(qū)中函數(shù)運(yùn)行空間,會(huì)造成返回指針?biāo)复鎯?chǔ)空間已不存在釋放棧區(qū)中函數(shù)運(yùn)行空間,會(huì)造成返回指針?biāo)复鎯?chǔ)空間已不存在 9.2.2 讀入圖書卡片讀入圖書卡片返回結(jié)構(gòu)體值的函數(shù)返回結(jié)構(gòu)體值的函數(shù)回顧第八章例回顧第八章例8.1中函數(shù)中函數(shù)inputcard。struct bookcard inputcard( void )struct bookcard card;int k;printf(nn new card:);printf(“nplease input bookname:”);scanf(“%s”, ); printf(“nplease input

32、abstract:”);scanf(“%s”, card.abstract);return card; inputcard函數(shù)的類型是函數(shù)的類型是struct bookcard為一個(gè)結(jié)構(gòu)體類為一個(gè)結(jié)構(gòu)體類型,表示函數(shù)返回值是一個(gè)結(jié)構(gòu)體值。在型,表示函數(shù)返回值是一個(gè)結(jié)構(gòu)體值。在inputcard返回時(shí),使返回時(shí),使用語句用語句return card;返回。返回。 函數(shù)帶著變量函數(shù)帶著變量card的值返回,的值返回,card正好是正好是struct bookcard類型的。函數(shù)將帶著類型的。函數(shù)將帶著struct bookcard類型的一類型的一個(gè)結(jié)構(gòu)體值返回到主函數(shù)個(gè)結(jié)構(gòu)體值返回到主函數(shù)main

33、中。中。 在主函數(shù)在主函數(shù)main中,以中,以groupcardi = inputcard( );調(diào)用函數(shù)調(diào)用函數(shù)inputcard。把。把inputcard帶回的結(jié)構(gòu)體值送入數(shù)帶回的結(jié)構(gòu)體值送入數(shù)組成分變量組成分變量groupcardi中。中。n函數(shù)的計(jì)算結(jié)果可能是一個(gè)結(jié)構(gòu)體值。在函數(shù)的計(jì)算結(jié)果可能是一個(gè)結(jié)構(gòu)體值。在C中,有兩種途中,有兩種途徑能夠把該結(jié)構(gòu)體值通過函數(shù)名字帶回調(diào)用函數(shù)的主程序。徑能夠把該結(jié)構(gòu)體值通過函數(shù)名字帶回調(diào)用函數(shù)的主程序。 使用指針。函數(shù)的結(jié)果類型是指向結(jié)構(gòu)體類型變量的使用指針。函數(shù)的結(jié)果類型是指向結(jié)構(gòu)體類型變量的指針類型。指針類型。 直接使用結(jié)構(gòu)體類型。函數(shù)的結(jié)果類型

34、是結(jié)構(gòu)體類型,直接使用結(jié)構(gòu)體類型。函數(shù)的結(jié)果類型是結(jié)構(gòu)體類型,直接把一個(gè)結(jié)構(gòu)體值帶回調(diào)用函數(shù)的主程序。直接把一個(gè)結(jié)構(gòu)體值帶回調(diào)用函數(shù)的主程序。n第二種方式就是我們剛剛介紹的例第二種方式就是我們剛剛介紹的例8.1中中inputcard所用所用的方式。的方式。n第一種方式就是返回指針的函數(shù),只不過相應(yīng)指針是指向第一種方式就是返回指針的函數(shù),只不過相應(yīng)指針是指向結(jié)構(gòu)體類型變量的指針。與其它類型返回指針的函數(shù)沒有結(jié)構(gòu)體類型變量的指針。與其它類型返回指針的函數(shù)沒有任何區(qū)別,就是任何區(qū)別,就是9.2.1介紹的方法。介紹的方法。9.3 9.3 作用域作用域n所謂作用域,就是使程序中聲明的標(biāo)識(shí)符有定義的區(qū)域。

35、所謂作用域,就是使程序中聲明的標(biāo)識(shí)符有定義的區(qū)域。在一個(gè)標(biāo)識(shí)符的作用域內(nèi),使用它是合法的。在一個(gè)標(biāo)識(shí)符的作用域內(nèi),使用它是合法的。n作用域是一個(gè)靜態(tài)概念,描述從程序靜態(tài)行文上看,程序作用域是一個(gè)靜態(tài)概念,描述從程序靜態(tài)行文上看,程序中一個(gè)被聲明的標(biāo)識(shí)符起作用的范圍。下表列出各種中一個(gè)被聲明的標(biāo)識(shí)符起作用的范圍。下表列出各種C標(biāo)標(biāo)識(shí)符的作用域。識(shí)符的作用域。C 標(biāo)識(shí)符作用域標(biāo)識(shí)符作用域類別類別 聲明的作用域聲明的作用域頂層標(biāo)識(shí)符頂層標(biāo)識(shí)符從聲明點(diǎn)到本源程序編譯單位文本結(jié)束從聲明點(diǎn)到本源程序編譯單位文本結(jié)束函數(shù)定義中的形參函數(shù)定義中的形參從聲明點(diǎn)到函數(shù)體結(jié)束從聲明點(diǎn)到函數(shù)體結(jié)束函數(shù)原型中的形參函數(shù)

36、原型中的形參從聲明點(diǎn)到函數(shù)原型結(jié)束從聲明點(diǎn)到函數(shù)原型結(jié)束復(fù)合語句中聲明的標(biāo)識(shí)符復(fù)合語句中聲明的標(biāo)識(shí)符 從復(fù)合語句中聲明點(diǎn)到復(fù)合語句結(jié)束從復(fù)合語句中聲明點(diǎn)到復(fù)合語句結(jié)束語句標(biāo)號(hào)語句標(biāo)號(hào)相應(yīng)標(biāo)號(hào)聲明所在的整個(gè)函數(shù)體相應(yīng)標(biāo)號(hào)聲明所在的整個(gè)函數(shù)體預(yù)處理器的宏預(yù)處理器的宏從相應(yīng)宏定義的從相應(yīng)宏定義的#define命令到本源程命令到本源程序編譯單位文本結(jié)束,序編譯單位文本結(jié)束,或第一個(gè)取消相應(yīng)宏定義的或第一個(gè)取消相應(yīng)宏定義的#undef命令命令 在在C中,每個(gè)源程序編譯單位,每個(gè)函數(shù)定義、函數(shù)原型、中,每個(gè)源程序編譯單位,每個(gè)函數(shù)定義、函數(shù)原型、復(fù)合語句都各自構(gòu)成一個(gè)作用域區(qū)域。復(fù)合語句都各自構(gòu)成一個(gè)作用

37、域區(qū)域。C規(guī)定:規(guī)定:l 在嵌套結(jié)構(gòu)中,若里層區(qū)域的一個(gè)標(biāo)識(shí)符與外層區(qū)域在嵌套結(jié)構(gòu)中,若里層區(qū)域的一個(gè)標(biāo)識(shí)符與外層區(qū)域 的某標(biāo)識(shí)符同名,則外層標(biāo)識(shí)符的作用域不包括里層的某標(biāo)識(shí)符同名,則外層標(biāo)識(shí)符的作用域不包括里層 那個(gè)同名標(biāo)識(shí)符的作用域區(qū)域。那個(gè)同名標(biāo)識(shí)符的作用域區(qū)域。l C 程序中使用的任意一個(gè)標(biāo)識(shí)符必須聲明;并且必須程序中使用的任意一個(gè)標(biāo)識(shí)符必須聲明;并且必須 先聲明后使用;在同一區(qū)域內(nèi)任何標(biāo)識(shí)符不得重復(fù)聲先聲明后使用;在同一區(qū)域內(nèi)任何標(biāo)識(shí)符不得重復(fù)聲 明。明。 例例9.7 錯(cuò)誤應(yīng)用錯(cuò)誤應(yīng)用標(biāo)識(shí)符標(biāo)識(shí)符 k 沒有聲明沒有聲明標(biāo)識(shí)符標(biāo)識(shí)符 x 在同一作用域中重復(fù)聲明在同一作用域中重復(fù)聲明 i

38、nt i,j; int f(void) . . k=i+j; float f( int x ) int x ; . . 第三行的第三行的 c 將被替換為將被替換為2.0標(biāo)識(shí)符標(biāo)識(shí)符 index , t2 先使用后聲明先使用后聲明 #define c 2.0 typedef int t ; t c,d,e; #define c 2.0 t2 y index ; typedef t2 float ; #define index 109.4 9.4 局部量和全局量局部量和全局量n由作用域規(guī)則可知由作用域規(guī)則可知 一個(gè)函數(shù)或復(fù)合語句引入的標(biāo)識(shí)符只在本函數(shù)一個(gè)函數(shù)或復(fù)合語句引入的標(biāo)識(shí)符只在本函數(shù)或復(fù)合語

39、句內(nèi)有效,或復(fù)合語句內(nèi)有效, 在本函數(shù)或復(fù)合語句外,便失去了它的意義在本函數(shù)或復(fù)合語句外,便失去了它的意義 稱它們是局部于聲明它們的函數(shù)或復(fù)合語句稱它們是局部于聲明它們的函數(shù)或復(fù)合語句 或稱該標(biāo)識(shí)符相對(duì)于聲明它們的函數(shù)或復(fù)合語或稱該標(biāo)識(shí)符相對(duì)于聲明它們的函數(shù)或復(fù)合語句來講是句來講是局部量局部量。由作用域規(guī)則還可知由作用域規(guī)則還可知n任何頂層聲明的標(biāo)識(shí)符在所有函數(shù)內(nèi)部以及復(fù)合語句都可以任何頂層聲明的標(biāo)識(shí)符在所有函數(shù)內(nèi)部以及復(fù)合語句都可以使用。條件是在函數(shù)內(nèi)部和復(fù)合語句中沒有與它同名的其它使用。條件是在函數(shù)內(nèi)部和復(fù)合語句中沒有與它同名的其它聲明,稱頂層聲明的標(biāo)識(shí)符相對(duì)于函數(shù)和復(fù)合語句來講是全聲明,

40、稱頂層聲明的標(biāo)識(shí)符相對(duì)于函數(shù)和復(fù)合語句來講是全局量局量n若一個(gè)復(fù)合語句嵌套在一個(gè)函數(shù)或另一個(gè)復(fù)合語句之內(nèi),且若一個(gè)復(fù)合語句嵌套在一個(gè)函數(shù)或另一個(gè)復(fù)合語句之內(nèi),且某一個(gè)標(biāo)識(shí)符在函數(shù)或其外層復(fù)合語句中聲明,在內(nèi)層復(fù)合某一個(gè)標(biāo)識(shí)符在函數(shù)或其外層復(fù)合語句中聲明,在內(nèi)層復(fù)合語句中沒有與相應(yīng)標(biāo)識(shí)符同名的聲明,則函數(shù)或外層復(fù)合語語句中沒有與相應(yīng)標(biāo)識(shí)符同名的聲明,則函數(shù)或外層復(fù)合語句中關(guān)于這個(gè)標(biāo)識(shí)符的聲明在內(nèi)層復(fù)合語句中仍然有效。即句中關(guān)于這個(gè)標(biāo)識(shí)符的聲明在內(nèi)層復(fù)合語句中仍然有效。即在內(nèi)層復(fù)合語句中仍可使用這個(gè)標(biāo)識(shí)符,稱在函數(shù)或外層復(fù)在內(nèi)層復(fù)合語句中仍可使用這個(gè)標(biāo)識(shí)符,稱在函數(shù)或外層復(fù)合語句中聲明的標(biāo)識(shí)符相對(duì)

41、于其內(nèi)層復(fù)合語句來講是全局量。合語句中聲明的標(biāo)識(shí)符相對(duì)于其內(nèi)層復(fù)合語句來講是全局量。n全局量和局部量是一個(gè)相對(duì)概念。全局量和局部量是一個(gè)相對(duì)概念。 某標(biāo)識(shí)符相對(duì)于某復(fù)合語句是局部的,相對(duì)于其某標(biāo)識(shí)符相對(duì)于某復(fù)合語句是局部的,相對(duì)于其內(nèi)層復(fù)合語句卻是全局的;內(nèi)層復(fù)合語句卻是全局的; 反之某標(biāo)識(shí)符相對(duì)于里層某復(fù)合語句是全局的,反之某標(biāo)識(shí)符相對(duì)于里層某復(fù)合語句是全局的,但是相對(duì)于聲明它本身的那個(gè)復(fù)合語句來講卻是但是相對(duì)于聲明它本身的那個(gè)復(fù)合語句來講卻是局部的。局部的。n全局量在內(nèi)層具有外層同樣的意義全局量在內(nèi)層具有外層同樣的意義 在內(nèi)層對(duì)全局量的操作直接反應(yīng)在外層程序中在內(nèi)層對(duì)全局量的操作直接反應(yīng)在

42、外層程序中例例9.8 計(jì)算調(diào)合級(jí)數(shù)前項(xiàng)和計(jì)算調(diào)合級(jí)數(shù)前項(xiàng)和nHn1.312111 開始開始 結(jié)束結(jié)束h=0i=1 TO nh=h+1/ih 約分約分/*PROGRAM the summation of a seriers*/ #include “stdio.h” /* 1 */int a,b,n; /* 2 */void add ( int *e , int *f , int ii ) /* 3 */ *e = (*e) * ii + (*f) ; /* 4 */ *f = (*f) * ii ; /* 5 */ /* 6 */int gcd( int u , int v ) /* 7 */

43、int r ; /* 8 */ r=v; /* 9 */ while ( r!=0 ) /* 10 */ r = u % v ; /* 11 */ u = v ; /* 12 */ v = r ; /* 13 */ /* 14 */ return u ; /* 15 */void reduce ( int *x , int *y ) /* 17 */ int g ; /* 18 */ g = gcd( x,y ) ; /* 19 */ *x = (*x) / g ; /* 20 */ *y = (*y) / g ; /* 21 */ /* 22 */int main(void) /* 23 *

44、/ int i ; /* 24 */ printf(please input the value of n:); /* 25 */ scanf(“%d”,&n); /* 26 */ a=0; /* 27 */ b=1; /* 28 */ for (i=1 ; i=n ; i+ ) /* 29 */ add( &a , &b , i ); /* 30 */ reduce( &a , &b ); /* 31 */ /* 32 */ printf(“ %dn” , a ) ; /* 33 */ printf(“ Hn = n”); /* 34 */ print

45、f(“ %dn” , b ) ; /* 35 */ /* 36 */運(yùn)行結(jié)果演示運(yùn)行結(jié)果演示程序中各個(gè)變量的作用域程序中各個(gè)變量的作用域 變量變量a, b, n; 函數(shù)函數(shù)main, add, reduce, gcd在頂層聲明,是全在頂層聲明,是全局量。局量。 作用域是它們各自的聲明符以后直到整個(gè)程序文件結(jié)束。作用域是它們各自的聲明符以后直到整個(gè)程序文件結(jié)束。 變量變量i在主函數(shù)在主函數(shù)main中聲明,是中聲明,是main的局部量。的局部量。 作用域是第作用域是第24行它的聲明符以后直到第行它的聲明符以后直到第36行行 add的形式參數(shù)的形式參數(shù)e, f, ii在在add中聲明,是中聲明,是a

46、dd的局部量的局部量 作用域是第作用域是第3行它們各自的聲明符以后直到第行它們各自的聲明符以后直到第6行。行。 gcd的形式參數(shù)的形式參數(shù)u, v和在和在gcd內(nèi)部復(fù)合語句中聲明的變量內(nèi)部復(fù)合語句中聲明的變量r是局是局部于部于gcd的局部量。的局部量。 作用域是第作用域是第7、8行它們各自的聲明符以后直到第行它們各自的聲明符以后直到第16行。行。 reduce 的形參的形參x, y和在和在reduce 內(nèi)部復(fù)合語句中聲明的變量內(nèi)部復(fù)合語句中聲明的變量g是局部于是局部于reduce 的局部量。的局部量。 作用域是第作用域是第17、18行它們各自的聲明符以后直到第行它們各自的聲明符以后直到第22行

47、行在本程序的執(zhí)行過程中:在本程序的執(zhí)行過程中:n第第 30 行調(diào)用函數(shù)行調(diào)用函數(shù)add作加法。作加法。以以 &a 、&b作實(shí)在參數(shù),對(duì)應(yīng)函數(shù)作實(shí)在參數(shù),對(duì)應(yīng)函數(shù)add的形式參數(shù)的形式參數(shù)e 、f ,分,分別把別把a(bǔ) 、b的地址送入指針形式參數(shù)的地址送入指針形式參數(shù)e 、f中。中。在在add中,采用間接尋址為中,采用間接尋址為 *e 、*f 賦值,因?yàn)橘x值,因?yàn)閑 、f分別指向分別指向a 、b ,就是給,就是給a 、b賦值。賦值。以以i作實(shí)參對(duì)應(yīng)形參作實(shí)參對(duì)應(yīng)形參ii ,把把i的值送入的值送入ii之中,參與運(yùn)算。之中,參與運(yùn)算。另外這個(gè)函數(shù)中還通過間接尋址另外這個(gè)函數(shù)中還通過間接

48、尋址 *e 、*f 訪問訪問a 、b ,用,用a 、b的值參與運(yùn)算。的值參與運(yùn)算。n31 行調(diào)用行調(diào)用reduce 作約分,參數(shù)結(jié)合以及信息傳遞類似作約分,參數(shù)結(jié)合以及信息傳遞類似add 。n19行行reduce函數(shù)體中調(diào)用函數(shù)函數(shù)體中調(diào)用函數(shù)gcd ,以,以x 、y做實(shí)參對(duì)應(yīng)形參做實(shí)參對(duì)應(yīng)形參u 、v ,把兩個(gè)整數(shù)值傳入函數(shù),把兩個(gè)整數(shù)值傳入函數(shù)gcd 。n在在gcd內(nèi),雖然反復(fù)給形參變量內(nèi),雖然反復(fù)給形參變量u 、v賦值,但是由于賦值,但是由于C參數(shù)的參數(shù)的值參數(shù)特性,這些賦值不影響實(shí)在參數(shù),不改變實(shí)在參數(shù)值參數(shù)特性,這些賦值不影響實(shí)在參數(shù),不改變實(shí)在參數(shù)x 、y的值。的值。n所以當(dāng)從所以

49、當(dāng)從gcd返回返回reduce后,后,x 、y的值沒有變化,保證了程序的值沒有變化,保證了程序的正確性。的正確性。9.5 9.5 計(jì)算計(jì)算n!n!遞歸程序設(shè)計(jì)遞歸程序設(shè)計(jì)例例9.9 編一個(gè)函數(shù)編一個(gè)函數(shù) factorial 計(jì)算階乘計(jì)算階乘 !按過去程序設(shè)計(jì)思想,該函數(shù)應(yīng)該寫成:按過去程序設(shè)計(jì)思想,該函數(shù)應(yīng)該寫成: int factorial ( int n ) int i,p; p=1; for ( i=1 ; i0按照該定義,按照該定義,! 就是一個(gè)簡單的條件語句和表達(dá)式計(jì)算,就是一個(gè)簡單的條件語句和表達(dá)式計(jì)算,可以編出如下函數(shù):可以編出如下函數(shù): int factorial ( int

50、n ) if ( n=0 ) return 1; else return n*factorial(n-1); 運(yùn)行結(jié)果演示運(yùn)行結(jié)果演示問題:在函數(shù)問題:在函數(shù) factorial 內(nèi)又調(diào)用函數(shù)內(nèi)又調(diào)用函數(shù) factorial 本身,行嗎?本身,行嗎?回答:行!回答:行!1. 首先按作用域規(guī)則,在函數(shù)首先按作用域規(guī)則,在函數(shù) factorial 內(nèi)又調(diào)用函數(shù)內(nèi)又調(diào)用函數(shù) factorial 本身是合法的;其次本身是合法的;其次 C 系統(tǒng)保證上述調(diào)用過程執(zhí)行的正確性,系統(tǒng)保證上述調(diào)用過程執(zhí)行的正確性,這就是遞歸。這就是遞歸。2. 從靜態(tài)行文看,在定義一個(gè)函數(shù)時(shí),若在定義它的內(nèi)部,又出從靜態(tài)行文看,

51、在定義一個(gè)函數(shù)時(shí),若在定義它的內(nèi)部,又出現(xiàn)對(duì)它本身的調(diào)用,則稱該函數(shù)是遞歸的,或遞歸定義的?,F(xiàn)對(duì)它本身的調(diào)用,則稱該函數(shù)是遞歸的,或遞歸定義的。3. 從動(dòng)態(tài)執(zhí)行角度看,當(dāng)調(diào)用一個(gè)函數(shù)時(shí),在進(jìn)入相應(yīng)函數(shù),還從動(dòng)態(tài)執(zhí)行角度看,當(dāng)調(diào)用一個(gè)函數(shù)時(shí),在進(jìn)入相應(yīng)函數(shù),還沒退出(返回)之前,又再一次的調(diào)用它本身,而再一次進(jìn)入沒退出(返回)之前,又再一次的調(diào)用它本身,而再一次進(jìn)入相應(yīng)函數(shù),則稱之為遞歸,或稱之為對(duì)相應(yīng)函數(shù)的遞歸調(diào)用。相應(yīng)函數(shù),則稱之為遞歸,或稱之為對(duì)相應(yīng)函數(shù)的遞歸調(diào)用。4. 稱遞歸定義的函數(shù)為遞歸函數(shù)。稱遞歸定義的函數(shù)為遞歸函數(shù)。上述函數(shù)上述函數(shù) factorial 就是遞歸函數(shù)。若計(jì)算就是遞

52、歸函數(shù)。若計(jì)算 5! ,使用函數(shù)調(diào)用,使用函數(shù)調(diào)用factorial(5) ,觀察其計(jì)算過程,觀察其計(jì)算過程: return 5*f(4)f(5)f=120f(4)f(3)f(2)f(1)f(0)return 4*f(3)return 3*f(2) return 2*f(1) return 1*f(0)return 1f=24f=6f=2f=1f=1int factorial ( int n ) if ( n=0 ) return 1; else return n*factorial(n-1); void main() printf(“%dn”,f(5) );運(yùn)行結(jié)果演示運(yùn)行結(jié)果演示遞歸程序設(shè)

53、計(jì)遞歸程序設(shè)計(jì)例例9.10 X 的的 n 次冪,可以定義為次冪,可以定義為0n *0n 11當(dāng)當(dāng)nnxxxfloat power ( float x, int n ) if ( n=0 )return 1 ;else return x * power(x,n-1) ;運(yùn)行結(jié)果演示運(yùn)行結(jié)果演示計(jì)算它的遞歸函數(shù)是計(jì)算它的遞歸函數(shù)是: float p ( int n , float x ) if ( n=0 ) return 1 ; else if (n=1) return x ; else return ( (2*n-1)*x*p(n-1,x) - (n-1)*p(n-2,x) )/n ; 1n

54、/)() 1()(1)-(21n x 0n 121當(dāng)當(dāng)當(dāng)nxpnxxpnxpnnn運(yùn)行結(jié)果演示運(yùn)行結(jié)果演示n遞歸程序設(shè)計(jì)的思想體現(xiàn)在:遞歸程序設(shè)計(jì)的思想體現(xiàn)在: 用逐步求精原則,先把一個(gè)問題分解成若干子問用逐步求精原則,先把一個(gè)問題分解成若干子問題題 這些子問題中有問題的與原始問題具有相同的特這些子問題中有問題的與原始問題具有相同的特征屬性,至多不過是某些參數(shù)不同,規(guī)模比原來征屬性,至多不過是某些參數(shù)不同,規(guī)模比原來小了小了 此時(shí),就可以對(duì)這些子問題實(shí)施與原始問題同樣此時(shí),就可以對(duì)這些子問題實(shí)施與原始問題同樣的分析算法,直到規(guī)模小到問題容易解決或已經(jīng)的分析算法,直到規(guī)模小到問題容易解決或已經(jīng)解

55、決時(shí)為止。解決時(shí)為止。 也就是說,若將整個(gè)問題的算法設(shè)計(jì)成一個(gè)函數(shù),也就是說,若將整個(gè)問題的算法設(shè)計(jì)成一個(gè)函數(shù),則解決這個(gè)子問題的算法就表現(xiàn)為對(duì)相應(yīng)函數(shù)的則解決這個(gè)子問題的算法就表現(xiàn)為對(duì)相應(yīng)函數(shù)的遞歸調(diào)用遞歸調(diào)用. 這里講的只是一般規(guī)律和程序設(shè)計(jì)思想。實(shí)際使用時(shí),設(shè)這里講的只是一般規(guī)律和程序設(shè)計(jì)思想。實(shí)際使用時(shí),設(shè)計(jì)遞歸函數(shù)要復(fù)雜得多。編寫遞歸程序要注意:計(jì)遞歸函數(shù)要復(fù)雜得多。編寫遞歸程序要注意: 1. 遞歸程序漂亮、好看、好讀、風(fēng)格優(yōu)美,但執(zhí)行效率遞歸程序漂亮、好看、好讀、風(fēng)格優(yōu)美,但執(zhí)行效率低。低。 2. 計(jì)算計(jì)算! 的函數(shù)即可以寫成循環(huán)形式,也可以寫成遞歸的函數(shù)即可以寫成循環(huán)形式,也可以

56、寫成遞歸形式。但是有些循環(huán)程序?qū)懗蛇f歸很困難。反之,有些遞歸形式。但是有些循環(huán)程序?qū)懗蛇f歸很困難。反之,有些遞歸程序?qū)懗裳h(huán)也很困難,甚至是不可能的。程序?qū)懗裳h(huán)也很困難,甚至是不可能的。 3. 終結(jié)條件。程序一定要能終止,不能無限遞歸下去。終結(jié)條件。程序一定要能終止,不能無限遞歸下去。 4. 使用全局量要特別小心。用不好,單元發(fā)生沖突,將使用全局量要特別小心。用不好,單元發(fā)生沖突,將導(dǎo)致程序出錯(cuò)。導(dǎo)致程序出錯(cuò)。例例9.12漢諾(漢諾( Hanoi )塔游戲)塔游戲n該問題又稱世界末日問題。相傳,古印度布拉瑪婆羅門神廟該問題又稱世界末日問題。相傳,古印度布拉瑪婆羅門神廟的憎侶們,當(dāng)時(shí)作一種被稱

57、為的憎侶們,當(dāng)時(shí)作一種被稱為 Hanoi塔的游戲。該游戲是:塔的游戲。該游戲是:在一個(gè)平板上,有三根鉆石針;在其中一根針上有成塔型落在一個(gè)平板上,有三根鉆石針;在其中一根針上有成塔型落放的大小不等的放的大小不等的64片金片;要求把這片金片;要求把這64片金片全部移到另一片金片全部移到另一根鉆石針上。移動(dòng)規(guī)則是:根鉆石針上。移動(dòng)規(guī)則是: 每次只允許移動(dòng)一片金片;每次只允許移動(dòng)一片金片; 移動(dòng)過程中的任何時(shí)刻,都不允許有較大的金片放在較小移動(dòng)過程中的任何時(shí)刻,都不允許有較大的金片放在較小的金片的上面;的金片的上面; 移動(dòng)過程中,三根鉆石針都可以利用,但是金片不許放在移動(dòng)過程中,三根鉆石針都可以利用

58、,但是金片不許放在除鉆石針以外的任何地方。除鉆石針以外的任何地方。n不論白天黑夜都有一個(gè)憎侶在移動(dòng)。據(jù)說當(dāng)不論白天黑夜都有一個(gè)憎侶在移動(dòng)。據(jù)說當(dāng)64片金片全部從片金片全部從一根鉆石針移到另一根鉆石針上那天,就是世界的末日。到一根鉆石針移到另一根鉆石針上那天,就是世界的末日。到那時(shí)他們的虔誠信徒可以升天,而其他人則要下地獄。那時(shí)他們的虔誠信徒可以升天,而其他人則要下地獄。當(dāng)然這只是傳說,按照規(guī)則把當(dāng)然這只是傳說,按照規(guī)則把 64 片金片全部從一根針移到另一根片金片全部從一根針移到另一根針上,總的移動(dòng)次數(shù)是針上,總的移動(dòng)次數(shù)是 264-1次,若一秒移動(dòng)一次,不發(fā)生錯(cuò)誤,次,若一秒移動(dòng)一次,不發(fā)生錯(cuò)

59、誤,日夜不停的移動(dòng),約需日夜不停的移動(dòng),約需 5849 億年。而太陽系的壽命僅有億年。而太陽系的壽命僅有100150億年而已。億年而已。請(qǐng)編程序,打印金片的移動(dòng)順序。請(qǐng)編程序,打印金片的移動(dòng)順序。解:不妨設(shè)三根鉆石針順次編號(hào)為解:不妨設(shè)三根鉆石針順次編號(hào)為 a 、b 、c ;開始所有;開始所有 64 片金片金片全部在片全部在 a 針上;現(xiàn)在要把它們移動(dòng)到針上;現(xiàn)在要把它們移動(dòng)到 b 針上;移動(dòng)過程中針上;移動(dòng)過程中 c 針針可以利用。如圖所示可以利用。如圖所示 . .64片片 a b c63片片 . .63片片 . .64片片1. 試想,若能夠把試想,若能夠把a(bǔ) 針上的針上的64片金片全部移動(dòng)

60、到片金片全部移動(dòng)到b針上,必須能夠針上,必須能夠先把先把a(bǔ)針頂部的針頂部的63片金片移到片金片移到c針上。針上。2. 現(xiàn)在,可以很容易的把現(xiàn)在,可以很容易的把a(bǔ)針上的一片金片移到針上的一片金片移到 b 針上。針上。3. 最后,再按照把最后,再按照把a(bǔ)針上的針上的63片金片移到片金片移到c針上的算法,把針上的算法,把c針上的針上的63片金片全部移到片金片全部移到b針上。從而,完成了題目要求的工作。針上。從而,完成了題目要求的工作。重新觀察上述過程:重新觀察上述過程: 怎樣進(jìn)行移動(dòng)?怎樣進(jìn)行移動(dòng)?開始就遇到把開始就遇到把a(bǔ)針最上邊的金片先移到針最上邊的金片先移到b針上,還是先移到針上,還是先移到c針上?針上?沒有任何根據(jù)作出決定,按一般方法是不好解決這個(gè)問題的。沒有任何根據(jù)作出決定,按一般方法是不好解決這個(gè)問題的。下邊換一個(gè)角度來考慮該問題:下邊換一個(gè)角度來考慮該問題:按這個(gè)想法,移動(dòng)按這個(gè)想法,移動(dòng) 64 片金片的問題可以被分解成:片金片的問

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(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ǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論