版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、第八章 函數 8.1 概述 C語言的程序除主函數外,還可以有若干個其他函數—塊狀結構。 對于較大的程序來說,往往把其中相對獨立的算法和功能定義成一個獨立的函數,以供需要的地方調用。 將一個程序分解成多個函數有如下優(yōu)點: (1) 減少代碼的重復現象。 (2) 便于分工合作。 (3) 便于閱讀。 (4) 便于獨立算法的代碼移植。,8.2 函數的定義和
2、調用 通過例子來說明如何定義和調用函數: 對于求兩個數中的最大值,有三個步驟: (1)從鍵盤輸入兩個數給a和b。 (2)求a和b中的最大值。 (3)輸出結果。 把求最大值的算法部分定義成一個獨立的函數:,函數類型 函數名 函數參數(形參)int max(int x,int y) main() { int z; { int a,b,c
3、; if(x>y)z=x; scanf(“%d%d”,&a,&b); else z=y; c=max(a,b); return(z); printf(“%d”,c); } } eg8-01.c x y z
4、 a b c,,,3,5,,,,,,說明:(1)程序由兩個函數組成,它們邏輯上相互獨立(功能、變量)。(2)程序的執(zhí)行總是從主函數開始,主函數總是被執(zhí)行一次,其他函數只有在被調用時才獲得控制。(3)函數調用有兩個作用:轉移控制權和傳遞參數。(4)return的作用也有兩個:交回控制權和返回結果。(5)實參可以是常量、變量或表達式,但類型要一致。,定義一個函數除考慮算法外就是:如何設計函數的參數,通過何
5、種途徑交回結果。 例:求自然數1—100中的素數之和。eg8-02.C ? prime( ? ) main() { int i; { int i,s=0; for(i=2;i<m;i++) for(i=1;i<=100;i++)
6、 if(m%i==0) ? if(prime(i) ) s+=i; ? printf(“\n %d”,s); } },int m),int,returm 0;,else return 1;
7、,return 1;,例:求5!+7!+4!的值。eg8-03.c ? fac( ? ){ int i,s=1; for(i=1;i<=n;i++) s*=i; return(s); }main(){ printf(“\n%d”,fac(5)+fac(7)+fac(4)); },int n,int,main(){ int s,fac(); 對被調函數聲明
8、 s=fac(5)+fac(7)+fac(4); printf(“\n%d”,s);}int fac(int n){ int i; int s=1; for(i=1;i<=n;i++) s*=i; return(s);} eg8-03-1.c不需聲明的情況:int char 主調函數在后(P165),若被調用的函數是庫函數,則應用#include命令將所調用函數的有關信息包含進來,如
9、:例:eg8-04.C #include “math.h” main() { float x,y; scanf(%f”,&x); y=sin(x); printf(“%f”,y); },8.3 函數的嵌套調用 C語言的函數定義雖然相互平行、相互獨立的,但可以嵌套調用,形如: 主函數 函數A 函數B,,,,,,,,,,,,,例:求多
10、項式 S= ∑i!+ ∑i!+ ∑i!的值。 eg8-05.Cfloat fac(int n) {…} ? sum( ? ) { int i; float s=0; for( i=? ) s+=fac(i); return(s); } } main(){ printf(“%f”,sum(
11、1,5)+sum(7,11)+sum(15,20); },1,5,7,11,15,20,int a, int b,float,i=a;i<=b;i++,8.4 函數的遞歸調用 在函數調用的過程中,出現直接或間接地調用該函數本身。如: f1() f2() f3() { { { f1(); f3(); f2(
12、); } } } 直接 間接 遞歸調用 遞歸調用,,,在實際應用中,有些問題既可用遞歸實現,也可不用遞歸(如求n!); 也有些問題非有遞歸不可(如漢諾塔問題);不少問題使用遞歸顯得很方便。 用遞歸方法求n! : 遞推公式:要給出結束遞歸的條件 1 當n=0或n
13、=1時 n!= n(n-1)! 當n>1時,,float fac(int n) main() { float f; { float f; if(n==0||n==1) f=1; f=fac(4); else f= ? printf(“\n%f”,f); return(f); }
14、 } eg8-06.c遞歸調用的執(zhí)行過程:,n*fac(n-1);,主函數 函數fac 函數fac 函數fac 函數fac問題:4個return的執(zhí)行順序?后進先出
15、!,f=fac(4);,n=4if(n==0||n==1)f=1;else f=n*fac(n-1);return(f),n=3if(n==0||n==1)f=1;else f=n*fac(n-1);return(f ),n=2if(n==0||n==1)f=1;else f=n*fac(n-1);return(f),n=1if(n==0||n==1)f=1;else f=n*fac(n-1);retur
16、n(f),,,,,,,,,,,,,,,例hanoi (漢諾)塔問題十九世紀未,歐洲珍奇商店出現一種漢諾塔游戲,并有推銷材料,說是古代印度布拉瑪廟里的僧侶們當時正在玩這種游戲,如果游戲結束,世界未日即來臨。一、規(guī)則及分析:n個盤子從一根針移到另一根針,每次只能移動一個盤子,不允許大盤在小盤上面。共有三根針,n個盤子由A移到C,需移動的次數是2n -1, 若64個盤子移動的次數為:264 - 1=18, 446, 744, 073
17、, 709, 551, 600一年的秒數是:365 x 24 x 60 x 60=3153600018446744073709511600÷31536000=58494217355年即:5849億年, 從能源角度推算, 太陽系壽命只有150億年,,,,,,,,A,B,C,二、方法與步驟1.將A上n-1個盤子借助C移到B2.把A上剩下一個盤子送到C3.將n-1個盤子從B借助A移到C三、實例:將A上3個盤子移到C
18、步驟:1.A上兩個盤子借助C移到B 2.A上最后一個盤子移到C 3.B上兩個盤子借助A移到C第一步進一步分解:1.1 A上一個盤子從A?C1.2 A上一個盤子從A?B1.3 C上一個盤子從C?B第二步進一步分解: A上最后一個盤子從A?C第三步進一步分解:3.1 B上一個盤子從B?A3.2 B上一個盤子從B?C3.3 A上一個盤子從A?C,,,,,,,,A,B,C,
19、結論:1~3步都是把n-1個盤子從一根針移到另一根針上,方法一樣,只是針的名稱不同而已,為使之一般化,將1~3步表示為:將one 針上的n-1個盤子借助 two針,移到three 針,只是對應關系不同。第一步對應關系:one ? A two ? C three ? B第三步對應關系:one ? B two ? A three ? C把上面三個步驟分成兩類操作:1.將 n - 1個盤子從一
20、根針移到另一根針上(n >1)2.將 1個盤子從一根針移到另一根針上hanoi(n,one,two,three)表示將n個盤子從one借助two移到three;move(x,y)表示將一個盤子從x移到y。 main n=3 n=2 n
21、=1 m=3 hanoi(3,A,B,C) hanoi(2,A,C,B) hanoi(1,A,B,C) hanoi(3,A,B,C) hanoi(2,A,C,B) hanoi(1,A,B,C) move(A,C)
22、 move(A,C) move(A,B) hanoi(1,C,A,B) hanoi(1,C,A,B)
23、 move(C,A) hanoi(2,B,A,C) hanoi(2,B,A,C) hanoi(1,B,C,A) hanoi(1,B,C,A)
24、 move(B,B) move(B,C) hanoi(1,A,B,C)
25、 hanoi(1,A,B,C) move(A,C),,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,eg8-0
26、7.c 用遞歸的方法解決漢諾塔程序如下:void move(char x, char y){printf(“%c?%c\ n”, x,y); }void hanoi(n, one, two, three)char one, two, three; int n;{if(n == 1) move(one,three); else {hanoi(n-1, one, three, two); move(one, t
27、hree); hanoi(n-1, two, one, three); }}main( ){int m; printf(“input the number of diskes:”); scanf(“%d”,&m); printf(“the step to moving %3d diskes:\ n”,m); hanoi(m, ‘A’, ‘B’, ‘C’ );}運行:input n
28、umber of diskes: 3? the step to moving 3 diskes: A ?C A ?B C ?B A ?C B ?A B ?C A ?C,8.5 數組作為函數的參數 當要傳遞的參數較少時,用簡單變量作為函數
29、的參數是方便的,但當要傳遞的參數是批量時,需要用數組作為函數的參數。,例:編寫函數,求100個數的平均數。eg8-08-1.Cfloat aver(int a[100]){ int i; float s=0; for(i=0;i<100;i++) s+=a[i] ; return(s/100); } main(){ int x[100]; float avg; 輸入
30、x; avg=aver(x); },對應的實參也應為數組型參數組的長度可省略,通用函數考慮: eg8-08-2.C float aver(int a[],int n) main() { int i; float s=0; { int x[100],n=100; for(i=0;i<n;i++) float av
31、g; s+=a[i]; 輸入x return(s/n); avg=aver(x,n); } },,,,,,,,,x,a,100,n,,n,值傳遞地址傳遞,100,n=5;,5,a[0]=3 ;,3,,例:閱讀程序:
32、main() swap(int a, int b){ int a=3,b=5; { int t; swap(a,b); t=a; a=b; b=t; printf(“\n%d,%d”,a,b); printf(“\n%d,%d”,a,b);}
33、 }eg8-09.C a b a b,3,5,,,以下程序的運行結果是 ? main() f ( int b[], int x){ int a[2]={2,4}, x=5; { x++; f
34、(a,x); b[0]+=2; printf(“%d,%d,%d”, b[1]+=3; x,a[0],a[1]);} }A) 5,2,4 B) 6,4,7 C) 6,2,4 D) 5,4,7eg8-10.
35、C,例:排序。void sort(int a[], int n) { int i,j,t; for(i=0;ia[j]){t=a[i];a[i]=a[j]; a[j]=t;}}main(){ int x[5],i; for(i=0;i<5;i++) scanf(“%d”,&x[i]); sort(x,5); for(i=0;i<5;i++) printf(“%4d”
36、,x[i]);} eg8-11.C,,,,,,x,a,例:方陣轉置(二維數組情況)。 eg8-12-1.Cat(int x[3][3]) x a{ int i,j,t; for(i=0;i<3;i++) for(j=i+1;j<3;j++){ t=x[i][j]; x[i][j]=x[j][i]; x[j][i]=t;}}
37、int a[3][3]; at(a); 行數不等情況?通用函數的處理?,,,,,,,,,,通用函數,按一維數組處理: eg8-12-2.Cat(int x[],int n)//n為行列數{ int i,j,t; for(i=0;i<n;i++) for(j=i+1;i<n;i++) { t=x[i*n+j]; x[i*n+j]=x[j*n+i]; x
38、[j*n+i]=t;}} int a[3][3]; at(a,3);,8.6 局部變量和全局變量 1、局部變量 在函數內定義的變量稱局部變量。 局部變量只在該函數內使用。 float f1(int x) int f2() main() { int i,j; { int a,b,c; { int m,n;
39、 ┊ ┊ { int i,j; ┊ ┊ ┊ } } } },說明:(1)任何函數(包括主函數)內定義的變量都是局部變量。(2)不同函數內定義的變量即使同名也互不干擾。 (3)復合語句中定義的變量只在該復合語句中有效
40、。,2 、 全局變量 在函數以外定義的變量,也稱外部變量。 全局變量可以為為本文件中其它函數所共用。它的作用范圍是從定義變量的位置開始到本源文件結束。,int p=1,q=5;float f1(int a){ int b,c; ┊}char c1,c2;char f2(int x,int y){ int i,j; ┊ }main(){ int m,n; ┊
41、},,,,,,,全局變量c1,c2的作用范圍,全局變量p,q的作用范圍,全局變量主要用于作為不同函數間數據傳遞的橋梁。 例:編寫一個函數,求n個數中的最大值、最小值和平均值。并編寫主函數完成:輸入100個數,調用該函數進行統計,輸出結果。,int max,min;float aver(int x[],int n){ int i; float s=0; min=x[0];max=x[0];
42、 for(i=0;imax)max=x[i]; if(x[i]<min)min=x[i]; s+=x[i]; } return (s/n); },用全局變量傳遞結果eg8-13-1.C,main(){ int a[100],i; float avg; for(i=0;i<100;i++) scanf(“%d”,&a[i]); avg=ave
43、r(a,100); printf(“\n%d,%d,%f”,max,min,avg);},分析不用全局變量的情況: eg8-13-2.Cfloat aver(int x[],int n){ int i; float s=0; int min=x[0],max=x[0]; for(i=0;imax)max=x[i]; if(x[i]<min)min=x[i]; s+
44、=x[i]; } return (s/n); }main(){ int a[100],i; float avg; int max,min; for(i=0;i<100;i++) scanf(“%d”,&a[i]); avg=aver(a,100); printf(“\n %d,%d,%f”,max,min,avg);},int max,min; float aver(i
45、nt x[],int n){ int i; float s=0; min=x[0];max=x[0]; for(i=0;imax)max=x[i]; if(x[i]<min)min=x[i]; s+=x[i]; } return (s/n); }main(){ int x[100],i; float avg; int max,min; for(i=0;i&
46、lt;100;i++) scanf(“%d”,&x[i]); avg=aver(x,100); printf(“\n %d,%d,%f”,max,min,avg);},分析全局變量與局部變量同名的情況eg8-13-3.C,,,max,min,max,min,,,強龍不壓地頭蛇!,閱讀程序,給出運行結果: eg8-14.Cint a=4,b=5,c=6; int f(int a,int b){
47、 a/=2; c+=b-a; return(a+b+c);}main(){ int a=2,d; d=f(a+2,a+b); printf(“\n %d,%d,%d,%d”, a,b,c,d);},4,5,,,,2,6,a,b,c,a,b,a,d,4,7,2,11,20,,,,,8.7 變量存儲類別 1、動態(tài)存儲方式和靜態(tài)存儲方式
48、 靜態(tài)存儲方式:在程序運行期間分配固定存儲單元的方式。動態(tài)存儲方式:在程序運行期間根據需要動態(tài)分配存儲單元的方式。,,變量,變量,局部變量,動態(tài)存儲方式變量,全局變量,靜態(tài)存儲方式變量,,空間角度,生存期角度,存放在靜態(tài)存儲區(qū)的變量:靜態(tài)存儲方式。 存放在動態(tài)存儲區(qū)的變量:動態(tài)存儲方式。,程序區(qū),靜態(tài)存儲區(qū),動
49、態(tài)存儲區(qū),程序開始運行時分配空間,運行結束時釋放主要存放全局變量和靜態(tài)局部變量,根據需要動態(tài)分配,動態(tài)釋放的區(qū)域主要存放動態(tài)局部變量和現場保護等,用戶區(qū),2、局部變量的存儲方式 每個局部變量在定義時可以指定其存儲方式,即對每個局部變量的定義除定義其數據類型外,還應定義其存儲方式。定義存儲方式用auto(自動的)static(靜態(tài)的)。如: int f1() int
50、f2() { auto int a=1; {static int b=1; ┊ ┊ } } 缺省時為auto,動態(tài)局部變量在函數調用時分配、賦初值,調用結束時釋放。 靜態(tài)局部變量在第一次調用時分配、賦初值,調用結束時不釋
51、放,其單元及其值仍保留,下次調用時不重新分配,不重新賦初值。 在實際應用中,如果希望在函數調用結束后仍保留某個局部變量的值給下次調用時使用,則可定義該變量為靜態(tài)的。,例:編寫一個函數計算:,y=,2x-1 第一次計算,3x+1 第二次計算,4x+2 其他,,float f ( float x) main(){ float y;
52、 {static int n=1; printf(“%f”,f(2.0));if(n==1)y=2*x-1; printf(“%f”,f(1.0));else if(n==2)y=3*x+1; printf(“%f”,f(3.0));else y=4*x+2; }
53、n++;return(y);}eg8-15.C,3 、全局變量的存儲方式全局變量都是靜態(tài)存儲方式,不允許用auto來定義全局變量??梢杂胹tatic來定義全局變量。如:static int x; 靜態(tài)全局變量(內部的)int y; 非靜態(tài)全局變量(外部的),對于非靜態(tài)全局變量,其它文件中的函數只要用extern加以外部說明,就可以訪問。 而對于靜態(tài)全局變量,只局限在本文件中的所有函數訪問,其它
54、文件中的函數即使用extern加以外部說明,也不能訪問。,int y; main() { y=0; } int f1() { y=2; },extern int y; int f3() { y=10; } int f4() { y=100; },static int y;,8.8 內部函數和外部函數 用extern加以定義的函數稱外部函
55、數 。 用extern加以定義的函數稱外部函數 。 extern int f1() static int f2() { { ┊ ┊ }
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
評論
0/150
提交評論