




版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領
文檔簡介
1、第9章 函數(shù)C 語言程序設計進階篇第1頁第1頁內(nèi)容概述函數(shù)定義、函數(shù)原型及申明。函數(shù)調(diào)用及參數(shù)傳遞。函數(shù)嵌套概念及其定義和使用辦法。函數(shù)遞歸概念及其定義和使用辦法。局部變量、全局變量以及最慣用兩種變量存儲類型auto和static。第2頁第2頁教學目的掌握自定義函數(shù)普通結構及定義函數(shù)辦法; 掌握形參、實參、函數(shù)原型等主要概念。掌握函數(shù)申明、函數(shù)調(diào)用普通辦法;熟悉函數(shù)嵌套概念,能定義和使用嵌套函數(shù)。理解局部變量、全局變量和變量存儲類型概念,掌握auto型和static型局部變量特點和使用辦法。 理解main函數(shù)參數(shù)及使用辦法。第3頁第3頁 在進行大型程序設計時,采用模塊化程序設計是一個十分有效辦
2、法。C語言在支持模塊化程序設計方面含有很強優(yōu)勢。C語言將函數(shù)作為程序設計基本單元,每個函數(shù)用于描述一個相對獨立基本操作,函數(shù)之間通過參數(shù)傳遞數(shù)據(jù)。采用模塊化程序設計思想可減少程序設計復雜度,提升程序可維護性。第4頁第4頁 求解較小問題算法和程序稱作“功效模塊”, 各功效模塊能夠先單獨設計,然后將求解所有子問題模塊組合成求解原問題程序。 由功效模塊構成程序結構圖主控模塊模塊1_1模塊1_n模塊2_1模塊2_n模塊n_1模塊n_n模塊1模塊2模塊n第5頁第5頁例 輸入兩個數(shù)輸出其中一個大數(shù)main() int a,b,c; int max(int x,int y) ; printf(”a= b=“
3、); scanf(“%d, %d”,&a,&b); c=max(a,b); printf(“max=%d”,c) ;int max(int x,int y) int z ; if (xy) z=x ; else z=y ; return (z) ;第6頁第6頁例 輸入年月日計算出該日為該年第幾天。 分析:(1)判斷年份是否為閏年。年份有閏年與平年之分,二者區(qū)分在于閏年二月為29天,平年二月為28天。因此,給定一個年份,首先應確定其是否是閏年。(2)求月份對應天數(shù)。月份不同,其對應天數(shù)不同,1、3、5、7、8、10、12月每個月為31天,4、6、9、11月每個月為30天,2月依據(jù)所在年份是否為閏
4、年來確定。(3)求總天數(shù)。分為經(jīng)歷完整月份天數(shù)與經(jīng)歷不完整月份天數(shù)。(4)輸出數(shù)據(jù)。輸出年月日及對應天數(shù)。第7頁第7頁(1)判斷閏年。int leap(int year) int lp; lp=(year%4=0&year%100!=0|year%400=0)?1:0; return lp;主控模塊判斷閏年求某月天數(shù)輸 出輸 入求總天數(shù)程序模塊結構圖第8頁第8頁(2)求某月天數(shù)。/*函數(shù)month_days調(diào)用函數(shù)leap判斷year是否為閏年*/int month_days(int year,int month) int d; switch(month) case 1: case 3: ca
5、se 5: case 7: case 8: case 10: case 12: d=31; break;case 2: d=leap(year)?29:28; break; /*若為閏年,d賦值29,不然賦值28*/ default: d=30; return d;第9頁第9頁(3)求天數(shù)和。/*函數(shù)days調(diào)用函數(shù)month_days,求各月份相應天數(shù)*/int days(int year,int month,int day) int i,ds=0; for (i=1;imonth;i+) ds=ds+month_days(year,i); ds=ds+day; return ds;第10頁
6、第10頁注意:在完整程序中,前三個函數(shù)應放在main( )函數(shù)之前。(4)主函數(shù)。void main() int year,month,day,t_day; printf(Input year-month-day:n); scanf(%d-%d-%d,&year,&month,&day); t_day=days(year,month,day); /*求天數(shù)和*/ printf(%d-%d-%d is %dth day of the year!n,year,month,day,t_day);第11頁第11頁 C語言源程序是由函數(shù)構成,函數(shù)是C源程序基本模塊,通過對函數(shù)模塊調(diào)用實現(xiàn)特定功效。C語言
7、中函數(shù)相稱于其它高級語言子程序。C語言不但提供了極為豐富庫函數(shù),還允許用戶自己定義函數(shù)。9.1 函數(shù)概述第12頁第12頁在C語言中可從不同角度對函數(shù)分類: 1從函數(shù)定義角度分類庫函數(shù)由C系統(tǒng)提供,用戶不必定義,也不必在程序中作類型闡明,只需在程序前包括有該函數(shù)原型頭文獻即可在程序中直接調(diào)用。用戶定義函數(shù)由用戶按需要編寫函數(shù)。對于用戶自定義函數(shù),不但要在程序中定義函數(shù)本身,并且在主調(diào)函數(shù)模塊中還必須對該被調(diào)函數(shù)進行類型闡明,然后才干使用。第13頁第13頁有返回值函數(shù) 有返回值函數(shù)被調(diào)用執(zhí)行完后將向調(diào)用者返回一個執(zhí)行結果,稱為函數(shù)返回值。無返回值函數(shù) 無返回值函數(shù)用于完畢某項特定處理任務,執(zhí)行完畢
8、后不向調(diào)用者返回函數(shù)值。2從函數(shù)功效角度分類:第14頁第14頁3從主調(diào)函數(shù)和被調(diào)函數(shù)之間數(shù)據(jù)傳送角度分類:無參函數(shù) 函數(shù)定義、函數(shù)闡明及函數(shù)調(diào)用中均不帶參數(shù)。主調(diào)函數(shù)和被調(diào)函數(shù)之間不進行參數(shù)傳送。這類函數(shù)通慣用來完畢一組指定功效,能夠返回或不返回函數(shù)值。有參函數(shù) 有參函數(shù)也稱為帶參函數(shù)。在函數(shù)定義及函數(shù)闡明時都有參數(shù),稱為形式參數(shù)(簡稱為形參)。在函數(shù)調(diào)用時也必須給出參數(shù),稱為實際參數(shù)(簡稱為實參)。第15頁第15頁1. 在C語言中,所有函數(shù)都是平等,即函數(shù)不能嵌套定義。但是函數(shù)之間允許互相調(diào)用,即允許嵌套調(diào)用。2. main()函數(shù)是程序執(zhí)行起點,也是程序執(zhí)行終點。3.一個C源程序有且僅有一
9、個主函數(shù)main()。闡明:第16頁第16頁 闡明部分; 執(zhí)行部分; 函數(shù)由函數(shù)闡明與函數(shù)體兩部分構成。 闡明部分; 執(zhí)行部分; 9.2 函數(shù)定義函數(shù)闡明函數(shù)體函數(shù)闡明函數(shù)體1無參函數(shù)類型闡明符 函數(shù)名()2有參函數(shù)類型闡明符 函數(shù)名(形式參數(shù)表)第17頁第17頁例 調(diào)用函數(shù)在屏幕上打印一行“*”#include stdio.hvoid print() /* 無參函數(shù) */ printf(*);main() print();程序運營結果:*第18頁第18頁#include stdio.hvoid print(int n) /* 一個形參 */ int i; for(i=0;in;i+) pri
10、ntf(*);main() int n; scanf(%d,&n); print(n); /* 一個實參 */例 調(diào)用函數(shù)在屏幕上打印指定數(shù)目“*”程序運營結果:10*第19頁第19頁#include stdio.hvoid print(int n,char ch) /* 兩個形參 */ int i; for(i=0;in;i+) printf(%c,ch);main() int n; char ch; scanf(%d %c,&n,&ch); print(n,ch); /* 兩個實參 */例 調(diào)用函數(shù)在屏幕上打印指定數(shù)目任意符號程序運營結果:10 $第20頁第20頁9.3.1 形式參數(shù)與實際
11、參數(shù) 函數(shù)參數(shù)分為形式參數(shù)和實際參數(shù)兩種。在定義函數(shù)時函數(shù)名后面括號中變量稱為形式參數(shù),簡稱形參。在調(diào)用函數(shù)時,函數(shù)名后面括號中表示式稱為實際參數(shù),簡稱實參。形式參數(shù)(簡稱形參)定義函數(shù)使用參數(shù)實際參數(shù)(簡稱實參)調(diào)用函數(shù)使用參數(shù)9.3 函數(shù)參數(shù)和返回值第21頁第21頁【例9.1】求 1+2+3+n值。#include stdio.hint s(int n) int i,s=0; for(i=1;i=1;i-) n=n+i; printf(n=%dn,n);void main() int n; printf(input numbern); scanf(%d,&n); s(n); printf(
12、n=%dn,n);程序運營情況下列:input number100n=5050n=100第23頁第23頁函數(shù)main函數(shù)snn實參與形參數(shù)據(jù)傳遞通過函數(shù)調(diào)用,將實參值傳遞給形參. 函數(shù)調(diào)用時,系統(tǒng)對參數(shù)處理環(huán)節(jié)為:計算各實參值,將實參值壓入形參棧中,然后執(zhí) 行函數(shù)體。當函數(shù)執(zhí)行完返回時,形參從棧頂彈出(取走)。 第24頁第24頁函數(shù)形參和實參含有下列特點: 形參變量只有在被調(diào)用時才分派內(nèi)存單元,在調(diào)用結束時,馬上釋放所分派內(nèi)存單元。 實參能夠是常量、變量、表示式、函數(shù)等,無論實參是何種類型量,在進行函數(shù)調(diào)用時,它們都必須含有擬定值,以便把這些值傳送給形參。 實參和形參在數(shù)量上、類型上、順序上應
13、嚴格一致,不然會發(fā)生“類型不匹配”錯誤。 函數(shù)調(diào)用中發(fā)生數(shù)據(jù)傳送是單向。第25頁第25頁 C函數(shù)計算結果通過 return語句返回, return語句表示形式下列:return 表示式;或 return(表示式);9.3.2 函數(shù)返回值 函數(shù)返回值也就是函數(shù)值,是指函數(shù)被調(diào)用之后,執(zhí)行函數(shù)體中程序段所取得并返回給主調(diào)函數(shù)值。第26頁第26頁對函數(shù)值有下列一些闡明:函數(shù)值只能通過return語句返回給主調(diào)函數(shù)。函數(shù)值類型和函數(shù)定義中函數(shù)類型應保持一致。假如兩者不一致,則以定義時函數(shù)類型為準,自動進行類型轉(zhuǎn)換。如函數(shù)值為整型,在函數(shù)定義時能夠省去類型闡明。不返回函數(shù)值函數(shù),能夠明擬定義為“空類型”
14、,類型闡明符為“void”。第27頁第27頁 一個函數(shù)一旦被定義,就可在程序其它函數(shù)中使用它,這個過程稱為函數(shù)調(diào)用。9.4.1 函數(shù)普通調(diào)用函數(shù)名(實際參數(shù)列表)函數(shù)調(diào)用形式:9.4 函數(shù)調(diào)用 實際參數(shù)普通為表示式,能夠是常量、變量(調(diào)用時必須有擬定值或擬定地址)。而形式參數(shù)必須為變量。第28頁第28頁函數(shù)表示式 函數(shù)作為表示式中一項出現(xiàn)在表示式中,以函數(shù)返回值參與表示式運算。這種方式要求函數(shù)是有返回值。 如 sum=s(n);函數(shù)語句 函數(shù)調(diào)用普通形式加上分號即構成函數(shù)語句。 如 printf(); scanf(); print();函數(shù)實參 函數(shù)作為另一個函數(shù)調(diào)用實際參數(shù)出現(xiàn)。 如 pri
15、ntf(“sum=%d”,s(n);C語言中,能夠用下列幾種方式調(diào)用函數(shù):第29頁第29頁9.4.2 實參到形參數(shù)據(jù)傳遞方式傳值方式傳遞數(shù)據(jù) 函數(shù)調(diào)用時,調(diào)用函數(shù)把實參值復制一份,傳送給被調(diào)用函數(shù)形參,從而實現(xiàn)調(diào)用函數(shù)向被調(diào)用函數(shù)數(shù)據(jù)傳送。實參對形參數(shù)據(jù)傳送是單向。傳址方式傳遞數(shù)據(jù) 函數(shù)調(diào)用時,將實參地址傳給被調(diào)用函數(shù),被調(diào)用函數(shù)從傳過來地址中取出實參所存數(shù)據(jù)進行操作。在傳址方式中,實參和形參占用是同一段內(nèi)存單元,因此形參值修改實際是就是對實參值修改。第30頁第30頁9.4.3 函數(shù)申明和函數(shù)原型 調(diào)用用戶自定義函數(shù)時,普通調(diào)用函數(shù)和被調(diào)用函數(shù)應在同一個文獻中,在調(diào)用函數(shù)中對被調(diào)用函數(shù)返回值類
16、型、函數(shù)名稱、函數(shù)形式參數(shù)類型進行闡明,這種闡明稱為函數(shù)申明。函數(shù)申明普通形式下列:類型名 函數(shù)名(類型1 形參1,類型n 形參n);或類型名 函數(shù)名(類型1,類型2,類型n);或類型名 函數(shù)名();函數(shù)申明是以語句形式出現(xiàn),因此其后有語句結束標識“;”。第31頁第31頁 假如被調(diào)函數(shù)返回值是整型或字符型時,能夠不對被調(diào)函數(shù)作闡明而直接調(diào)用。這時系統(tǒng)將自對被調(diào)函數(shù)返回值按整型處理。 當被調(diào)函數(shù)函數(shù)定義出現(xiàn)在主調(diào)函數(shù)之前時,在主調(diào)函數(shù)中也能夠不對被調(diào)函數(shù)再作闡明而直接調(diào)用。 如在所有函數(shù)定義之前,在函數(shù)外預先闡明了各個函數(shù)類型,則在以后各主調(diào)函數(shù)中,可不對被調(diào)函數(shù)作闡明。 對庫函數(shù)調(diào)用不需要再作
17、闡明,但必須把該函數(shù)頭文獻用include命令包括在源文獻前部。C語言要求存在下列幾種情況時,能夠省去主調(diào)函數(shù)中對被調(diào)函數(shù)函數(shù)闡明:第32頁第32頁例 編程求兩個整數(shù)階乘之和。#include void main() int m1,m2; long result; long fac(int); /* 申明后面定義函數(shù)fac*/ printf(請輸入整數(shù)m1,m2: ); scanf(%d,%d,&m1, &m2); result=fac(m1)+fac(m2); /* 函數(shù)調(diào)用 */ printf(%d!+%d!=%ld n, m1,m2,result);第33頁第33頁long fac(in
18、t n) /*定義函數(shù)fac,其功效是求n!*/ int i; long r=1; for(i=1;i=n;i+) r=r*i; return r;運營情況下列:請輸入整數(shù)m1,m2:3,53!+5!=126第34頁第34頁 所謂函數(shù)嵌套調(diào)用是指一個函數(shù)調(diào)用另一函數(shù)過程中又出現(xiàn)對其它函數(shù)調(diào)用。 這種嵌套調(diào)用層次原則上不限制。 函數(shù)1 函數(shù)2 函數(shù)3 . . 調(diào)用函數(shù)2 調(diào)用函數(shù)3 . 9.5函數(shù)嵌套調(diào)用第35頁第35頁【例9.2】計算s=22!+32!程序分析: 本題可編寫兩個函數(shù):一個是用來計算平方值函數(shù)f1();另一個是用來計算階乘值函數(shù)f2()。主函數(shù)先調(diào)f1()函數(shù)計算出平方值,再在f
19、1()函數(shù)中以平方值為實參,調(diào)用f2()函數(shù)計算其階乘值,然后返回到f1()函數(shù),再返回主函數(shù),在循環(huán)程序中計算累加和。第36頁第36頁#include stdio.hlong f2(int q) long c=1; int i; for(i=1;i=q;i+) c=c*i; return c;long f1(int p) int k; long r; k=p*p; r=f2(k); return r;程序代碼下列:void main() int i; long s=0; for (i=2;i=3;i+) s=s+f1(i); printf(ns=%ldn,s);第37頁第37頁9.6 函數(shù)遞
20、歸調(diào)用 一個函數(shù)在執(zhí)行過程中又直接或間接調(diào)用本身過程稱為遞歸調(diào)用,這種函數(shù)稱為遞歸函數(shù)。在遞歸調(diào)用中,主調(diào)函數(shù)又是被調(diào)函數(shù),執(zhí)行遞歸函數(shù)將重復調(diào)用其本身。第38頁第38頁遞歸不是一個數(shù)據(jù)結構,而是一個有效算法設計注意:遞歸算法必須是逐步有規(guī)律簡化,最后 要有一個非遞歸出口,不能出現(xiàn)無窮調(diào)用情況。第39頁第39頁階乘遞歸定義:(1)5!=5 4!(2)4!=4 3!(3) 3!=3 2!(4) 2!=2 1!(5) 1!=1 0!(6) 0!=1【例9.3】用遞歸調(diào)使用辦法計算n!第40頁第40頁long int fact(int n) int x; long int y; if (n=0) r
21、eturn 1; x=n-1; y=fact(x); return(n*y);用遞歸求階乘C語言實當代碼下列:#include void main() long int fn; fn=fact(5); printf(”nfn=%ld”,fn);第41頁第41頁求解階乘 5! 過程主程序 main : fact(5)參數(shù) 5 計算 5*fact(4) 返回 120參數(shù) 4 計算 4*fact(3) 返回 24參數(shù) 3 計算 3*fact(2) 返回 6參數(shù) 2 計算 2*fact(1) 返回 2參數(shù) 1 計算 1*fact(0) 返回 1參數(shù)傳遞結果返回遞歸調(diào)用回歸求值參數(shù) 0 直接定值 = 1
22、 返回 1第42頁第42頁n=5 5! 5*4! 4*3! 3*2! 2*1! 1 1 1*2 2*3 6*4 24*5120回推遞推遞歸結束條件n!= (n=1)n*(n-1)! (n1)第43頁第43頁【例9.4】用遞歸法將一個整數(shù)n逆序輸出。程序分析: 首先定義一個遞歸函數(shù)convert()。在主函數(shù)中調(diào)用convert()。convert()函數(shù)執(zhí)行過程是:程序首先將整數(shù)n最低位數(shù)字轉(zhuǎn)換為字符后并輸出;假如n10將結束函數(shù)執(zhí)行,不然就遞歸調(diào)用convert()函數(shù)本身。由于每次遞歸調(diào)用實參為n/10,即把n/10值賦予形參n,最后當n值小于10時不再作遞歸調(diào)用,形參n值也小于10,即i
23、=0,將使遞歸終止,然后逐層退回。第44頁第44頁#include stdio.h void convert(int n) int i; putchar(n%10+0); if (i=n/10)!=0) convert(i); void main() int number; printf(Input an integer:); scanf(%d,&number); if (number0) putchar(-); number=-number; convert(number); putchar(n); 程序代碼下列:第45頁第45頁補充:Hanoi塔問題 假設有三根木樁分別為A、B和C。在木樁
24、A上安置了N個圓盤,由上到下編號為1,2,N,編號越大圓盤直徑也越大。現(xiàn)需要將A木樁上N個圓盤借助B木樁移到C木樁上,且必須按照下述移動規(guī)則: 1. 直徑較小圓盤永遠置于直徑比較大圓盤上; 2. 圓盤可任意地由任何一個木樁移到其它木樁上; 3. 一次只能移動一個盤子。第46頁第46頁第47頁第47頁 漢諾塔(Tower of Hanoi)問題解題思緒: 假如 n=1,則將這一個盤子直接從A柱移到C柱上。否則,執(zhí)行下列三步: 1.用C柱做過渡,將A柱上(n-1)個盤子移到B柱上; 2.將A柱上最后一個盤子直接移到C柱上; 3.用A柱做過渡,將B柱上(n-1)個盤子移到C柱上。第48頁第48頁#i
25、nclude void Hanoi(int n,char x,char y,char z) if(n=1)printf(Move disk %d from %c to %cn,n,x,z);else Hanoi(n-1, x, z, y);printf(Move disk %d from %c to %cn,n,x,z);Hanoi(n-1, y, x, z);void main( ) int num;char one,two,three;scanf(%d ,&num);scanf(%c %c %c,&one,&two,&three);Hanoi(num,one,two,three);第49頁
26、第49頁變量數(shù)據(jù)類型變量應占用內(nèi)存空間大小變量在存儲空間分派時所限定邊界條件變量性質(zhì)變量數(shù)據(jù)類型變量存儲類型變量作用域變量生存期共同決定9.7變量作用域及存儲特性第50頁第50頁1. 變量按作用域:分為全局變量和局部變量2. 區(qū)別:見下表全局變量(外部變量)局部變量(內(nèi)部變量)定義位置函數(shù)體外函數(shù)體內(nèi)作用域從定義處到文獻結束從定義處到本函數(shù)結束舉例所有在函數(shù)體外定義變量(1) 所有在函數(shù)體內(nèi)定義變量(2)形式參數(shù)注意與局部變量同名處理不同樣函數(shù)中同名局部變量互不干擾9.7.1. 變量作用域 第51頁第51頁課堂練習1:分析下面程序運營結果。void f1( ) int t=2; a *= t;
27、 b /= t; void main( ) int a, b; printf(”Enter a,b:”); scanf(”%d,%d”, &a, &b); f1( ); /* 調(diào)用函數(shù)f1( ) */ printf (”a=%d,b=%d ”, a, b); 編譯程序會提醒犯錯: undefined symbol a 和 undefined symbol b 。為何?第52頁第52頁課堂練習2:分析下面程序運營結果 #include int a=2,b=4; /*a,b為全局變量*/ void f1( ) int t1,t2; t1 = a * 2; t2 = b * 3; b = 100;
28、printf (” t1=%d,t2=%dn”, t1, t2); void main() int b=4; f1( ); printf (” a=%d,b=%d ”, a, b); 程序輸出結果為: t1=4,t2=12 a=2, b=4 結論:全局變量與局部變量同名時,局部變量作用域屏蔽全局變量第53頁第53頁9.7.2 變量存儲特性 變量存儲特性變量生存期變量存儲類型變量存在時間,即變量存在性。變量存儲存儲媒介,如存儲器、外存儲器和CPU通用存儲器。變量屬性數(shù)據(jù)類型存儲特性第54頁第54頁變量(按存在時間)靜態(tài)存儲變量(static)動態(tài)存儲變量(auto)生存期為程序執(zhí)行整個過程,在該
29、過程中占有固定存儲空間,也稱永久存儲。只生存在某一段時間內(nèi)函數(shù)形參、函數(shù)體或分程序中定義變量,只有當程序進入該函數(shù)或分程序時才分派存儲空間,函數(shù)/分程序執(zhí)行完后,變量存儲空間又被釋放。第55頁第55頁C語言變量存儲特性可分四類:自動型(auto)、靜態(tài)型(static)、外部型(extern)和存儲器型(register)。 完整變量定義:存儲特性 數(shù)據(jù)類型 變量名;自動型變量auto 類型標識符 變量列表;經(jīng)常能夠缺省auto。函數(shù)內(nèi)定義局部變量、函數(shù)形式參數(shù)和函數(shù)體內(nèi)分程序局部變量。隨函數(shù)調(diào)用而存在,隨函數(shù)返回而消失,它們在一次調(diào)用結束到下一次調(diào)用開始之間不再占有存儲空間。作用域局限于所定
30、義函數(shù),其生存期就是函數(shù)生存期,在一個函數(shù)中引用另一個函數(shù)自動型變量值是錯誤。第56頁第56頁外部型變量“外部型變量”,是相對于在函數(shù)“內(nèi)部”闡明變量而言,它們在函數(shù)外部定義。外部型變量又稱為全局變量,在編譯時分派存儲單元。若變量定義與引用分別處于不同源文件中,即將變量作用域延伸到其它源文件,則需要在引用該變量源文件中對它進行申明,源文件或源文件中函數(shù)才干引用它。 若變量定義與引用處于同一源文件(即全局變量),在該源文件不同函數(shù)中能夠經(jīng)過變量名對這種變量進行直接引用,作用域在整個源文件。外部型變量申明形式:extern 類型標識符 變量名;在引用外部型變量文獻中不會為其分派內(nèi)存空間。 外部型變
31、量生存期為整個程序運營期。第57頁第57頁void main() /*在函數(shù)main中引用變量a不必申明*/extern int a; /*申明變量a為外部型變量*/void fac(int n) a=a*n;/*函數(shù)fac外已申明a為外部變量,函數(shù)fac能夠引用a*/ int a=1; /* 在s.c文獻定義了全局變量a */void fun() /*在函數(shù)fun中引用變量a不必申明*/ /*源文獻s.c*/*源文獻d.c*/比如:第58頁第58頁靜態(tài)型變量靜態(tài)型變量是指在編譯時分派存儲空間變量。static 類型標識符 變量列表;局部靜態(tài)變量全局靜態(tài)變量 函數(shù)內(nèi)部定義靜態(tài)變量 作用域與自動
32、型變量相同 當所在函數(shù)執(zhí)行結束后,靜態(tài)變量所占內(nèi)存單元并不釋放,其值仍然保留 函數(shù)外部定義靜態(tài)變量 在程序中凡未指明存儲類型全局變量均為全局靜態(tài)型變量 作用域僅限所在源程序文獻 第59頁第59頁int f(int a) int b=0; static int c=3; b+;c+; printf( %5d%5d%5d ,a,b,c); return(a+b+c);void main() int a=2,k; for(k=0;k3;k+) printf(%5dn,f(a);課堂練習3:分析下面程序運營結果。運營結果為:1 4 72 1 5 82 1 6 9第60頁第60頁存儲器型變量變量(按使用
33、 存儲媒介)內(nèi)存變量存儲器變量使用CPU中存儲器來存取變 量值前面所簡介變量都為內(nèi)存變量由編譯程序在內(nèi)存中分派存儲單元變量存取在內(nèi)存儲器中完畢。存儲器處于CPU內(nèi)部 可避免CPU頻繁訪問存儲器, 從而提升程序執(zhí)行速度。 數(shù)據(jù)內(nèi)存 運算器 運算器 結果 控制器 數(shù)據(jù)存儲器第61頁第61頁存儲器型變量不能定義為全局變量只限于整型、字符型和指針型局部變量。不能夠定義為靜態(tài)局部變量。只能為動態(tài)變量普通只允許同時定義兩個存儲器變量。register 類型名 變量名;存儲器型變量定義形式: register int a; register char b; 第62頁第62頁課堂練習4:閱讀程序,寫出運營結果
34、:void main() int i=1; static int a=10; register int b=5; printf(” i=%d,a=%d,b=%dn”,i,a,b); other(); printf(” i=%d,a=%d,b=%dn ”,i,a,b);other() int i; static int a; i=6; a=100; printf(” i=%d,a=%dn ”,i,a);i=1,a=10,b=5i=6,a=100i=1,a=10,b=5第63頁第63頁9.7局部變量和全局變量9.7.1局部變量在一個函數(shù)內(nèi)部定義變量是內(nèi)部變量,它只在本函數(shù)范圍內(nèi)有效,也就是說只有在
35、本函數(shù)內(nèi)才干使用它們,在此函數(shù)以外是不能使用這些變量。這稱為“局部變量”。 第64頁第64頁float f1( int a) /*函數(shù)f1 */int b,c; a、b、c有效 char f2(int x,int y) /*函數(shù)f2 */int i,j; x、y、i、j有效 void main( ) /*主函數(shù)*/int m,n; m、n有效 第65頁第65頁(1) 主函數(shù)中定義變量(m,n)也只在主函數(shù)中有效,而不由于在主函數(shù)中定義而在整個文獻或程序中有效。主函數(shù)也不能使用其它函數(shù)中定義變量。(2) 不同函數(shù)中能夠使用相同名字變量,它們代表不同對象,互不干擾。比如, 上面在f1函數(shù)中定義了變
36、量b和c,倘若在f2函數(shù)中也定義變量b和c,它們在內(nèi)存中占不同單元,互不混同。(3) 形式參數(shù)也是局部變量。比如上面f1函數(shù)中形參a,也只在f1函數(shù)中有效。其它函數(shù)能夠調(diào)用f1函數(shù),但不能引用f1函數(shù)形參a。(4) 在一個函數(shù)內(nèi)部,能夠在復合語句中定義變量,這些變量只在本復合語句中有效,這種復合語句也稱為“分程序”或“程序塊”。說明第66頁第66頁void main ( )int a,b;int c; c=a+b; c在此范圍內(nèi)有效 a,b在此范圍內(nèi)有效 第67頁第67頁9.7.2 全局變量在函數(shù)內(nèi)定義變量是局部變量,而在函數(shù)之外定義變量稱為外部變量,外部變量是全局變量(也稱全程變量)。全局變
37、量可認為本文獻中其他函數(shù)所共用。它有效范圍為從定義變量位置開始到本源文獻結束。 第68頁第68頁int p=1,q=5; /* 外部變量 */float f1(int a) /* 定義函數(shù)f1 */int b,c;char c1,c2; /* 外部變量*/char f2 (int x, int y) /* 定義函數(shù)f2 */int i,j; 全局變量p,q作用范圍 全局變量c1,c2作用范圍void main ( ) /*主函數(shù)*/int m,n; 第69頁第69頁例 9.15 有一個一維數(shù)組,內(nèi)放個學生成績,寫一個函數(shù),求出平均分、最高分和最低分。 #include float Max,Mi
38、n; *全局變量*void main() float average(float array ,int n); float ave,score10; int ; for(;) scanf(,); ave= average(,); printf(“max=%6.2fnmin=%6.2fn average=%6.2fn“,Max,Min,ave); 第70頁第70頁float average(float array ,int n) * 定義函數(shù),形參為數(shù)組 */ int ; float aver,sum=array; Max=Min=array; for(=;) if(arrayMax)Maxar
39、ray; else if(arrayMin)Min array; sum=sum+array; aver; return(); 運營情況下列: 第71頁第71頁第72頁第72頁提議不在必要時不要使用全局變量,原因下列: 全局變量在程序所有執(zhí)行過程中都占用存儲單元,而不是僅在需要時才開辟單元。 使用全局變量過多,會減少程序清楚性,人們往往難以清楚地判斷出每個瞬時各個外部變量值。在各個函數(shù)執(zhí)行時都也許改變外部變量值,程序容易犯錯。因此,要限制使用全局變量。第73頁第73頁它使函數(shù)通用性減少了,由于函數(shù)在執(zhí)行時要依賴于其所在外部變量。假如將一個函數(shù)移到另一個文獻中,還要將相關外部變量及其值一起移過去
40、。但若該外部變量與其它文獻變量同名時,就會出現(xiàn)問題,減少了程序可靠性和通用性。普通要求把程序中函數(shù)做成一個封閉體,除了能夠通過“實參形參”渠道與外界發(fā)生聯(lián)系外,沒有其它渠道。第74頁第74頁例 9.6 外部變量與局部變量同名#include int a=3,b=5; /* a,b為外部變量*/ a,b作用范圍void main ( ) int a=8; /*a為局部變量 */ 局部變量a作用范圍 printf (%d, max (a,b); 全局變量b作用范圍 max (int a, int b) /*a,b為局部變量 */ int c; c=ab?ab; 形參a、b作用范圍 return (
41、c); 運營結果為8 第75頁第75頁9.7 變量存儲類別 9.7. 動態(tài)存儲方式與靜態(tài)存儲方式 前面已簡介了從變量作用域(即從空間)角度來分,能夠分為全局變量和局部變量。那么從變量值存在時間(即生存期)角度來分,又能夠分為靜態(tài)存儲方式和動態(tài)存儲方式。 所謂靜態(tài)存儲方式是指在程序運營期間由系統(tǒng)分派固定存儲空間方式。而動態(tài)存儲方式則是在程序運營期間依據(jù)需要進行動態(tài)分派存儲空間方式。這個存儲空間能夠分為三部分: 程序區(qū)靜態(tài)存儲區(qū)動態(tài)存儲區(qū)第76頁第76頁在語言中每一個變量和函數(shù)有兩個屬性:數(shù)據(jù)類型和數(shù)據(jù)存儲類別。對數(shù)據(jù)類型,讀者已熟悉(如整型、字符型等)。存儲類別指是數(shù)據(jù)在內(nèi)存中存儲方式。存儲方式
42、分為兩大類:靜態(tài)存儲類和動態(tài)存儲類。詳細包括四種:自動(),靜態(tài)(),存儲器(),外部()。依據(jù)變量存儲類別,能夠知道變量作用域和生存期。 第77頁第77頁9.7. auto變量函數(shù)中局部變量,如不專門申明為static存儲類別,都是動態(tài)地分派存儲空間,數(shù)據(jù)存儲在動態(tài)存儲區(qū)中。函數(shù)中形參和在函數(shù)中定義變量(包括在復合語句中定義變量),都屬這類,在調(diào)用該函數(shù)時系統(tǒng)會給它們分派存儲空間,在函數(shù)調(diào)用結束時就自動釋放這些存儲空間。因此這類局部變量稱為自動變量。自動變量用關鍵字作存儲類別申明。比如:int (int ) *定義f函數(shù),為形參 *auto int ,; *定義、為自動變量 * 第78頁第7
43、8頁9.7.3用static申明局部變量 有時希望函數(shù)中局部變量值在函數(shù)調(diào)用結束后不消失而保留原值,即其占用存儲單元不釋放,在下一次該函數(shù)調(diào)用時,該變量已有值,就是上一次函數(shù)調(diào)用結束時值。這時就應當指定該局部變量為“靜態(tài)局部變量”,用關鍵字進行申明。通過下面簡樸例子能夠理解它特點。第79頁第79頁例97 考察靜態(tài)局部變量值。#include void main()int (int); ,; (; ( ,(); int (int ) int ; ; ; (); 第80頁第80頁對靜態(tài)局部變量闡明:(1) 靜態(tài)局部變量屬于靜態(tài)存儲類別,在靜態(tài)存儲區(qū)內(nèi)分派存儲單元。在程序整個運營期間都不釋放。而自動
44、變量(即動態(tài)局部變量)屬于動態(tài)存儲類別,占動態(tài)存儲區(qū)空間而不占靜態(tài)存儲區(qū)空間,函數(shù)調(diào)用結束后即釋放。(2) 對靜態(tài)局部變量是在編譯時賦初值,即只賦初值一次,在程序運營時它已有初值。以后每次調(diào)用函數(shù)時不再重新賦初值而只是保留上次函數(shù)調(diào)用結束時值。而對自動變量賦初值,不是在編譯時進行,而是在函數(shù)調(diào)用時進行,每調(diào)用一次函數(shù)重新給一次初值,相稱于執(zhí)行一次賦值語句。第81頁第81頁(3)如在定義局部變量時不賦初值話,則對靜態(tài)局部變量來說,編譯時自動賦初值(對數(shù)值型變量)或空字符(對字符變量)。而對自動變量來說,假如不賦初值則它值是一個不擬定值。這是由于每次函數(shù)調(diào)用結束后存儲單元已釋放,下次調(diào)用時又重新另
45、分派存儲單元,而所分派單元中值是不擬定。(4) 即使靜態(tài)局部變量在函數(shù)調(diào)用結束后仍然存在,但其它函數(shù)是不能引用它。第82頁第82頁例98 輸出到階乘值。#include void main()int fac(int ); int ; for(;) printf(%!=,fac();Int fac(int )static int ; *; (); 第83頁第83頁9.7.4 register變量 普通情況下,變量(包括靜態(tài)存儲方式和動態(tài)存儲方式)值是存儲在內(nèi)存中。當程序中用到哪一個變量值時,由控制器發(fā)出指令將內(nèi)存中該變量值送到運算器中。 通過運算器進行運算,假如需要存數(shù),再從運算器將數(shù)據(jù)送到內(nèi)存
46、存儲。 第84頁第84頁假如有一些變量使用頻繁(比如在一個函數(shù)中執(zhí)行次循環(huán),每次循環(huán)中都要引用某局部變量),則為存取變量值要花費不少時間。為提升執(zhí)行效率,語言允許將局部變量值放在CPU中存儲器中,需要用時直接從存儲器取出參與運算,不必再到內(nèi)存中去存取。由于對存儲器存取速度遠高于對內(nèi)存存取速度,因此這樣做能夠提升執(zhí)行效率。這種變量叫做存儲器變量,用關鍵字作申明。比如,例819中程序是輸出到n階乘值。第85頁第85頁例919使用存儲器變量#include void main ( )long fac(long); long i,n; scanf(%ld,&n); for(i=1;i=n;i+) pr
47、intf(%ld!=%ldn,i,fac(i);long fac(long n)register long i,f=1; /*定義存儲器變量*/ for (i=1;i=n;i+) f=f*i; return (f);第86頁第86頁.7.5用extern申明外部變量外部變量是在函數(shù)外部定義全局變量,它作用域是從變量定義處開始,到本程序文獻末尾。在此作用域內(nèi),全局變量可認為程序中各個函數(shù)所引用。編譯時將外部變量分派在靜態(tài)存儲區(qū)。有時需要用extern來聲明外部變量,以擴展外部變量作用城。第87頁第87頁1. 在一個文獻內(nèi)申明外部變量例9.20 用extern申明外部變量,擴展它在程序文獻中作用域
48、。#include void main() int max(int,int); *外部變量申明* extern A,B; printf(%dn,max(A,B); int A=13,B=-8; *定義外部變量* int max(int x,int y) *定義函數(shù) * int z; z=xy?x:y; return(z); 第88頁第88頁2. 在多文獻程序中申明外部變量例9.21 用extern將外部變量作用域擴展到其它文獻。 本程序作用是給定值,輸入和,求和am值。文獻file中內(nèi)容為:#include int A; /*定義外部變量*/void main() int (int); /*函
49、數(shù)申明*/ int ,; printf(enter the number a and its power m:n); scanf(,A,); A*; printf(*,A,); (); printf(*n,A,); 第89頁第89頁文獻file中內(nèi)容為:extern A; /*申明A為一個已定義外部變量*/ int (int );int ,; for(;) *A; (); 第90頁第90頁9.7.6用static申明外部變量有時在程序設計中希望一些外部變量只限于被本文獻引用,而不能被其它文獻引用。這時能夠在定義外部變量時加一個申明。比如:file1.c file2.cstatic int A;
50、 extern int A;void main ( ) void fun (int n) A=A*n; 第91頁第91頁9.7.7關于變量申明和定義對變量而言,申明與定義關系稍微復雜一些。在申明部分出現(xiàn)變量有兩種情況:一個是需要建立存儲空間(如:int a; ),另一個是不需要建立存儲空間(如:extern a;)。前者稱為“定義性申明”(defining declaration) ,或簡稱定義(definition)。 后者稱為“引用性申明”(referencing declaration)。廣義地說,申明包括定義,但并非所有申明都是定義。對“int a;” 而言,它既是申明,又是定義。而對
51、“extern a;” 而言,它是申明而不是定義。第92頁第92頁普通為了敘述以便,把建立存儲空間申明稱定義,而把不需要建立存儲空間申明稱為申明。顯然這里指申明是狹義,即非定義性申明。比如:void main() extern A; /*是申明不是定義。申明A是一 個已定義外部變量*/ int A; 第93頁第93頁9.7.8存儲類別小結(1) 從作用域角度分,有局部變量和全局變量。它們采用存儲類別下列:局部變量 |自動變量,即動態(tài)局部變量 (離開函數(shù),值就消失) |靜態(tài)局部變量(離開函數(shù),值仍保留) |存儲器變量(離開函數(shù),值就消失) |(形式參數(shù)能夠定義為自動變量或存儲 器變量)全局變量
52、|靜態(tài)外部變量(只限本文獻引用) |外部變量 (即非靜態(tài)外部變量,允許其它文獻引用)第94頁第94頁(2) 從變量存在時間(生存期)來區(qū)別,有動態(tài)存儲和靜態(tài)存儲兩種類型。靜態(tài)存儲是程序整個運營時間都存在,而動態(tài)存儲則是在調(diào)用函數(shù)時暫時分派單元。動態(tài)存儲 |自動變量(本函數(shù)內(nèi)有效) |存儲器變量(本函數(shù)內(nèi)有效) |形式參數(shù)(本函數(shù)內(nèi)有效)靜態(tài)存儲 |靜態(tài)局部變量(函數(shù)內(nèi)有效) |靜態(tài)外部變量(本文獻內(nèi)有效) |外部變量(其它文獻可引用)第95頁第95頁(3) 從變量值存儲位置來區(qū)別,可分為:內(nèi)存中靜態(tài)存儲區(qū) |靜態(tài)局部變量 |靜態(tài)外部變量(函數(shù)外部靜態(tài)變量) |外部變量(可為其它文獻引用)內(nèi)存中
53、動態(tài)存儲區(qū):自動變量和形式參數(shù)CPU中存儲器:存儲器變量第96頁第96頁() 關于作用域和生存期概念。從前面敘述能夠知道,對一個變量性質(zhì)能夠從兩個方面分析,一是變量作用域,一是變量值存在時間長短,即生存期。前者是從空間角度,后者是從時間角度。兩者有聯(lián)系但不是同一回事。 (5) static對局部變量和全局變量作用不同。對局部變量來說,它使變量由動態(tài)存放方式改變?yōu)殪o態(tài)存放方式。而對全局變量來說,它使變量局部化(局部于本文件),但仍為靜態(tài)存放方式。從作用域角度看,凡有static申明,其作用域都是局限,或者是局限于本函數(shù)內(nèi)(靜態(tài)局部變量),或者局限于本文件內(nèi)(靜態(tài)外部變量)。 第97頁第97頁9.
54、8 內(nèi)部函數(shù)和外部函數(shù) 函數(shù)本身在一個文獻中為全局。即一個文獻中定義函數(shù)可被該文獻所有其它函數(shù)調(diào)用。由于一個函數(shù)要被另外函數(shù)調(diào)用。 但是,也能夠指定函數(shù)不能被其它文獻調(diào)用。依據(jù)函數(shù)能否被其它源文獻調(diào)用,將函數(shù)區(qū)別為內(nèi)部函數(shù)和外部函數(shù)9.8.1 內(nèi)部函數(shù)只能被本文獻中其它函數(shù)調(diào)用 假如一個函數(shù)只能被本文獻中其它函數(shù)所調(diào)用,它稱為內(nèi)部函數(shù)。在定義內(nèi)部函數(shù)時,在函數(shù)名和函數(shù)類型前面加static。即static 類型標識符 函數(shù)名(形參表)如 static int fun ( int a , int b )第98頁第98頁例: static int max (a, b) int a, b; 則該函數(shù)
55、max只能被本文獻中其它函數(shù)引用,而不能被其它文獻中函數(shù)引用。第99頁第99頁 既可被本文獻中函數(shù)調(diào)用,也可被其它文獻中函數(shù)調(diào)用。9.8.2 外部函數(shù)(1) 在定義函數(shù)時,如果在函數(shù)首部最左端加關鍵字extern,則表示此函數(shù)是外部函數(shù),可供其他文獻調(diào)用。如函數(shù)首部可以寫為extern int fun (int a, int b)這樣,函數(shù)fun就可認為其他文獻調(diào)用。C語言規(guī)定,如果在定義函數(shù)時省略extern,則隱含為外部函數(shù)。本書前面所用函數(shù)都是外部函數(shù)。第100頁第100頁(2) 在需要調(diào)用此函數(shù)文獻中,用extern對函數(shù)作申明,表示該函數(shù)是在其它文獻中定義外部函數(shù) 第101頁第101
56、頁【例9.5】在一個字符串內(nèi)刪除指定字符(用外部函數(shù)實現(xiàn))。 file1.c(文獻1)main ( ) extern enter_string ( ); delete_string( ); extern print_string( ); /* 闡明本文獻要用到其它文獻中函數(shù)*/ char c; static char str80; enter_string (str); scanf (“ %c”, &c); delete_string (str, c); print_string (str);第102頁第102頁 file2.c (文獻2)#include stdio.h extern ent
57、er_string (str) /*定義外部函數(shù)enter_string*/char str80; gets (str); /* 讀入字符串str */第103頁第103頁 file3.c (文獻3)extern delete_string (str, ch) /* 定義外部函數(shù)delete_string */char str , ch; int i, j; for (i=j=0; stri!= 0 ; i+) if (stri!=ch) strj+=stri; stri= 0 ; 第104頁第104頁 file4.c (文獻4)extern print_string (str) /* 定義外
58、部函數(shù)print_string */char str ; printf(%s, str);運營情況下列:abcdefgcc abdefg第105頁第105頁實現(xiàn)辦法:在工程中加入相關C文獻: 添加file2.c,file3.c,file4.c(如右圖)或者: 在 main ( )前面加上: #include file2.c #include file3.c #include file4.c第106頁第106頁9.9 程序舉例【例9.6】用遞歸法將任意十進制整數(shù)轉(zhuǎn)換成R進制數(shù)(R在216之間)。程序分析: 將十進制整數(shù)n轉(zhuǎn)換成R進制數(shù)基本辦法是用n重復清除R,將所得余數(shù)逆序輸出即可。能夠定義變量
59、R和i,全局數(shù)組a用來存儲十進制數(shù)n除以R后余數(shù),由于要轉(zhuǎn)換非進制數(shù)范圍是216,因此定義了全局數(shù)組str。通過若干次遞歸調(diào)用后,a數(shù)組中存儲元素是n每次除以R后產(chǎn)生余數(shù)。在主函數(shù)中利用while循環(huán)將a數(shù)組中元素逆序輸出。第107頁第107頁程序代碼下列:#include stdio.h#include conio.hint R;int a16=0;char str17=0123456789ABCDEF;int i;void main() void notdecimal(int n); int n; printf(please input an integer number:); scanf
60、(%d,&n); 第108頁第108頁 if(n0) printf(%c,strai); printf(n);void notdecimal(int n) if(n!=0) ai+=n%R; notdecimal(n/R); 程序運營情況下列:please input an integer number:123please input R:21111011第109頁第109頁【例9.7】驗證任一偶數(shù)(不小于4)均可分解為兩個素數(shù)之和,編程求出所有這樣素數(shù)對。程序分析 本例主要是素數(shù)判斷問題。首先要找出從鍵盤任意輸入大偶數(shù)m從3m/2之內(nèi)所有素數(shù)i,然后再判斷m-i是否為素數(shù),若是則輸出素數(shù)對。
溫馨提示
- 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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 外包合同范文(17篇)
- 銀行更新改造借款合同(4篇)
- 不同標的運輸合同書(紅心番石榴)(4篇)
- 勞動合同協(xié)議書匯編(4篇)
- 廢土清理車輛租賃合同(20篇)
- 剪切機買賣合同10篇
- 租賃T汽車吊合同5篇
- 勞務派遣單位注銷后用工單位繼續(xù)用工應簽合同
- 2025年水稻種植承包合同7篇
- 抵押擔保的借款合同樣板6篇
- 2025年導游從業(yè)資格通關秘籍
- 啤酒采購合同協(xié)議書模板
- 中醫(yī)把脈入門培訓課件
- 高血糖癥的急救與護理
- 成人失禁性皮炎的預防與護理
- 技術信息收集與分析方法考核試卷
- 小學2025年國防教育課程開發(fā)計劃
- 2025屆安徽省示范高中皖北協(xié)作區(qū)高三下學期一模考試英語試題(原卷版+解析版)
- 防溺水家長測試題及答案
- 山東省公共衛(wèi)生臨床中心招聘考試真題2024
- Module4 Unit 2 The apples are falling down the stairs(教學設計)-2023-2024學年外研版(三起)英語六年級下冊
評論
0/150
提交評論