版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
第5章函數(shù)學(xué)習(xí)目標(biāo)本章主要介紹庫函數(shù)的使用、函數(shù)的定義和調(diào)用方法,然后介紹變量的作用域和存儲方式,最后講解內(nèi)部函數(shù)和外部函數(shù)的概念。通過本章的學(xué)習(xí),需要掌握函數(shù)的聲明、定義、調(diào)用和參數(shù)傳遞,理解函數(shù)的遞歸調(diào)用過程,理解變量的作用域和生存期的概念,了解內(nèi)部函數(shù)和外部函數(shù)的概念。第5章函數(shù)程序設(shè)計中也是如此,當(dāng)程序的功能比較多,如果把所有的程序代碼都寫在一個主函數(shù)(main函數(shù))中,就會使主函數(shù)變得繁雜、冗長,使閱讀和維護程序變得十分困難,因此我們往往會“生產(chǎn)”一些“部件”來分擔(dān)主函數(shù)的工作,即事先編好一批常用的函數(shù)來實現(xiàn)各種不同的功能,這就是模塊化的程序設(shè)計思路。圖5.1是一個程序中函數(shù)調(diào)用的示意圖。第5章函數(shù)圖5.1函數(shù)調(diào)用示意圖第5章函數(shù)例如sqrt函數(shù)用來求一個數(shù)的平方根,strlen函數(shù)用來求一個字符串中字符的個數(shù),把它們保存在函數(shù)庫中,這些稱為庫函數(shù)。再比如有的程序中要反復(fù)實現(xiàn)某一功能(例如打印歡迎信息、操作菜單等),就需要編寫能實現(xiàn)這些功能的用戶自定義函數(shù),以減少重復(fù)編寫程序段的工作量。圖5.2是從用戶角度對函數(shù)的分類。第5章函數(shù)圖5.2從用戶角度對函數(shù)的分類例5.1輸入兩個整數(shù),計算它們的和并輸出運算結(jié)果。#include<stdio.h>voidmain(){
int
add(int
x,inty);//聲明add函數(shù)
int
a,b,sum;
printf("請輸入兩個整數(shù):\n");
scanf("%d,%d",&a,&b);sum=add(a,b);//調(diào)用add函數(shù)printf("兩數(shù)之和:sum=%d\n",sum);}int
add(int
x,inty)//定義add函數(shù),完成求和運算{
ints;s=x+y;returns;}運行結(jié)果:請輸入兩個整數(shù):8,7兩數(shù)之和:sum=15例5.2以下關(guān)于結(jié)構(gòu)化程序設(shè)計的敘述中正確的是(2010年9月全國計算機等級考試二級C試題選擇題第11題)A)一個結(jié)構(gòu)化程序必須同時由順序,分支,循環(huán)三種結(jié)構(gòu)組成B)結(jié)構(gòu)化程序使用goto語句會很便捷C)在C語言中,程序的模塊化是利用函數(shù)實現(xiàn)的D)由三種基本結(jié)構(gòu)構(gòu)成的程序只能解決小規(guī)模的問題分析:程序通過多個函數(shù)來實現(xiàn)各種不同的功能,這就是模塊化的程序設(shè)計思路。正確的是C。例5.3以下選項中關(guān)于程序模塊化得敘述錯誤的是(2011年9月全國計算機等級考試二級C試題選擇題第12題)A)把程序分成若干相對獨立的模塊可便于編碼和調(diào)試B)把程序分成若干相對獨立,功能單一的模塊,可便于重復(fù)使用這些模塊C)可采用自底向上、逐步細(xì)化的設(shè)計方法把若干獨立模塊組裝成所要求的程序D)可采用自頂向下、逐步細(xì)化的設(shè)計方法把若干獨立模塊組裝成所要求的程序分析:程序模塊化的設(shè)計方法是自頂而下、逐步細(xì)化。所以上述表述中錯誤的是C。第5章函數(shù)5.1庫函數(shù)5.2函數(shù)定義和調(diào)用5.3 函數(shù)的嵌套調(diào)用和遞歸調(diào)用5.4局部變量和全局變量5.5 變量的存儲方式和生存期5.6內(nèi)部函數(shù)和外部函數(shù)5.1庫函數(shù)5.1.1標(biāo)準(zhǔn)庫函數(shù)5.1.2include命令行5.1.1標(biāo)準(zhǔn)庫函數(shù)它是由系統(tǒng)提供的,用戶不必自己定義而直接使用它們,只需在程序前包含有該函數(shù)定義的頭文件。5.1.1標(biāo)準(zhǔn)庫函數(shù)必須掌握或熟悉的庫函數(shù)有:(1)數(shù)學(xué)函數(shù)(頭文件math.h):abs()、fabs()、sin()、cos()、tan()、asin()、acos()、atan()、exp()、sqrt()、pow()、fmod()、log()、log10()。(2)字符串處理函數(shù)(頭文件string.h):strcmp()、strcpy()、strcat()、strlen()。(3)字符處理函數(shù)(頭文件ctype.h):isalpha()、isdigit()、islower()、isupper()、isspace()。5.1.1標(biāo)準(zhǔn)庫函數(shù)(4)輸入輸出函數(shù)(頭文件stdio.h):getchar()、putchar()、gets()、puts()、fopen()、fclose()、fprintf()、fscanf()、fgetc()、fputc()、fgets()、fputs()、feof()、rewind()、fread()、fwrite()、fseek()。(5)動態(tài)存儲分配函數(shù)(頭文件stdlib.h):malloc()、calloc()、realloc()、free()。5.1.2include命令行在程序中調(diào)用庫函數(shù)時,由于庫函數(shù)并不是由用戶在本文件中定義的,而是存放在函數(shù)庫中的,因此要將調(diào)用庫函數(shù)時所需的信息包含在#include指令指定的“頭文件”中。格式:#include<文件名>5.1.2include命令行功能:雙引號中的文件名即庫函數(shù)的文件了,一般存在于編譯器目錄下面,在計算機中搜索"*.h",就會找到庫函數(shù)的文件了。將庫函數(shù)包含到當(dāng)前的程序內(nèi),將指定的文件與當(dāng)前的源程序組成一個文件。例5.4輸出1到10數(shù)字的平方根和立方值。#include<stdio.h>#include<math.h>voidmain(){
intx=1;doublesquareroot,power;
while(x<=10){
squareroot=sqrt(x);//調(diào)用sqrt平方根函數(shù)
power=pow(x,3);//調(diào)用pow函數(shù)求x的立方
printf("%d的平方根:%3.2f\t%d的立方:%5.0f\n",
x,squareroot,x,power); x++;}}運行結(jié)果:1的平方根:1.001的立方:12的平方根:1.412的立方:83的平方根:1.733的立方:274的平方根:2.004的立方:645的平方根:2.245的立方:1256的平方根:2.456的立方:2167的平方根:2.657的立方:3438的平方根:2.838的立方:512 9的平方根:3.009的立方:72910的平方根:3.1610的立方:1000例5.5用程序?qū)崿F(xiàn)大小寫字母轉(zhuǎn)換。#include<stdio.h>#include<ctype.h>voidmain(){ charmsg1,msg2,toupper,tolower;
printf("請輸入一個小寫字母:"); msg1=getchar();
toupper=toupper(msg1);//調(diào)用toupper函數(shù)把小寫轉(zhuǎn)換為大寫
printf("轉(zhuǎn)換為大寫:%c\n",toupper);
printf("請輸入一個大寫字母:"); msg2=getchar();
tolower=tolower(msg2);//調(diào)用tolower函數(shù)把大寫轉(zhuǎn)換為小寫
printf("轉(zhuǎn)換為小寫:%c\n",tolower);}運行結(jié)果:請輸入一個小寫字母:r轉(zhuǎn)換為大寫:R請輸入一個大寫字母:Q轉(zhuǎn)換為小寫:q5.2函數(shù)定義和調(diào)用5.2.1函數(shù)定義的語法5.2.2函數(shù)的返回值5.2.3函數(shù)調(diào)用形式5.2.4函數(shù)說明5.2.5調(diào)用函數(shù)與被調(diào)用函數(shù)之間的數(shù)據(jù)傳遞5.2.1函數(shù)定義的語法C語言要求,在程序中使用的函數(shù),必須“先定義,后使用”。程序設(shè)計者需要在程序中自己定義想用的而庫函數(shù)并沒有提供的函數(shù),指定函數(shù)名字、函數(shù)返回值類型、函數(shù)實現(xiàn)的功能以及參數(shù)的個數(shù)與類型,將這些信息通知編譯系統(tǒng)。5.2.1函數(shù)定義的語法1.定義無參函數(shù)無參函數(shù)是指函數(shù)名后面的括號是空的,沒有任何參數(shù)。無參函數(shù)可以帶回或不帶回函數(shù)值,一般用來執(zhí)行指定的一組操作。格式:類型名函數(shù)名(){ 函數(shù)體 }
例如,函數(shù)getchar()就是無參函數(shù),它帶回的函數(shù)返回值就是鍵盤輸入的字符。5.2.1函數(shù)定義的語法2.定義有參函數(shù)有參函數(shù)。在調(diào)用函數(shù)時,主調(diào)函數(shù)在調(diào)用被調(diào)用函數(shù)時,通過參數(shù)向被調(diào)用函數(shù)傳遞數(shù)據(jù),一般情況下,執(zhí)行被調(diào)用函數(shù)時會得到一個函數(shù)值,供主調(diào)函數(shù)使用。格式:類型名函數(shù)名(形式參數(shù)表列){ 函數(shù)體 }例5.6編寫求兩個整數(shù)較大者的函數(shù)。intmax(intx,inty){
intz
;z=x>y
?x
:y
;return(z)
;}分析:這是一個函數(shù)定義的例子,intmax(intx,inty)是函數(shù)的首部。int是類型名,說明函數(shù)返回一個int類型的值;max是函數(shù)名,是用戶命名的標(biāo)識符;函數(shù)名后面的括號里是形式參數(shù)表列(形參),這里有x和y兩個,它們的類型是int,注意形參要逐個定義,各形參之間用逗號分開。5.2.2函數(shù)的返回值通常,函數(shù)調(diào)用的目的是使主調(diào)函數(shù)獲得一個確定的值,即函數(shù)的返回值。例如,我們在前面介紹的調(diào)用語句中有c=max(a,b);這就是調(diào)用函數(shù)max(a,b),函數(shù)執(zhí)行后返回一個函數(shù)值,并把值賦給變量c。5.2.2函數(shù)的返回值函數(shù)的返回值是通過函數(shù)中的return語句獲得的。如果需要從被調(diào)用函數(shù)帶回一個函數(shù)值,則被調(diào)用函數(shù)中必須包含return語句。5.2.2函數(shù)的返回值對于函數(shù)的返回值有如下說明:(1)一個函數(shù)中可以有一個以上的return語句,但被執(zhí)行的只有一個,即返回值只有一個,執(zhí)行到哪一個return語句,哪一個return語句就起作用。(2)return語句的形式可以是:return表達式;或return(表達式);或return;例如:return(x>y?x:y);(3)函數(shù)返回值的類型,應(yīng)當(dāng)是定義函數(shù)時指定的函數(shù)類型。例如函數(shù)定義為:floatadd(float
x,floaty){return(x+y);}函數(shù)類型為float,則通過return語句返回的值類型也應(yīng)為float。如果函數(shù)類型和return語句中表達式的值類型不一致,則以函數(shù)類型為準(zhǔn)。(4)對于不帶回值的函數(shù),定義函數(shù)為“void類型”。此時在函數(shù)體中不得出現(xiàn)return語句。例5.7以下關(guān)于return語句的敘述中正確的是(2010年3月全國計算機等級考試二級C試題選擇題第24題)A)一個自定義函數(shù)中必須有一條return語句B)一個自定義函數(shù)中可以根據(jù)不同情況設(shè)置多條return語句C)定義成void類型的函數(shù)中可以有帶返回值的return語句D)沒有return語句的自定義函數(shù)在執(zhí)行結(jié)束時不能返回到調(diào)用處分析:按照return語句的特點,正確的是B。5.2.3函數(shù)調(diào)用形式定義函數(shù)的目的是為了調(diào)用此函數(shù),以實現(xiàn)所需的操作。1.函數(shù)調(diào)用函數(shù)調(diào)用的一般形式:格式:函數(shù)名(實際參數(shù)表)例如:m=getchar();//調(diào)用無參函數(shù)
c=max(a,b);//調(diào)用有參函數(shù)2.函數(shù)調(diào)用的方式按函數(shù)調(diào)用在程序中出現(xiàn)的形式和位置來分,可以用以下幾種方式調(diào)用函數(shù):(1)函數(shù)表達式函數(shù)調(diào)用出現(xiàn)在另一個表達式中,用函數(shù)的返回值參與表達式的運算。這種方式要求函數(shù)是有返回值的。例如:c=max(a,b);這是一個賦值表達式,把函數(shù)max(a,b)的返回值賦予變量c。(2)函數(shù)調(diào)用語句函數(shù)調(diào)用的一般形式加上分號即構(gòu)成單獨的一個語句。例如:printf(“%d”,a);scanf(“%d”,&b);(3)函數(shù)參數(shù)函數(shù)調(diào)用作為另一個函數(shù)的實參。例如:m=max(a,max(b,c));其中max(b,c)是一次函數(shù)調(diào)用,它的值作為max()另一次調(diào)用的實參。經(jīng)過賦值后,m的值是a,b,c三者最大者。例5.8有以下程序(2009年9月全國計算機等級考試二級C試題選擇題第24題)#include<stdio.h>voidfun(intp){ intd=2; p=d++; printf("%d",p);}main(){ inta=1; fun(a);printf("%d\n",a); }程序運行后的輸出結(jié)果是:A)32 B)12 C)21 D)22分析:main()調(diào)用fun(),將實參a的值,拷貝一份傳遞給形參p,因此p也等于1;fun()函數(shù)體內(nèi)執(zhí)行了p=d++,自增運算符在d的后面,先取值后加1,則p=2,d=3,第一個打印結(jié)果為2;函數(shù)調(diào)用結(jié)束,形參不影響實參的值,因此實參a保持原值,第2個打印結(jié)果為1,選C。例5.9有以下函數(shù)(2011年3月全國計算機等級考試二級C試題填空題第9題)voidprt(char
ch,intn){inti;
for(i=1;i<=n;i++)
printf(i%6!=0?"%c":"%c\n",ch);}執(zhí)行調(diào)用語句prt('*',24);后,函數(shù)共輸出了
行*號。分析:調(diào)用語句prt('*',24);傳遞參數(shù),ch值為'*',n值為24,所以for循環(huán)從1到24。而printf語句其實是一個條件語句,首先判斷i%6!=0,如果i的值不能被6整除,則相當(dāng)于執(zhí)行printf("%c",ch);如果i的值能被6整除,則相當(dāng)于執(zhí)行printf("%c\n",ch);那么,從1~24,只有4次被6整除,所以共換行4次,即函數(shù)共輸出了
4行*號。5.2.4函數(shù)說明一般情況下,在使用用戶自定義函數(shù),并且被調(diào)函數(shù)與主調(diào)函數(shù)在同一個程序文件中時,應(yīng)在主調(diào)函數(shù)中對被調(diào)函數(shù)作函數(shù)說明。函數(shù)說明的作用是向編譯系統(tǒng)聲明將要調(diào)用此函數(shù),并將有關(guān)信息通知編譯系統(tǒng)。函數(shù)說明的一般形式:格式:類型名函數(shù)名(形式參數(shù)表列);例如:intadd(intx,inty);或者
int
add(int,int)
;以上兩種形式都可。第二種形式省略了參數(shù)名,因為編譯系統(tǒng)不檢查參數(shù)名,所以參數(shù)名可有可無。例5.10輸入兩個整數(shù),輸出其中較大者。要求用函數(shù)來實現(xiàn)。#include<stdio.h>voidmain(){intmax(intx,inty);//在main中對max函數(shù)說明
inta,b,c;printf("請輸入兩個整數(shù)
:");scanf("%d,%d",&a,&b);c=max(a,b);//調(diào)用max函數(shù)
printf("較大的數(shù)是
:%d\n",c);}intmax(intx,inty)//定義max函數(shù){intz; z=x>y?x:y; returnz;}運行結(jié)果:請輸入兩個整數(shù)
:7,8較大的數(shù)是
:8C語言在以下幾種情況時,可以省略函數(shù)說明:(1)當(dāng)被調(diào)函數(shù)的函數(shù)定義出現(xiàn)在主調(diào)函數(shù)之前時,在主調(diào)函數(shù)中可以不對被調(diào)函數(shù)進行說明而直接調(diào)用。(2)如果在所有函數(shù)定義之前,即文件開頭,已對各個函數(shù)進行了說明(稱為外部聲明),則在后面的主調(diào)函數(shù)中,可不再對被調(diào)函數(shù)作說明。(3)對庫函數(shù)的調(diào)用不需要作說明,只需把該函數(shù)的頭文件用include命令包含在源文件前面。5.2.5調(diào)用函數(shù)與被調(diào)用函數(shù)之間的數(shù)據(jù)傳遞函數(shù)參數(shù)分為形式參數(shù)和實際參數(shù),函數(shù)定義時出現(xiàn)的是形式參數(shù)。當(dāng)主調(diào)函數(shù)調(diào)用有參函數(shù)時,調(diào)用語句中出現(xiàn)的是實際參數(shù)。形式參數(shù)和實際參數(shù)的功能是作數(shù)據(jù)傳遞。函數(shù)調(diào)用時,主調(diào)函數(shù)把實際參數(shù)的值傳送給被調(diào)函數(shù)的形式參數(shù),從而實現(xiàn)主調(diào)函數(shù)向被調(diào)函數(shù)的數(shù)據(jù)傳遞。實際參數(shù)與形式參數(shù)個數(shù)應(yīng)相等,類型應(yīng)一致。傳遞參數(shù)時,實際參數(shù)與形式參數(shù)按順序?qū)?yīng),一一傳遞數(shù)據(jù)。例5.11有以下程序(2009年3月全國計算機等級考試二級C試題選擇題第24題)#include<stdio.h>int
f(int
x,inty){return((y-x)*x);}main(){inta=3,b=4,c=5,d;d=f(f(a,b),f(a,c));
printf("%d\n",d);}程序運行后的輸出結(jié)果是:A)10 B)9 C)8 D)7分析:main()調(diào)用f函數(shù),實參是函數(shù)f(a,b)和f(a,c)的返回值,所以首先求f(a,b)和f(a,c)的函數(shù)值,f(a,b)又是將a,b作為實參傳遞給函數(shù)形參,返回函數(shù)值3;同樣,f(a,c)返回函數(shù)值6;繼續(xù)計算函數(shù)f(3,6),獲得函數(shù)返回值9,賦值給變量d。選B。例5.12有以下程序(2011年3月全國計算機等級考試二級C試題選擇題第33題)#include<stdio.h>int
fun(int
x,inty){if(x!=y)return((x+y)/2);elsereturn(x);}main(){
inta=4,b=5,c=6; printf("%d\n",fun(2*a,fun(b,c)));}程序運行后的輸出結(jié)果是:A)3 B)6 C)8 D)12分析:要輸出fun(2*a,fun(b,c))的值,首先求fun(b,c)的函數(shù)值,b、c作為實參傳遞給函數(shù)形參,返回函數(shù)值5,注意fun函數(shù)的類型定義為int,所以返回值取整;繼續(xù)計算函數(shù)fun(8,5),獲得函數(shù)返回值6。選B。例5.13有以下程序(2011年9月全國計算機等級考試二級C試題選擇題第24題)#include<stdio.h>doublef(doublex);main(){doublea=0;inti;for(i=0;i<30;i+=10)a+=f((double)i);printf("%5.0f\n",a);}doublef(doublex){returnx*x+1;}程序運行后的輸出結(jié)果是:A)503B)401C)500D)1404分析:本題通過for循環(huán)3次調(diào)用f函數(shù)。第1次調(diào)用i=0,函數(shù)返回1,則a=1;第2次調(diào)用i=10,函數(shù)返回101,則a=102;第3次調(diào)用i=20,函數(shù)返回401,則a=503;循環(huán)條件已不成立,所以循環(huán)結(jié)束。選A。5.3 函數(shù)的嵌套調(diào)用和遞歸調(diào)用5.3.1 函數(shù)的嵌套調(diào)用5.3.2函數(shù)的遞歸調(diào)用5.3.1 函數(shù)的嵌套調(diào)用C語言函數(shù)的定義是互相獨立、互相平行的,函數(shù)之間不存在從屬關(guān)系。一個函數(shù)內(nèi)不能定義另一個函數(shù),即不能嵌套定義,但可以嵌套調(diào)用函數(shù),也就是說,在調(diào)用一個函數(shù)的過程中,又調(diào)用另一個函數(shù)。函數(shù)的嵌套調(diào)用過程如圖5.3所示。main()函數(shù)f1()函數(shù)f2()函數(shù)調(diào)用f1()函數(shù)調(diào)用f2()函數(shù)結(jié)束返回返回①②③④⑤⑥⑦⑧⑨圖5.3函數(shù)的嵌套調(diào)用圖5.3中所示的是兩層嵌套,其執(zhí)行過程是:(1)執(zhí)行main函數(shù)的開頭部分。(2)在main中調(diào)用f1函數(shù),程序轉(zhuǎn)到f1函數(shù)。(3)執(zhí)行f1函數(shù)過程中,調(diào)用f2函數(shù),程序轉(zhuǎn)到f2函數(shù)。(4)在f2函數(shù)執(zhí)行完后,程序返回到f1函數(shù)中調(diào)用f2函數(shù)的位置。(5)繼續(xù)執(zhí)行f1函數(shù)中未執(zhí)行的部分,執(zhí)行完后返回到main函數(shù)調(diào)用f1函數(shù)的位置。(6)繼續(xù)執(zhí)行main函數(shù)直到程序結(jié)束。例5.14輸入3個整數(shù),找出其中最大的數(shù)。用函數(shù)的嵌套調(diào)用來處理。#include<stdio.h>voidmain(){
intmax3(inta,int
b,intc);//對max3的函數(shù)聲明
int
a,b,c,max;
printf("請輸入3個整數(shù):");
scanf("%d%d%d",&a,&b,&c); max=max3(a,b,c);//調(diào)用max3函數(shù),找出3個數(shù)中最大數(shù)
printf("最大的數(shù)是:%d\n",max);}intmax3(inta,int
b,intc)//定義max3函數(shù){
intmax2(inta,intb);//對max2的函數(shù)聲明
intm; m=max2(a,b);//調(diào)用max2函數(shù),找出a、b中較大者,放在m中
m=max2(m,c);//調(diào)用max2函數(shù),找出m、c中較大者,即3個數(shù)中最大者
return(m);}intmax2(inta,intb)//定義max2函數(shù){
if(a>=b) returna;//若a較大,則返回a else returnb;//否則返回b}運行結(jié)果:請輸入3個整數(shù)
:785最大的數(shù)是
:8分析:從代碼可以看到,程序由主函數(shù)、max3函數(shù)、max2函數(shù)組成。主函數(shù)調(diào)用max3函數(shù),max3函數(shù)調(diào)用max2函數(shù),形成嵌套調(diào)用。5.3.2函數(shù)的遞歸調(diào)用在調(diào)用一個函數(shù)的過程中又出現(xiàn)直接或間接地調(diào)用該函數(shù)本身,稱為函數(shù)的遞歸調(diào)用。C語言允許函數(shù)的遞歸調(diào)用。在調(diào)用函數(shù)f的過程中,又要調(diào)用f函數(shù),這是直接遞歸調(diào)用,見圖5.4。如果在調(diào)用f1函數(shù)過程中又要調(diào)用f2函數(shù),而在調(diào)用f2函數(shù)過程中又要調(diào)用f1函數(shù),就是間接遞歸調(diào)用,見圖5.5。5.3.2函數(shù)的遞歸調(diào)用f函數(shù)調(diào)用f函數(shù)f1函數(shù)調(diào)用f2函數(shù)f2函數(shù)調(diào)用f1函數(shù)
圖5.4直接遞歸調(diào)用
圖5.5間接遞歸調(diào)用
5.3.2函數(shù)的遞歸調(diào)用可以看到,無論是直接遞歸調(diào)用還是間接遞歸調(diào)用,都會形成無終止的自身調(diào)用,這在程序中是不允許的。為了結(jié)束遞歸調(diào)用,可以用if語句來控制,只有在某一條件成立時才繼續(xù)執(zhí)行遞歸調(diào)用,否則就不再繼續(xù)。5.3.2函數(shù)的遞歸調(diào)用例5.15從鍵盤輸入一個正整數(shù)n,用遞歸方法求n!。分析:由于n!=n*(n-1)!,所以要計算n!,就必須先計算(n-1)!,而要知道(n-1)!,必須先計算(n-2)!,以此類推,要求2!,必須先知道1!,而1!=1。以上關(guān)系可用下面的遞歸公式表示:n!=n!=1(n=0,1)n*(n-1)!(n>1)程序代碼如下:#include<stdio.h>voidmain(){
int
fac(intn);//fac函數(shù)聲明
intn;
inty;
printf("請輸入一個正整數(shù):");
scanf("%d",&n);//輸入要求階乘的數(shù)
y=fac(n);
printf("%d!=%d\n",n,y);}int
fac(intn)//定義fac函數(shù){
intf;
if(n<0)//n不能小于0
printf("n<0,錯誤!"); elseif(n==0||n==1)//n=0或1時,n!=1,結(jié)束遞歸
f=1; elsef=fac(n-1)*n;//n>1時,n!=n*(n-1)! return(f);}運行結(jié)果:請輸入一個正整數(shù):55!=120例5.16設(shè)有如下函數(shù)定義(2011年3月全國計算機等級考試二級C試題選擇題第32題)int
fun(intk){if(k<1)return0;elseif(k==1)return1;elsereturnfun(k-1)+1;}若執(zhí)行調(diào)用語句:n=fun(3),則函數(shù)fun總共被調(diào)用的次數(shù)是A)2 B)3 C)4 D)5分析:這是一個函數(shù)遞歸調(diào)用的例題。當(dāng)執(zhí)行fun(3)時,形參k的值為3,執(zhí)行函數(shù)語句,由于不滿足k<1或k==1,則遞歸調(diào)用fun(2),同樣的情況,再次遞歸調(diào)用fun(1),這時返回函數(shù)值1,所以總共調(diào)用fun函數(shù)3次。選B。例5.17有以下程序(2011年9月全國計算機等級考試二級C試題填空題第11題)#include<stdio.h>voidfun(intx){if(x/5>0)fun(x/5);
printf("%d",x);}main(){fun(11);printf("\n");}程序運行后的輸出結(jié)果是
。分析:這也是函數(shù)遞歸調(diào)用的程序。當(dāng)執(zhí)行fun(11)時,因為11/5=2>0,所以遞歸調(diào)用fun(2),這時不再滿足if條件,則執(zhí)行printf語句,輸出2;接著回到上一層調(diào)用點,繼續(xù)后面語句的執(zhí)行,輸出11,所以程序運行的結(jié)果是2_11。這里2_11之間的短橫表示輸出時的空格。printf()函數(shù)是格式輸出函數(shù),輸出時應(yīng)注意它的格式要求。5.4局部變量和全局變量5.4.1 局部變量5.4.2全局變量在C語言中,一個變量能夠起作用(被引用)的程序范圍,稱為變量的作用域,即一個變量定義之后,在何處能夠使用該變量。若變量在整個程序范圍內(nèi)的各個函數(shù)中均可被訪問,稱其為全局變量。如果變量僅在特定的函數(shù)或程序塊內(nèi)可被訪問,不能被其他函數(shù)或程序訪問,稱其為局部變量。5.4.1 局部變量上面提過,變量的作用域決定于變量的定義位置。在一個函數(shù)內(nèi)部定義的變量只在本函數(shù)范圍內(nèi)有效,在此函數(shù)以外是不能使用這些變量的;在復(fù)合語句內(nèi)定義的變量只在本復(fù)合語句范圍內(nèi)有效,只有在本復(fù)合語句內(nèi)才能引用它們。這些都是局部變量。
例如:floatf1(inta)//a,b,c在f1函數(shù)中有效{int
b,c;...}intf2(intx,inty)//x,y,i,j在f2函數(shù)中有效{int
i,j
;{
intc;//c在復(fù)合語句中定義,只在此語句范圍內(nèi)有效
c=i+j;}...}voidmain()//m,n在main函數(shù)中有效{int
m,n;...}5.4.2全局變量全局變量也稱為外部變量,它是在函數(shù)之外定義的變量。全局變量不屬于某一個特定的函數(shù),它可以為本文件中其他函數(shù)所共用,它的有效范圍為從定義變量的位置開始到本源文件結(jié)束。5.4.2全局變量int
a,b;//定義外部變量a,b,全程序有效floatf1()//定義f1函數(shù){...}floatx,y;//定義外部變量x,y,從定義到程序結(jié)束都有效intf2(){
inti;//i在f2函數(shù)中定義,是局部變量
...}voidmain()//定義main函數(shù){...}5.4.2全局變量設(shè)置全局變量的作用是增加函數(shù)間數(shù)據(jù)聯(lián)系。由于全局變量是各個函數(shù)都能引用的變量,因此如果在一個函數(shù)中改變了全局變量的值,就能影響到其他函數(shù)中全局變量的值,相當(dāng)于各個函數(shù)間有直接的傳遞通道。例5.18輸入正方體的長寬高l,w,h,求其體積即3個面的面積。#include<stdio.h>ints1,s2,s3;//定義全局變量s1,s2,s3int
vs(int
a,int
b,intc)//定義求體積及面積的函數(shù)vs{
intv; v=a*b*c; s1=a*b;//函數(shù)可訪問全局變量
s2=b*c;//為s1,s2,s3賦值
s3=a*c; returnv;//返回體積值}voidmain(){
int
v,l,w,h;
printf("請輸入正方體的長寬高:");
scanf("%d%d%d",&l,&w,&h); v=vs(l,w,h);//調(diào)用vs函數(shù)求體積、面積
printf("正方體的體積v=%d,各面面積s1=%d,s2=%d,s3=%d\n",v,s1,s2,s3);}運行結(jié)果:請輸入正方體的長寬高:345正方體的體積v=60,各面面積s1=12,s2=20,s3=15分析:本例通過函數(shù)來計算正方體的體積及3個面的面積,但函數(shù)只能返回一個值,所以把3個面積定義為全局變量,這樣一般函數(shù)和主函數(shù)都可以訪問,我們在函數(shù)中計算出面積值,賦給全局變量,主函數(shù)也訪問這些變量來獲取它們的值。這也反映出全局變量是實現(xiàn)函數(shù)之間數(shù)據(jù)通訊的有效方法。例5.19分析下面程序。#include<stdio.h>inta=3,b=5;//定義全局變量a,bvoidmain(){
int
add(int
a,intb);//函數(shù)聲明
inta=8;//定義局部變量a
printf("兩數(shù)之和:%d\n",add(a,b));//調(diào)用add函數(shù),a,b為實參}int
add(int
x,inty){ return(x+y);//求兩數(shù)之和}運行結(jié)果:兩數(shù)之和:13分析:在本例中,既定義了全局變量a、b,也定義了同名局部變量a。局部變量a是在主函數(shù)中定義的,其作用域為主函數(shù),在此范圍內(nèi),全局變量a就失去作用,所以當(dāng)調(diào)用函數(shù)add(a,b)時,傳遞的實參a是局部變量a,而不是全局變量a。所以輸出結(jié)果為13。例5.20有以下程序(2009年9月全國計算機等級考試二級C試題填空題第11題)#include<stdio.h>inta=5;voidfun(intb){inta=10;a+=b;printf("%d",a);}main(){intc=20;fun(c);a+=c;printf("%d\n",a);}程序運行后的輸出結(jié)果是
。分析:程序首先定義了全局變量a=5。當(dāng)執(zhí)行主函數(shù)main時,會調(diào)用fun函數(shù),fun函數(shù)中定義了局部變量a=10,則全局變量a失去作用,所以輸出30。返回到主函數(shù)調(diào)用點繼續(xù)執(zhí)行,主函數(shù)中的a是全局變量a,所以輸出25,因此程序運行的結(jié)果是3025。5.5 變量的存儲方式和生存期5.5.1 動態(tài)存儲方式與靜態(tài)存儲方式5.5.2 局部變量的存儲類別5.5.3 全局變量的存儲類別5.5.4 存儲類別小結(jié)5.5.1 動態(tài)存儲方式與靜態(tài)存儲方式在C語言中,變量不僅有確定的數(shù)據(jù)類型定義,還有存儲方式的定義。變量的存儲方式是其存儲屬性,即變量在內(nèi)存中的存儲方法,不同的存儲方法,將影響變量值存在的時間(即生存期)。變量的生存期是指程序在運行期間,從給變量分配存儲單元,到所分配的存儲單元被系統(tǒng)收回的那段時間。有的變量在程序運行的整個過程都是存在的,始終占有固定的存儲單元;而有的變量則是在調(diào)用其所在的函數(shù)時才臨時分配存儲單元,而在函數(shù)調(diào)用結(jié)束后該存儲單元就馬上釋放了,變量也就不存在了在C語言中,變量的存儲有兩種方式:靜態(tài)存儲方式和動態(tài)存儲方式。靜態(tài)存儲方式是指在程序運行期間由系統(tǒng)分配固定的存儲空間的方式,而動態(tài)存儲方式則是在程序運行期間根據(jù)需要進行動態(tài)的分配存儲空間的方式。內(nèi)存中提供給程序的存儲空間通常分為3部分,如圖5.6所示。程序區(qū)靜態(tài)存儲區(qū)動態(tài)存儲區(qū)圖5.6程序占用的內(nèi)存空間程序的數(shù)據(jù)分別存放在靜態(tài)存儲區(qū)和動態(tài)存儲區(qū)中。全局變量全部存放在靜態(tài)存儲區(qū)中,在程序開始執(zhí)行時就給全局變量分配存儲區(qū),程序執(zhí)行完畢即釋放。在程序執(zhí)行過程中它們占據(jù)固定的存儲單元,而不是動態(tài)進行分配和釋放。在動態(tài)存儲區(qū)中則存放以下數(shù)據(jù):(1)函數(shù)形式參數(shù)。在調(diào)用函數(shù)時給形參分配存儲空間。(2)函數(shù)調(diào)用時的現(xiàn)場保護和返回地址等。以上數(shù)據(jù)在函數(shù)調(diào)用開始時分配動態(tài)存儲空間,函數(shù)結(jié)束時釋放這些空間。注意在兩次調(diào)用同一函數(shù)時,每次分配給局部變量的存儲空間不一定相同。在定義和聲明變量時,一般應(yīng)同時指定其數(shù)據(jù)類型和存儲類別。如果不指明存儲類別,表示采用默認(rèn)方式(即系統(tǒng)隱含指定的某一種存儲類別)。所以變量的完整定義形式為:格式:存儲類別數(shù)據(jù)類型變量名;C的存儲類別包括4種:自動(auto)、靜態(tài)(static)、寄存器(register)、外部(extern)。不同的存儲類別,將影響到變量的生存期以及作用域。5.5.2 局部變量的存儲類別1.自動變量(auto)在函數(shù)內(nèi)或復(fù)合語句中定義的變量,如果不指定其存儲類別為static,那么就是自動存儲變量,其關(guān)鍵字為auto。自動存儲變量都是動態(tài)地分配存儲空間的,數(shù)據(jù)存儲在動態(tài)存儲區(qū)中,即調(diào)用函數(shù)時,系統(tǒng)會給這些變量分配存儲空間,在函數(shù)調(diào)用結(jié)束時就自動釋放這些存儲空間。
例如:intfun(){autointnum;//定義num為自動變量
…}實際上,我們在定義這類局部變量時,往往省略其存儲類別,因為關(guān)鍵字“auto”可以省略,不寫auto則隱含指定為自動存儲類別。所以以上函數(shù)定義可寫作:intfun(){
intnum;//定義num為自動變量
…}2.靜態(tài)局部變量(static)有時需要函數(shù)中局部變量的值在函數(shù)調(diào)用結(jié)束后不消失,即其占用的存儲單元在整個程序運行期間都不釋放,那么可以將該局部變量定義為靜態(tài)局部變量,用關(guān)鍵字static進行聲明。例如:staticint
m,n;例5.21靜態(tài)局部變量與自動局部變量的比較。#include<stdio.h>voidmain(){ voidtest();//test函數(shù)聲明
int
i,a=0;//自動局部變量a,在主函數(shù)中定義
for(i=0;i<3;i++) test();//調(diào)用test() {
inta=10;//自動局部變量a,在復(fù)合語句中定義
a=a*10;
printf("復(fù)合語句中:a=%d\n",a); } a=a+10;
printf("主函數(shù)中:a=%d\n",a);}voidtest(){ staticinta=5;//靜態(tài)局部變量a,賦初值一次
printf("靜態(tài)變量:a=%d\n",a); a=a+10;}運行結(jié)果:靜態(tài)變量:a=5靜態(tài)變量:a=15靜態(tài)變量:a=25復(fù)合語句中:a=100主函數(shù)中:a=10分析:首先在主函數(shù)中循環(huán)調(diào)用test()函數(shù),函數(shù)中的靜態(tài)局部變量a,在每次函數(shù)調(diào)用結(jié)束后,它的值并不消失,所以循環(huán)調(diào)用時其值能夠保持連續(xù)性。復(fù)合語句和主函數(shù)中定義了同名自動局部變量a,注意其不同的作用域。例5.22若函數(shù)中有定義語句:intk;則(2009年3月全國計算機等級考試二級C試題選擇題第12題)A)系統(tǒng)將自動給k賦初值0B)這時k中的值無定義C)系統(tǒng)將自動給k賦初值-1D)這時k中無任何值分析:函數(shù)中定義intk;則k應(yīng)是自動存儲變量,它不同于靜態(tài)存儲變量,系統(tǒng)不會自動給k賦值,所以這時k中的值無定義。選B。例5.23有以下程序(2011年3月全國計算機等級考試二級C試題選擇題第34題)#include<stdio.h>intfun(){staticintx=1;x*=2;returnx;}main(){int
i,s=1;for(i=1;i<=3;i++)s*=fun();printf("%d\n",s);}程序運行后的輸出結(jié)果是:A)0B)10C)30D)64分析:主函數(shù)中通過循環(huán),共3次調(diào)用fun()函數(shù)。在fun()函數(shù)中,定義了靜態(tài)局部變量x=1。第一次調(diào)用fun(),返回x值為2;第二次調(diào)用fun(),由于靜態(tài)變量保留上一次函數(shù)調(diào)用的結(jié)果,所以乘以2后返回x值為4;第三次調(diào)用fun(),返回x值為8,所以在主函數(shù)中,s=2*4*8=64。選D。例5.24有以下程序(2009年9月全國計算機等級考試二級C試題選擇題第34題)#include<stdio.h>
int
f(intn);main(){inta=3,s;
s=f(a);s=s+f(a);printf("%d\n",s);}
int
f(intn){staticinta=1;n+=a++;returnn;}
程序運行以后的輸出結(jié)果是:
A)7B)8C)9D)10分析:在函數(shù)f()中定義了靜態(tài)變量a,第1次調(diào)用f函數(shù),返回4,同時在函數(shù)中靜態(tài)變量a的值自增為2;第2次調(diào)用f函數(shù),靜態(tài)變量會保留上一次的結(jié)果,所以返回5,則s=9。選C。例5.25有以下程序(2011年9月全國計算機等級考試二級C試題選擇題第33題)#include<stdio.h>int
f(intm){staticintn=0; n+=m; returnn;}main(){intn=0;
printf("%d,",f(++n));printf("%d\n",f(n++));}程序運行后的輸出結(jié)果是:A)1,2B)1,1 C)2,3 D)3,3分析:主函數(shù)中定義n=0,調(diào)用函數(shù)f(++n),即f(1),在函數(shù)f中定義靜態(tài)變量n,加1后返回1;主函數(shù)再次調(diào)用f(n++),++運算符在變量的后面,所以還是f(1),函數(shù)中的靜態(tài)變量保留上一次的值,所以在原值1的基礎(chǔ)上加1,返回2,最終輸出1,2。選A。3.寄存器變量(register)一般情況下,變量值是存放在內(nèi)存中的,但我們也知道,計算機的CPU內(nèi)部包含若干個通用寄存器,硬件在對數(shù)據(jù)操作時,常常是先把數(shù)據(jù)取到寄存器(或一部分取到寄存器),然后進行操作。而且,計算機對寄存器中數(shù)據(jù)的操作速度要遠(yuǎn)遠(yuǎn)快于對內(nèi)存中數(shù)據(jù)的操作速度。為提高程序的運行速度,可將使用十分頻繁的局部變量說明為寄存器變量,將其存儲在CPU的寄存器中。寄存器變量定義的關(guān)鍵字是register,例如:registerintn;5.5.3 全局變量的存儲類別全局變量(即外部變量)是在函數(shù)的外部定義的,它的作用域從變量定義處開始,到本程序文件的末尾。全局變量都存放在靜態(tài)存儲區(qū)中,占有固定的存儲單元,生存期為程序的整個運行過程。1.在一個文件內(nèi)聲明外部變量如果外部變量不在文件的開頭定義,其有效的作用范圍只限于定義處到文件結(jié)束。如果想在定義點之前引用該外部變量,解決的方法是在引用之前用關(guān)鍵字extern對該變量作“外部變量聲明”。表示該變量是一個已經(jīng)定義的外部變量。有了此聲明,就可以從“聲明”處起,合法地使用該外部變量。例5.26求兩數(shù)中較大者。#include<stdio.h>voidmain(){
int
max(int
x,inty);//函數(shù)聲明externintA,B;//全局變量聲明printf("兩數(shù)中較大的是:%d\n",max(A,B));//使用全局變量作為實參}intmax(intx,inty)//函數(shù)定義{intz;z=x>y?x:y;return(z);}intA=15,B=-8;//定義全局變量A,B運行結(jié)果:兩數(shù)中較大的是:15分析:在本程序文件的最后定義了外部變量A、B,其作用域是從定義處開始的,那么在主函數(shù)main中不能引用外部變量A、B?,F(xiàn)在main函數(shù)中用extern對A和B進行“外部變量聲明”,所以從“聲明”處起,可以合法地使用該外部變量A和B。用extern聲明外部變量時,類型名可以寫也可以不寫。例如,“externintA,B;”也可以寫成“externA,B;”。2.在多文件的程序內(nèi)聲明外部變量一個C程序可以由一個或多個源程序文件組成。如果程序由多個源程序文件組成,那么在一個文件中想引用另一個文件中已定義的外部變量,有什么辦法呢?實現(xiàn)的方法是:在其中一個文件中定義外部變量,而在另一文件中用extern對這個變量作“外部變量聲明”。在編譯和連接時,編譯系統(tǒng)會由此知道這個變量是一個已在別處定義的外部變量,并將在另一文件中定義的外部變量的作用域擴展到本文件,在本文件中就可以合法地引用該外部變量。例5.27輸入A和m,求Am的值。文件file1.c:#include<stdio.h>intA;//定義外部變量voidmain(){
int
power(int);//函數(shù)聲明
int
b,m;
printf("請輸入一個整數(shù)和它的方次:");
scanf("%d%d",&A,&m); b=power(m);
printf("%d**%d=%d\n",A,m,b);}文件file2.c:externA;//在file2中聲明file1定義的外部變量A,使其在本文件有效int
power(intn){
int
i,y=1;
for(i=1;i<=n;i++) y*=A; return(y);}運行結(jié)果:請輸入一個整數(shù)和它的方次:323**2=93.用static聲明外部變量有時在程序
溫馨提示
- 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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 化工合同審批管理
- 食品文化節(jié)采暖系統(tǒng)施工合同
- 水產(chǎn)養(yǎng)殖防水保溫施工協(xié)議
- 藝人演出教育推廣協(xié)議
- 農(nóng)業(yè)科技招投標(biāo)與合同履約分析
- 婚慶策劃公司租賃合同
- 建筑工程水電站施工合同樣本
- 綠色商業(yè)植草磚施工合同
- 電影院干掛石材施工協(xié)議
- 洗衣服務(wù)公司人事經(jīng)理聘用合同
- 加油站-課程設(shè)計
- 帛書老子道德經(jīng)全文-校注
- 柑橘園的規(guī)劃與設(shè)計(趙錚)
- 國家開放大學(xué)電大《中文學(xué)科論文寫作》期末題庫及答案
- 提高地下車庫防水質(zhì)量QC成果
- 物業(yè)消防系統(tǒng)承接查驗表
- 俄羅斯聯(lián)邦政府第782號決議 電梯安全技術(shù)規(guī)程(2009版)
- OPERA系統(tǒng)培訓(xùn)ppt課件
- 110Kv輸變電工程電氣安裝技術(shù)交底
- ASTM_A29/A29M熱鍛及冷加工碳素鋼和合金鋼棒
- 錄屏軟件Camtasia_Studio使用教程
評論
0/150
提交評論