《C語言程序設(shè)計新視角》課件第5章_第1頁
《C語言程序設(shè)計新視角》課件第5章_第2頁
《C語言程序設(shè)計新視角》課件第5章_第3頁
《C語言程序設(shè)計新視角》課件第5章_第4頁
《C語言程序設(shè)計新視角》課件第5章_第5頁
已閱讀5頁,還剩280頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

第5章函數(shù)5.1由程序規(guī)模增加引發(fā)的問題5.2模塊化的設(shè)計思想5.3函數(shù)在程序中的三種形式5.4主函數(shù)與子函數(shù)的比較5.5函數(shù)框架設(shè)計要素第5章函數(shù)5.6函數(shù)間信息如何傳遞5.7函數(shù)設(shè)計的綜合例子5.8函數(shù)的嵌套調(diào)用5.9函數(shù)的遞歸調(diào)用5.10作用域問題5.11本章小結(jié)

【主要內(nèi)容】

·揭示函數(shù)機(jī)制設(shè)置的原因和原理以及多個函數(shù)間相互關(guān)系的本質(zhì)含義;

·函數(shù)的聲明、定義、調(diào)用形式;

·函數(shù)參數(shù)的含義、使用規(guī)則;

·函數(shù)的設(shè)計要素及方法實例;

·讀程序的訓(xùn)練;

·自頂向下算法設(shè)計的訓(xùn)練;

·函數(shù)間信息傳遞調(diào)試要點的介紹。

【學(xué)習(xí)目標(biāo)】

·理解程序規(guī)模足夠大時分模塊(函數(shù))構(gòu)建程序的概念;

·理解并掌握在函數(shù)之間傳遞信息的機(jī)制;

·理解并掌握在函數(shù)之間信息屏蔽的機(jī)制;

·熟練掌握創(chuàng)建新函數(shù)的要素;

·理解如何編寫和使用能夠調(diào)用自身的函數(shù)。

解決現(xiàn)實問題的大多數(shù)程序,規(guī)模都比在前幾章中所介紹的程序要大得多,這樣的程序往往需要多人合作來完成,那么用什么樣的規(guī)則來把大的任務(wù)劃分成小的任務(wù)呢?按照我們?nèi)粘L幚韺嶋H問題的經(jīng)驗,按問題的功能來劃分是比較合適的,即把一個大的功能劃分成多個小的功能。像前面章節(jié)中,計算機(jī)處理數(shù)據(jù),一般分成數(shù)據(jù)的輸入、數(shù)據(jù)的處理和數(shù)據(jù)的輸出三部分,合起來就完成了指定的功能。5.1由程序規(guī)模增加引發(fā)的問題此外,有些功能我們需要重復(fù)使用,如前面已經(jīng)多次使用的數(shù)據(jù)的輸入/輸出功能。有效的做法,不應(yīng)該是每使用一次同樣的功能,都要重新編一次程序。

經(jīng)驗表明,開發(fā)和構(gòu)建大型程序的最好方法就是用較小的程序片段或模塊來構(gòu)建它,其中的模塊在必要時是可重復(fù)使用的。這就是“分而治之”這種很古老但很實用的策略在程序設(shè)計中的應(yīng)用。

模塊:能完成指定功能的子程序。

多模塊結(jié)構(gòu):將程序分為不同的模塊,每一模塊實現(xiàn)不同的功能。

模塊化程序設(shè)計的特點如下:

(1)各模塊相對獨立、功能單一,程序邏輯清晰,便于編寫和調(diào)試。

(2)降低了程序設(shè)計的復(fù)雜性,縮短了開發(fā)周期。

(3)提高了模塊的可靠性。

(4)避免了程序開發(fā)的重復(fù)勞動。

(5)易于維護(hù)和擴(kuò)充功能。

“模塊”這個詞有很多別名,如函數(shù)、子程序等。在結(jié)構(gòu)化分析和設(shè)計方法中人們常說的就是“模塊”;在面向?qū)ο蠓治龊驮O(shè)計中又把它說成是“類(class)”;在基于構(gòu)件的開發(fā)方法中的說法則是“構(gòu)件”。

一個程序只由一個模塊組成和由多個小模塊組成,除了模塊數(shù)量不同外,還有其他的區(qū)別嗎?

答:這正是我們下面要討論的問題。

下面先來看一個實際生活中做工程的分工合作的例子——鋪設(shè)瓷磚。

鋪設(shè)瓷磚的流程包括四個步驟:測量→計算→買料→鋪設(shè)。5.2模塊化的設(shè)計思想

問題一:鋪設(shè)瓷磚流程中的四個步驟,單人做和四個人分工完成,它們的區(qū)別有哪些?

答:可以從工作量、工作性質(zhì)和彼此間是否需要信息交流這幾個方面分項來看,內(nèi)容如表5.1所示。

表5.1鋪設(shè)瓷磚時單人做和多人分工完成的比較問題二:

(1)一段程序完成此功能與四段子程序完成此功能的不同點有哪些?

(2)如果用程序來實現(xiàn)上述功能,那么問題的關(guān)鍵點又在哪里呢?

答:程序無論是按各功能分段做,還是合起來一起做,對計算機(jī)而言,本質(zhì)是一樣的,都是由一個CPU完成,故表5.1中的“工作量”、“工作性質(zhì)”項都可以忽略,這樣,程序在一段里完成四個功能和分四段分別完成四個功能,其不同點就是模塊間必須要有信息交流,如“測量”模塊測量的結(jié)果,要如何交給“計算”模塊,“計算”的結(jié)果又如何傳遞給“買料”,等等。因此,在多模塊機(jī)制中,計算機(jī)解題的關(guān)鍵,就是解決程序按功能“分段”即模塊化后模塊間“信息交流”在機(jī)制上如何設(shè)置、如何實現(xiàn)的問題。

程序設(shè)計語言應(yīng)提供這樣的交流機(jī)制,才能真正在程序中實現(xiàn)多個子程序的構(gòu)建。

模塊:能夠單獨命名并獨立地完成一定功能的程序語句的集合。模塊內(nèi)部的實現(xiàn)細(xì)節(jié)和數(shù)據(jù)是外界不可見的,它與外界的聯(lián)系是通過信息接口進(jìn)行的。

信息接口:其他模塊或程序使用該模塊的約定方式,包括輸入/輸出信息等。

在C語言中,模塊的概念是用“函數(shù)”一詞來描述的。

函數(shù)的“信息交流”機(jī)制在設(shè)置時要考慮哪些因素,是怎樣設(shè)計出來的?5.2.1工程計劃

為了說明函數(shù)的信息交流機(jī)制,首先來看看瓷磚分工鋪設(shè)的實際流程。

在鋪設(shè)前,先要做計劃,即按照工種、需要的信息、完成的功能、提交的結(jié)果等項,填好表5.2。

表5.2函數(shù)的設(shè)計思想1——工程計劃

任何一個子工種都由三部分組成:需要的信息、要完成的功能和提交的結(jié)果。5.2.2工程施工

相對于計劃所需要的信息都是抽象的,并不涉及具體的數(shù)據(jù);實際施工時,需要的信息都是具體的,具體如表5.3所示。

表5.3函數(shù)的設(shè)計思想2——工程施工

計劃只需要抽象的概念;施工則要有實際的數(shù)據(jù)。5.2.3函數(shù)定義形式的設(shè)計

與實際的工程類比,我們可以從功能、信息輸入和信息輸出這三個方面考慮函數(shù)的形式設(shè)計。

(1)功能:

·功能描述:工種名稱←→函數(shù)名稱;

·功能實現(xiàn):施工步驟←→函數(shù)體語句。

(2)信息輸入:工種需要的信息←→函數(shù)的輸入信息。

(3)信息輸出:工種提交的結(jié)果←→函數(shù)的輸出信息。

上面三者的對應(yīng)關(guān)系如表5.4所示。

表5.4函數(shù)的設(shè)計思想——工程計劃與函數(shù)定義(1)

為使用的方便,函數(shù)要有名稱,且應(yīng)該設(shè)置有輸入信息的接收入口、提交信息的輸出口。函數(shù)的功能用語句實現(xiàn)。

綜上,與實際工作流程計劃的例子類比,函數(shù)的定義形式在結(jié)構(gòu)上要有三個要素:功能、輸入信息和輸出信息。函數(shù)的定義形式設(shè)計如下:

結(jié)果的類型函數(shù)名(輸入信息)

{

功能完成語句;

提交結(jié)果;/*輸出信息*/

}通常,我們把花括號括起來的部分稱做函數(shù)體。

“輸入信息”和“提交結(jié)果”具體的格式要求是怎樣的呢?這要從二者數(shù)據(jù)的種類和數(shù)量情形來分析,詳見表5.5。

表5.5函數(shù)的設(shè)計思想——工程計劃與函數(shù)定義(2)說明:

(1)輸入接口設(shè)置:由指定的輸入信息參數(shù)表接收。由實際的工種可以看到,需要處理的信息可以有0個或多個,它們可以分成數(shù)值和地址兩大類,因此參數(shù)表中需要處理的信息可以有不同類型的多個數(shù)據(jù)。

(2)輸出接口設(shè)置:有兩種方式。由實際的工種可以看到,提交的信息和需要處理的信息一樣,可以有0個或多個,也分成兩數(shù)值和地址大類,因此提交的結(jié)果也可以有不同類型的多個數(shù)據(jù)。對應(yīng)“提交結(jié)果”功能,C語言中專門設(shè)置了一個return語句來實現(xiàn)結(jié)果的返回。C語言中按提交結(jié)果的數(shù)目,設(shè)計了三種提交結(jié)果的方式:

(1)提交一個結(jié)果:使用return語句返回這個結(jié)果,特別規(guī)定函數(shù)的類型即是這個結(jié)果的類型。

(2)提交多個結(jié)果:把結(jié)果放在約定地址的存儲區(qū)域里。

方法一:使用語句return(約定地址)。使用return語句返回上述存儲區(qū)域的起始地址時有限定條件(具體的限定條件將在后續(xù)“局部量”的例子中給出。)

方法二:在形式參數(shù)表中約定放置提交結(jié)果的地址。特別提醒:此時return的功能仍可使用。

(3)無結(jié)果提交:函數(shù)只完成特定功能,而沒有“計算”出一個具體的數(shù)值,如完成定點報時的工作,這時無return語句提交結(jié)果,因此把函數(shù)類型設(shè)置為void型。

按照上述函數(shù)應(yīng)該有的關(guān)鍵要素,函數(shù)定義的一般形式如下:

函數(shù)類型函數(shù)名(形式參數(shù)表)

{

聲明部分;

語句部分;

}說明:

(1)函數(shù)類型:return語句提交結(jié)果的類型,可以是任何C語言允許的數(shù)據(jù)類型。

(2)函數(shù)名:標(biāo)識符。

(3)形式參數(shù)表:多個變量的定義形式,中間用逗號分開,其中的變量叫做形參。

(4)有時把函數(shù)中的變量聲明和語句部分合稱為“函數(shù)體”。

(5)return語句包含在函數(shù)體中。

函數(shù)設(shè)計三要素:

(1)功能描述:盡量用一個詞來描述函數(shù)的功能,以此做函數(shù)的名稱。

(2)輸入:列出所有的要提供給函數(shù)處理的信息,它們決定了函數(shù)形式參數(shù)表的內(nèi)容。

(3)輸出:輸出信息的類型決定了函數(shù)的類型。

【例5-1】函數(shù)定義形式設(shè)計的例子。寫出前面瓷磚鋪設(shè)流程中“測量”函數(shù)和“計算”函數(shù)的定義形式。

【解】(1)“計算”函數(shù):按照函數(shù)設(shè)計的三要素,列出相應(yīng)信息項如表5.6所示。

表5.6“計算”函數(shù)的設(shè)計形參表有房間長length、寬width和瓷磚尺寸size三個實型參數(shù)。輸出只有一個整型的瓷磚數(shù)量值,故用return返回它即可,函數(shù)的類型就是整型。

由此,可以給出“計算”函數(shù)的定義框架:

intcalculate(floatlength,floatwidth,floatsize)

{函數(shù)體

return(number);

}

(2)“測量”函數(shù):其三要素信息如表5.7所示。

表5.7測量函數(shù)的設(shè)計

·功能:測量給定房間的長、寬尺寸;

·輸入:房間地址;

·輸出:房間的長、寬尺寸。

這里的輸出有兩個,不能同時通過return提交,該如何處理?

答:由于這里的輸出信息多于一個,因此可以采用與輸入信息共用“地址”的方法,即通過在形式參數(shù)表里設(shè)置指針量(指針量中存放的是地址值)來提交房間的長、寬這兩個數(shù)據(jù),故形參表中就有三個參數(shù)了。這樣return的功能沒有用到,所以函數(shù)的類型為void?!皽y量”函數(shù)的定義框架如下:

voidsurvey(int*address,float*length,float*width)

{函數(shù)體}

說明:指針變量定義的一般形式為

數(shù)據(jù)類型*變量名;5.2.4函數(shù)調(diào)用形式的設(shè)計

實際工程的步驟是先按照工種、需要的信息、完成的功能、提交的結(jié)果等抽象信息做好計劃;然后在實際施工時,根據(jù)具體的信息進(jìn)行實際的處理。函數(shù)的具體執(zhí)行過程也是類似的,相對于形式參數(shù),也要提供有實際的操作數(shù)據(jù)——實際參數(shù),才能做具體的處理,它們的對應(yīng)關(guān)系見表5.8。

表5.8函數(shù)的設(shè)計思想——工程施工與函數(shù)調(diào)用

我們把函數(shù)的具體執(zhí)行稱為函數(shù)的調(diào)用,其格式為

函數(shù)名(實際參數(shù)表)

說明:

(1)實際參數(shù)表:實際參數(shù)可以是常數(shù)、變量或表達(dá)式。各實參之間用逗號分隔。

(2)對無參函數(shù)調(diào)用時則無實際參數(shù)表,但括號依然保留。

(3)有類型函數(shù)調(diào)用——只能出現(xiàn)在表達(dá)式右側(cè),如“計算”函數(shù),它會返回一個確定的值,這個值要有一個變量來接收它,這個變量的類型要和函數(shù)類型一致。

(4)無類型函數(shù)調(diào)用——當(dāng)做獨立的語句處理,如“測量”函數(shù),它不返回具體的

數(shù)值。

【例5-2】函數(shù)調(diào)用形式的例子。給出“測量”、“計算”函數(shù)的調(diào)用形式。設(shè)

floata,b; /*房間的長寬*/

intnum; /*瓷磚的數(shù)量*/

int*addr; /*房間地址*/

(1)“測量”函數(shù)的調(diào)用形式:

survey(addr,&a,&b);

(2)“計算”函數(shù)的調(diào)用形式:

num=calculate(a,b,0.36);

說明:函數(shù)調(diào)用時,實際參數(shù)的個數(shù)、類型和位置要與形參的相對應(yīng)。5.2.5函數(shù)間配合運行的機(jī)制設(shè)計

1.函數(shù)的聲明

函數(shù)聲明也稱函數(shù)原型,類似于變量的聲明。函數(shù)聲明里的形式參數(shù)可以只寫類型而省略名稱。

函數(shù)聲明形式如下:

返回值類型符函數(shù)名稱(形式參數(shù)列表);

瓷磚鋪設(shè)流程中各函數(shù)的聲明如下:

voidsurvey(int*address,float*length,float*width);

floatcalculate(floatlength,floatwidth,floatsize);

floatbuy(floatamount);

voidlay(void);

為什么需要函數(shù)原型?

在ANSIC新標(biāo)準(zhǔn)中,允許采用函數(shù)原型方式對被調(diào)用函數(shù)進(jìn)行說明。

函數(shù)原型能告訴編譯器此函數(shù)有多少個參數(shù),每個參數(shù)分別是什么類型,函數(shù)的返回類型又是什么。當(dāng)函數(shù)被調(diào)用時,編譯器可以根據(jù)這些信息判斷實參個數(shù)、類型是否正確等。函數(shù)原型能讓編譯器及時地發(fā)現(xiàn)函數(shù)調(diào)用時存在的語法錯誤。

一般習(xí)慣于在程序文件的開頭為程序中使用的每個函數(shù)編寫函數(shù)原型,這樣能提高編譯效率。

2.函數(shù)的定義

(1)“測量”函數(shù):

/**********

“測量”函數(shù)

功能:完成房間長寬尺寸的測量

輸入:房間地址address

輸出:房間長length、寬width

**********/

voidsurvey(int*address,float*length,float*width)

{函數(shù)體}

(2)“計算”函數(shù):

/**********

“計算”函數(shù)

功能:計算瓷磚數(shù)量

輸入:房間長length、寬width、瓷磚尺寸size

輸出:瓷磚數(shù)量

**********/

intcalculate(floatlength,floatwidth,floatsize)

{函數(shù)體}

(3)“買料”函數(shù)

/**********

“買料”函數(shù)

功能:瓷磚購買

輸入:瓷磚數(shù)量amount

輸出:無

**********/

voidbuy(intamount)

{函數(shù)體}

(4)“鋪設(shè)”函數(shù):

/**********

“鋪設(shè)”函數(shù)

功能:完成房間施工

輸入:無

輸出:無

**********/

voidlay(void)

{函數(shù)體}

3.函數(shù)的調(diào)用

1 #defineSIZE0.36

2 intmain()

3 {

4 int*address;/*房間的地址*/

5 floatlength1,length2;/*房間的長、寬*/

6 intnum;/*瓷磚數(shù)量*/

7

8survey(address,&length1,&length2);

9 num=calculate(length1,length2,SIZE);

10 buy(num);

11 lay();

12 return0;

13 }所有子函數(shù)的功能都在相應(yīng)的函數(shù)定義中給出,這些函數(shù)的運行要通過函數(shù)調(diào)用才能實現(xiàn)。在這個具體的例子中,按照各工種的先后順序在主函數(shù)中調(diào)用它們,這樣就完成了由多個子函數(shù)分工配合實現(xiàn)的復(fù)雜功能的總過程。

函數(shù)調(diào)用

所謂函數(shù)調(diào)用,就是使程序轉(zhuǎn)去執(zhí)行函數(shù)體。在C/C++中,除了主函數(shù)外,其他任何函數(shù)都不能單獨作為程序來運行,任何函數(shù)功能的實現(xiàn)都是通過被主函數(shù)直接或間接調(diào)用來進(jìn)行的。

函數(shù)在程序中有三種表現(xiàn)形式,具體見表5.9。5.3函數(shù)在程序中的三種形式

表5.9函數(shù)的三種形式

函數(shù)頭的格式:

函數(shù)類型函數(shù)名(形式參數(shù)表);

下面再介紹一下函數(shù)的三種形式的格式。

(1)函數(shù)聲明格式:

返回值類型符函數(shù)名稱(形式參數(shù)列表);

(2)函數(shù)定義格式:

/*************************

函數(shù)功能:實現(xiàn)××××功能

函數(shù)參數(shù):參數(shù)1,表示×××

參數(shù)2,表示×××

函數(shù)返回值:表示××

*****************************/

函數(shù)類型函數(shù)名(形式參數(shù)表)

{

聲明部分;

語句部分;

}

(3)函數(shù)調(diào)用格式:

函數(shù)名(實際參數(shù)表)

若站在數(shù)學(xué)的角度,我們可以這樣來解釋函數(shù)——關(guān)于函數(shù)的另一種說法。

當(dāng)我們把“函數(shù)”當(dāng)成一個剛畢業(yè)去找工作的學(xué)生時,可以有以下的故事演繹:

“函數(shù)”的故事

見面會上“函數(shù)”簡單說明了一下自己,

遞上厚厚的文本定義了自己的十八般武藝,

被領(lǐng)導(dǎo)看上調(diào)用來委心重任,

與同事信息交流工作同心協(xié)力,

合作完成大事業(yè)建立功績……函數(shù)在程序中出現(xiàn)的“面目”有三種:聲明形式(或稱說明形式)、定義形式和調(diào)用形式。函數(shù)在程序中通過信息交流,完成相互的配合,最終實現(xiàn)復(fù)雜的功能。

可以通過分別在主函數(shù)和子函數(shù)中實現(xiàn)同一功能來比較實現(xiàn)過程的差異和相同點。請看下面的例子。

【例5-3】在三個數(shù)a、b、c中,找其中的最大值max。

在主函數(shù)中實現(xiàn):

intmain()

{inta,b,c,max;

scanf("%d,%d,%d",&a,&b,&c);

max=a>b?a:b;5.4主函數(shù)與子函數(shù)的比較

max=max>c?max:c;

printf("max=%d",max);

return0;

}

在子函數(shù)中實現(xiàn):

intmax(inta,intb,intc)

{intmax;

max=a>b?a:b;

max=max>c?max:c;

return(max);

}在主函數(shù)main中實現(xiàn)此功能和由子函數(shù)max實現(xiàn)此功能的區(qū)別在于輸入信息的來源和輸出信息的渠道不一樣。主函數(shù)是通過鍵盤輸入要處理的數(shù)據(jù),子函數(shù)是通過信息接口———形參表得到它們;主函數(shù)直接把結(jié)果顯示出來,而子函數(shù)是把結(jié)果返回給調(diào)用者。當(dāng)然,子函數(shù)還要通過被調(diào)用,給它實際的參數(shù)才能運行。

形參和實參變量可以不同名嗎?

答:形參和實參同名或不同名,在語法上都沒有錯,但二者不同名有助于避免混淆,有利于調(diào)試。本章后面會在局部量與全局量的概念學(xué)習(xí)中再討論這個問題。

編寫子函數(shù),最重要的就是確定子函數(shù)的框架。子函數(shù)的框架要素有函數(shù)名、形參表和函數(shù)類型。我們通過實際的例子來學(xué)習(xí)函數(shù)的設(shè)計步驟。

5.5函數(shù)框架設(shè)計要素

【例5-4】函數(shù)設(shè)計的例子1。使用isPrime函數(shù)在屏幕上打印出20以內(nèi)的素數(shù)。

【解】程序設(shè)計思路:首先用子函數(shù)isPrime判斷一個整數(shù)是否為素數(shù);然后在主函數(shù)中調(diào)用isPrime,逐個判斷20以內(nèi)的整數(shù)是否為素數(shù),是則輸出。

isPrime的功能:判斷一個數(shù)是否為素數(shù),返回1代表是素數(shù),返回0代表不是素數(shù)。

如前所述,編寫子函數(shù),最重要的就是確定子函數(shù)的框架,確定了輸入、輸出和功能這三個要素,子函數(shù)的框架要素即函數(shù)名、形參表、函數(shù)類型也就相應(yīng)確定了。具體內(nèi)容如表5.10所示。

表5.10函數(shù)設(shè)計例子1之函數(shù)框架設(shè)計函數(shù)設(shè)計三要素的具體內(nèi)容如表5.11所示。

表5.11函數(shù)設(shè)計三要素說明:當(dāng)輸出信息多于一個時,可以采用以下兩種方法。

(1)與輸入信息共用“地址”;

(2)返回信息是“地址”。

isPrime子函數(shù)程序:

/*************************

函數(shù)isPrime判斷一個數(shù)是否為素數(shù)。

返回1代表是素數(shù);

返回0代表不是素數(shù)

************************/

intisPrime(intx)

{

intk;/*素數(shù)測試范圍*/

if(x==1)return0;/*x是1,不是素數(shù)*/

if(x==2)return1;/*x是1,不是素數(shù)*/

for(k=2;k<x/2;k++)

{

if(x%k==0)return0;/*檢查x是否為素數(shù)*/

}

return1;/*是素數(shù),返回1*/

}

完整的帶主函數(shù)的程序:

1/*創(chuàng)建并使用程序員定義的函數(shù)*/

2#include<stdio.h>

3intisPrime(intx);/*函數(shù)原型——函數(shù)的聲明形式*/

4

5intmain()

6{

7 inti;/*計數(shù)器*/

8

9 /*循環(huán)20次,從1-20逐個判斷其是否為素數(shù)*/

10 for(i=1;i<=20;i++)

11 {

12 if(isPrime(i))/*函數(shù)調(diào)用*/

13 {

14 printf("%d",i);

15 }

16 }/*結(jié)束for循環(huán)*/

17 printf("\n");

18 return0;

19 }/*結(jié)束main*/

20

21/*判斷一個數(shù)是否為素數(shù),返回1代表是素數(shù),返回0代表不是素數(shù)*/

22intisPrime(intx)

23{

24 intk;/*素數(shù)測試范圍*/

25

26 if(x==1)/*1不是素數(shù)*/

27 {

28 return0;

29 }

30 if(x==2)/*2是素數(shù)*/

31 {

32 return1;

33 }

34 for(k=2;k<x/2;k++)/*在2到x/2范圍內(nèi)檢查*/

35 {

36 if(x%k==0)/*檢查x是否為k的倍數(shù)*/

37 {

38 return0;/*不是素數(shù),返回0*/

39 }

40 }

41 return1;/*是素數(shù),返回1*/

42}

程序結(jié)果:

2345711131719

查看函數(shù)調(diào)用的運行軌跡。

圖5.1所示為調(diào)試步驟1,程序從主函數(shù)開始執(zhí)行。

圖5.1函數(shù)設(shè)計例子1之調(diào)試步驟1圖5.2顯示了i變量的情形:

CXX0069:Error:variableneedsstackframe

即變量需要堆棧幀(框架)。造成錯誤的原因是,要查看的變量i只有分配了存儲空間才能看到。圖5.2變量的查看1圖5.3中,將要調(diào)用子函數(shù)isPrinme之前,顯示i=1。

圖5.4所示為調(diào)試步驟3,按F11鍵跟蹤子函數(shù)。

此時,有一個現(xiàn)象值得注意,i的值顯示:

CXX0017:Error:symbol"i"notfound

即符號i未找到,如圖5.5所示。

圖5.3函數(shù)設(shè)計例子1之調(diào)試步驟2

圖5.4函數(shù)設(shè)計例子1之調(diào)試步驟3

圖5.5變量的查看2為什么會出現(xiàn)圖5.5所示的現(xiàn)象呢?剛剛在主函數(shù)中還看到了i,難道是程序執(zhí)行出錯了嗎?其實不是,C程序多函數(shù)機(jī)制設(shè)置就是這樣處理的,這涉及變量或數(shù)據(jù)的作用域問題,在后面有關(guān)作用域問題的討論中會給出相關(guān)的概念,在此只簡單解釋一下。多函數(shù)機(jī)制中規(guī)定每個函數(shù)只能使用自己本函數(shù)內(nèi)部定義的量(除此之外,當(dāng)然還有特例情形),因此,在進(jìn)行變量的查看時也就只能看到正在執(zhí)行的函數(shù)有權(quán)限使用的變量的值了。圖5.6所示為調(diào)試步驟4,圖中可以查看isPrime(i)作為if的表達(dá)式其取值的情況。

圖5.7所示為調(diào)試步驟5,可以看到,i值每增加一次,就調(diào)用一次isPrime函數(shù)。

圖5.8所示為調(diào)試步驟6,可以看到,i=3時,isPrime返回1,說明其是素數(shù)。

圖5.9所示為調(diào)試步驟7,當(dāng)i=6時,isPrime返回0,說明其不是素數(shù)。

圖5.10所示為調(diào)試步驟8,當(dāng)i=20時,for循環(huán)對isPrime做最后一次調(diào)用。

圖5.6函數(shù)設(shè)計例子1之調(diào)試步驟4

圖5.7函數(shù)設(shè)計例子1之調(diào)試步驟5

圖5.8函數(shù)設(shè)計例子1之調(diào)試步驟6

圖5.9函數(shù)設(shè)計例子1之調(diào)試步驟7

圖5.10函數(shù)設(shè)計例子1之調(diào)試步驟8圖5.11所示為調(diào)試步驟9,此時for循環(huán)結(jié)束,i=21。

圖5.11函數(shù)設(shè)計例子1之調(diào)試步驟9

函數(shù)運行順序為:主函數(shù)和子函數(shù)配合運行時,程序總是從主函數(shù)開始運行,遇到有子函數(shù)的調(diào)用時,進(jìn)入子函數(shù)運行,直至運行完畢,然后再回到主函數(shù),繼續(xù)運行。

例如,在main函數(shù)中,調(diào)用子函數(shù)a的流程如圖5.12所示。

圖5.12函數(shù)調(diào)用流程

有關(guān)函數(shù)的問題

(1)函數(shù)名結(jié)構(gòu):“動詞”或者“動詞+名詞”,如CalculateGetMax。

(2)變量名結(jié)構(gòu):“名詞”或者“形容詞+名詞”,如ValuenewValue。

(3)函數(shù)設(shè)計規(guī)則。表5.12中給出了在設(shè)計函數(shù)時應(yīng)該遵循的規(guī)則。

表5.12函數(shù)設(shè)計規(guī)則說明:

①一個函數(shù)一個功能。對函數(shù)的功能可以用一句話描述。

②函數(shù)不能過長。1986年IBM在OS/360的研究結(jié)果表明,大多數(shù)有錯誤的函數(shù)都大于500行。1991年對148000行代碼的研究表明,小于143行的函數(shù)比更長的函數(shù)更容易維護(hù)。

③檢查函數(shù)的輸入信息。輸入信息有問題時,要向調(diào)用者提出警示信息。函數(shù)的輸入主要有兩種:一種是參數(shù)輸入;另一種是全局變量、數(shù)據(jù)文件的輸入,即非參數(shù)輸入。函數(shù)在使用輸入之前,應(yīng)進(jìn)行必要的檢查。

選擇有意義的函數(shù)名和有意義的參數(shù)名,可以使程序具有更好的可讀性,并有助于避免過多使用注釋。

【例5-5】函數(shù)設(shè)計的例子2。用程序?qū)崿F(xiàn)從n個不同的元素中每次取k個元素的組合數(shù)目。計算公式如下:

【解】因為公式中要多次計算階乘,所以我們先設(shè)計一個計算階乘的子函數(shù)結(jié)構(gòu),如表5.13所示。

表5.13函數(shù)設(shè)計例子2之框架設(shè)計

表5.14函數(shù)設(shè)計例子2之函數(shù)實現(xiàn)設(shè)計

圖5.13函數(shù)的返回流程

(1)函數(shù)的返回值是int型,為什么函數(shù)類型要用Float?

(2)函數(shù)體中有兩個return語句,每次返回幾個值?

答:(1)求階乘的結(jié)果放到float型變量中,可以運算比int型更大的數(shù),而結(jié)果不會溢出。

(2)從流程圖5.13中可以清楚地看到,雖然流程中有多處返回,但每個返回執(zhí)行后,流程就結(jié)束了,所以每次只能返回一個值。

程序總流程:

1 #include<stdio.h>

2 floatfactorial(intx);

3 /*計算整數(shù)x的階乘*/

4 floatfactorial(intx)

5 {

6 inti;

7 floatt=1;

8 for(i=1;i<=x;i++)

9 t=t*i;

10 return(t);

11 }函數(shù)聲明函數(shù)定義

12

13 intmain()

14 {

15 floatc;

16 intm,n;

17

18 printf("inputm,n:");

19 scanf("%d%d",&m,&n);

20 c=factorial(m)/(factorial(n)*factorial(m-n));

函數(shù)調(diào)用

21 printf("Theresultis%8.1f",c);

22 return0;

23 }

函數(shù)的聲明出現(xiàn)在哪里比較好?

對于函數(shù)的聲明位置,C語言的規(guī)則是可以放在調(diào)用函數(shù)內(nèi),也可以放在函數(shù)外部。在調(diào)用一個函數(shù)時,如果前面的代碼沒有函數(shù)定義或聲明,將導(dǎo)致編譯出錯。

一般地,當(dāng)程序中有多個子函數(shù)時,它們的聲明最好都放在預(yù)編譯命令后,而不要放在調(diào)用函數(shù)內(nèi)。這樣聲明的特點是:當(dāng)前文件從函數(shù)的聲明位置開始到文件結(jié)束的任何函數(shù)中都可以調(diào)用該函數(shù)。簡單地說,函數(shù)聲明和變量說明是類似的,也是要“先聲明,后使用”。

子函數(shù)要處理的信息是通過實際參數(shù)傳遞給形式參數(shù)得到的,下面將通過實際例子觀察C函數(shù)間信息傳遞的方式。5.6函數(shù)間信息如何傳遞5.6.1C函數(shù)實際參數(shù)與形式參數(shù)的關(guān)系

形式參數(shù):簡稱“形參”,是在定義函數(shù)名和函數(shù)體的時候使用的參數(shù),目的是用來接收調(diào)用該函數(shù)時傳入的參數(shù)。

實際參數(shù):簡稱“實參”,是在調(diào)用時傳遞給該函數(shù)的參數(shù)。

表5.15形參與實參的關(guān)系要嚴(yán)格按照其語法格式的要求來使用函數(shù)的不同格式,初學(xué)者最容易犯的錯誤,就是不注意形式參數(shù)與實際參數(shù)的填寫,在此特別強調(diào)一下。

(1)形式參數(shù)表:在函數(shù)定義里,形式參數(shù)表中放參數(shù)的定義形式,即變量的定義形式。如果形參是數(shù)組,則在數(shù)組括號之間并不需要指定數(shù)組的大小,因為此時只傳遞數(shù)組的地址。函數(shù)定義形式:

函數(shù)類型函數(shù)名(形式參數(shù)表)

{

聲明部分;

語句部分;

}形式參數(shù)表中放參數(shù)的定義形式,如:基本變量:intx指針:int*ptr數(shù)組:一維inta[]二維intb[][6]。12

(2)實際參數(shù)表:在函數(shù)調(diào)用時,實際參數(shù)表中放參數(shù)的使用形式,即變量的使用形式(或稱變量引用形式);對數(shù)組則僅僅放置數(shù)組名。

函數(shù)調(diào)用形式:

函數(shù)名(實際參數(shù)表)實際參數(shù)表中放參數(shù)的使用形式,如:基本變量:x指針:ptr數(shù)組:一維a二維b

(3)函數(shù)返回return:括號里的參數(shù)可以是一個變量,也可以是一個常量,但一定只能是一個量,不能是多個。

函數(shù)返回形式:

Return(參數(shù))5.6.2函數(shù)間信息傳遞的實際例子

【例5-6】函數(shù)間信息傳遞的例子1。傳遞一個數(shù)組與傳遞一個變量給函數(shù)的區(qū)別。

【解】這里設(shè)計兩個子函數(shù)來觀察這種區(qū)別,函數(shù)的具體功能設(shè)計見表5.16。

表5.16函數(shù)間信息傳遞的例子1之函數(shù)功能設(shè)計

表5.17函數(shù)間信息傳遞的例子1之函數(shù)框架設(shè)計程序?qū)崿F(xiàn):

1/*傳遞一個數(shù)組與傳遞一個變量給函數(shù)的區(qū)別*/

2#include<stdio.h>

3#defineSIZE5

4

5/*函數(shù)聲明*/

6

voidmodify_array(inta[],intlength);/*修改整個數(shù)組元素的值*/

7voidmodify_value(intv);/*修改單個變量值*/

8

9intmain()

10{

11inta[SIZE]={1,3,5,7,9};/*初始化數(shù)組a*/

12intvalue;

13inti;/*計數(shù)器*/

14

15printf("以下結(jié)果均在main函數(shù)中觀察得到\n");

16printf("在modify_array函數(shù)中修改傳遞來的整個數(shù)組:\n");

17printf("modify_array調(diào)用前a數(shù)組=");

18/*輸出原始數(shù)組*/

19for(i=0;i<SIZE;i++)

20{

21printf("%3d",a[i]);

22}

23printf("\n");

24/*把數(shù)組傳遞給函數(shù),函數(shù)中傳入了數(shù)組a的地址*/

25modify_array(a,SIZE);

26printf("modify_array調(diào)用后a數(shù)組=");

27/*輸出修改后的數(shù)組*/

28for(i=0;i<SIZE;i++)

29{

30printf("%3d",a[i]);

31}

32

33/*把變量value的副本傳遞給函數(shù)*/

34value=6;

35printf("\n\n在modify_value函數(shù)中修改傳遞來的單個變量:\n");

36printf("modify_value調(diào)用前:value=%d\n",value);

37modify_value(value);

38printf("modify_value調(diào)用后:value=%d\n",value);

39

40/*把數(shù)組元素a[SIZE-1]的副本傳遞給函數(shù)*/

41printf("\n在modify_value函數(shù)中修改傳遞來的單個數(shù)組元素的值:\n");

42printf("modify_value調(diào)用前:a[%d]=%d\n",SIZE-1,a[SIZE-1]);

43modify_value(a[SIZE-1]);

44printf("modify_value調(diào)用后:a[%d]=%d\n",SIZE-1,a[SIZE-1]);

45

46return0;/*表示程序成功結(jié)束*/

47}/*main函數(shù)結(jié)束*/

48

49/*在函數(shù)modify_array中,數(shù)組的地址被傳入到函數(shù)中*/

50voidmodify_array(intb[],intsize)

51{

52intj;/*計數(shù)器*/

53/*將數(shù)組的每個元素都加1*/

54for(j=0;j<size;j++)

55{

56b[j]=b[j]+1;

57}

58}

59

60/*在函數(shù)modify_value中,變量v的副本被傳入到函數(shù)中*/

61voidmodify_value(intv)

62{

63v=v*2;/*將參數(shù)值乘以2*/

64}/*函數(shù)modify_int結(jié)束*/

程序結(jié)果(以下結(jié)果均在main函數(shù)中觀察得到):

在modify_array函數(shù)中修改傳遞來的整個數(shù)組:

modify_array調(diào)用前a數(shù)組=13579

modify_array調(diào)用后a數(shù)組=246810

在modify_value函數(shù)中修改傳遞來的單個變量:

modify_value調(diào)用前:value=6

modify_value調(diào)用后:value=6

在modify_value函數(shù)中修改傳遞來的單個數(shù)組元素的值:

modify_value調(diào)用前:a[4]=10

modify_value調(diào)用后:a[4]=10

為什么給子函數(shù)傳遞數(shù)組地址,就可以從同地址中得到被修改的值,而傳遞單個的變量值,就得不到被修改的結(jié)果?

答:上述問題,需要跟蹤函數(shù)的調(diào)用過程,查看實際參數(shù)與形式參數(shù)的空間分配使用狀況,才能清楚。

查看形參與實參單元分配及函數(shù)間信息如何傳遞。

(1)傳遞數(shù)組地址。

圖5.14所示為調(diào)試步驟1,modify_array被調(diào)用之前,實參a數(shù)組的地址為0x12ff6c。

圖5.14函數(shù)間信息傳遞的例子1之調(diào)試步驟1

圖5.15為調(diào)試步驟2,此時進(jìn)入子函數(shù)modify_array,將a數(shù)組的地址傳遞給b數(shù)組。

圖5.15函數(shù)間信息傳遞的例子1之調(diào)試步驟2

圖5.16所示為調(diào)試步驟3,可見在Watch窗口中,b數(shù)組的值只顯示了一個,要看到全部的信息,可以通過圖5.17所示的Memory窗口查看。

圖5.16函數(shù)間信息傳遞的例子1之調(diào)試步驟3圖5.17的Memory窗口顯示對b數(shù)組的內(nèi)容修改完畢,其值為2、4、6、8、10。

圖5.17Memory窗口圖5.18所示為調(diào)試步驟4,此時返回主函數(shù),因為a與b是同一地址,所以看到的數(shù)據(jù)依然是前面看到的那些。通過形參與實參“共用地址”的方法,可以把多個處理結(jié)果返回給調(diào)用者,這在返回值多于一個的場合是一種有效的方法。

圖5.18函數(shù)間信息傳遞的例子1之調(diào)試步驟4以上函數(shù)間通過共用地址傳遞信息,實參、形參單元及其中值的變化如圖5.19所示。圖5.19函數(shù)間通過共用地址傳遞信息

(2)傳遞一個變量值(值傳遞——傳值調(diào)用)。

圖5.20所示為調(diào)試步驟5,modify_value被調(diào)用之前,實參value的值為6,地址是0x12ff68。

圖5.21所示為調(diào)試步驟6,此時進(jìn)入modify_value函數(shù)執(zhí)行,實際參數(shù)的值被賦給形參v,v的地址為0x12ff14。

注意:此時形參、實參各分存儲單元,只是把實參值拷貝到了形參的空間,并不是像前面數(shù)組那樣共用地址。

圖5.22所示為調(diào)試步驟7,此時modify_value函數(shù)對形參進(jìn)行修改,v=12。

圖5.20函數(shù)間信息傳遞的例子1之調(diào)試步驟5

圖5.21函數(shù)間信息傳遞的例子1之調(diào)試步驟6

圖5.22函數(shù)間信息傳遞的例子1之調(diào)試步驟7圖5.23所示為調(diào)試步驟8,此時返回主函數(shù),實參value的值仍然是原來的6,即形參v的改變并不影響實參的值,因為它們的存儲空間是各自獨立的。

函數(shù)間通過單個變量給形參賦值傳遞信息,實參、形參單元及其中值的變化如圖5.24所示。

圖5.23函數(shù)間信息傳遞的例子1之調(diào)試步驟8

圖5.24函數(shù)間通過單個變量給形參賦值傳遞信息

(3)傳遞一個數(shù)組元素值。

圖5.25所示為調(diào)試步驟9,modify_value被調(diào)用之前,實參a[SIZE-1]的值為10(注:SIZE=5),地址是0x12ff7c。

圖5.26所示為調(diào)試步驟10,此時進(jìn)入modify_value函數(shù)執(zhí)行,實際參數(shù)的值被賦給形參v,v的地址為0x12ff14。

注意:此時形參、實參各分存儲單元,只是把實參值拷貝到了形參的空間。

圖5.27所示為調(diào)試步驟11,此時modify_value函數(shù)對形參進(jìn)行修改,v=20。

圖5.25函數(shù)間信息傳遞的例子1之調(diào)試步驟9

圖5.26函數(shù)間信息傳遞的例子1之調(diào)試步驟10

圖5.27函數(shù)間信息傳遞的例子1之調(diào)試步驟11圖5.28所示為調(diào)試步驟12,此時返回主函數(shù),實參a[SIZE-1]的值仍然是原來的10,即形參v的改變并不影響實參的值,因為它們的存儲空間是各自獨立的。

函數(shù)間通過單個變量給形參賦值傳遞信息,實參、形參單元及其中值的變化如圖5.29所示。

圖5.28函數(shù)間信息傳遞的例子1之調(diào)試步驟12

圖5.29函數(shù)間通過數(shù)組元素給形參賦值傳遞信息

關(guān)于形參與實參單元分配等

(1)數(shù)組名做參數(shù),實參、形參數(shù)組是共用地址的;

(2)普通變量做參數(shù),是各分單元的;

(3)在函數(shù)內(nèi)定義的量,只在本函數(shù)內(nèi)可見。

由此例可體會到通過參數(shù)傳遞地址即傳址調(diào)用(或稱引用調(diào)用reference)的好處,它可以減少函數(shù)間信息傳遞時需要復(fù)制的數(shù)量,從而提高信息傳遞效率。

關(guān)于值調(diào)用

(1)形參、實參有各自的存儲單元;

(2)函數(shù)調(diào)用時,將實參的值復(fù)制給形參。

(3)在函數(shù)中參加運算的是形參,形參單元值的改變不能影響實參單元。

“值調(diào)用”(callbyvalue)的方法是把實際參數(shù)的值復(fù)制到函數(shù)的形式參數(shù)中。這樣,函數(shù)中的形式參數(shù)的任何變化不會影響到調(diào)用時所使用的變量。傳值調(diào)用起到了數(shù)據(jù)隔離的作用,即不允許被調(diào)函數(shù)去修改元素變量的值。

關(guān)于引用調(diào)用

(1)形參與實參共用地址;

(2)調(diào)用函數(shù)可以修改原始變量的值。

“引用調(diào)用”(callbyreference)的方法是實際參數(shù)與形式參數(shù)共用地址,在函數(shù)中,這個地址用來訪問調(diào)用中所使用的實際參數(shù)。這意味著,形式參數(shù)的變化會影響調(diào)用時所使用的變量。

【例5-7】函數(shù)間信息傳遞的例子2。求數(shù)組intb[]中下標(biāo)為m到n項的和。主函數(shù)負(fù)責(zé)提供數(shù)組、m和n的值及結(jié)果的輸出,求和功能由子函數(shù)func完成。

【設(shè)計方案一】對函數(shù)結(jié)構(gòu)的設(shè)計如表5.18所示。

表5.18函數(shù)間信息傳遞的例子2之函數(shù)框架設(shè)計1把數(shù)組的信息通過傳址方式傳遞,m、n的值通過傳值方式傳遞,結(jié)果只有一個整型,可以通過return語句返回。表5.19給出了func函數(shù)的實現(xiàn)。

表5.19函數(shù)間信息傳遞的例子2之函數(shù)實現(xiàn)設(shè)計1程序?qū)崿F(xiàn):

1/*函數(shù)間信息傳遞的例子2——方案一*/

2#include"stdio.h"

3#defineSIZE10

4intfunc(intb[],intm,intn);

5

6/*求數(shù)組intb[]中下標(biāo)為m到n項的和*/

7intfunc(intb[],intm,intn)

8{inti,sum=0;

9

10 for(i=m;i<=n;i++)

11 {

12 sum=sum+b[i];

13 }

14returnsum;

15}

16

17intmain()

18{

19

intx;

20 inta[SIZE]={1,2,3,4,5,6,7,8,9,0};

21 intp=3,q=7;/*指定求和下標(biāo)的位置*/

22

23 printf("數(shù)組a下標(biāo)%d至%d項的元素為:",p,q);

24 for(inti=p;i<=q;i++)

25 {

26 printf("%d",a[i]);

27 }

28 printf("\n");

29

30 x=func(a,p,q);

31 printf("數(shù)組a下標(biāo)%d至%d項的元素和為:%d\n",p,q,x);

32 return0;

33}程序結(jié)果:

數(shù)組a下標(biāo)3~7項的元素為:45678

數(shù)組a下標(biāo)3~7項的元素和為:30

【設(shè)計方案二】我們?nèi)匀煌ㄟ^傳址方式傳遞數(shù)組的信息,既然是傳址,信息傳遞是雙向的,func的結(jié)果可以放在數(shù)組的約定位置,如數(shù)組的最后一個元素的位置,這樣就不用通過return語句返回了。采用這種方案,形參要增加一個“結(jié)果在b中存放的位置”,具體參見表5.20。

表5.20函數(shù)間信息傳遞的例子2之函數(shù)框架設(shè)計2

表5.21函數(shù)間信息傳遞的例子2之函數(shù)實現(xiàn)設(shè)計2程序?qū)崿F(xiàn):

1/*函數(shù)間信息傳遞的例子2——方案二*/

2#include"stdio.h"

3#defineSIZE10

4

5voidfunc(intb[],intm,intn,intsize);

6

7/*求數(shù)組intb[]中下標(biāo)為m到n項的和,結(jié)果放在下標(biāo)是size的位置*/

8 voidfunc(intb[],intm,intn,intsize)

9 {

10 inti,sum=0;

11

12 for(i=m;i<=n;i++)

13 {

14 sum=sum+b[i];

15 }

16 b[size]=sum;/*求和的結(jié)果放在b數(shù)組指定位置*/

17 }

18

19 intmain()

20 {

21 inta[SIZE]={1,2,3,4,5,6,7,8,9,0};

22 intp=3,q=7;/*指定求和下標(biāo)的位置*/

23

24 printf("數(shù)組a下標(biāo)%d至%d項的元素為:",p,q);

25 for(inti=p;i<=q;i++)

26 {

27 printf("%d",a[i]);

28 }

29 printf("\n");

30

31 func(a,p,q,SIZE-1);

32 printf("數(shù)組a下標(biāo)%d至%d項的元素和為:%d\n",p,q,a[SIZE-1]);

33 return0;

34 }

程序結(jié)果:

數(shù)組a下標(biāo)3~7項的元素為:45678

數(shù)組a下標(biāo)3~7項的元素和為:30

【例5-8】函數(shù)間信息傳遞的例子3。讀程序,分析結(jié)果。

1/*函數(shù)間信息傳遞的例子3*/

2#include"stdio.h"

3#include"string.h"

4voidi_s(charin[],charout[]);

5

6voidi_s(charin[],charout[])

7{

8

inti,j;

9

intl=strlen(in);

10

for(i=j=0;i<l;i++,j++)

11

{

12

out[j]=in[i]; /*步驟1*/

13 out[++j]='__'; /*步驟2*/

14 in[i]+=1; /*步驟3*/

15 }

16 out[j-1]='\0';

17}

18

19intmain()

20{

21

chars[]="1234";

22charg[20];

23

24i_s(s,g);

25printf("%s\n",g);

26return0;

27}通過上面函數(shù)間信息傳遞的規(guī)則,讀者可以自己分析例5-8,每個執(zhí)行步驟的中間結(jié)果項已經(jīng)列在表5.22中了,以方便讀程。

表5.22函數(shù)間信息傳遞的例子35.6.3函數(shù)間信息傳遞的總結(jié)

函數(shù)間信息傳遞的種類參見表5.23。

表5.23函數(shù)間信息傳遞的種類函數(shù)間信息傳遞的方式參見表5.24。

表5.24函數(shù)間信息傳遞的方式

表5.25函數(shù)間信息傳遞的途徑5.6.4共享數(shù)據(jù)的使用限制

通過前面的例子可知,函數(shù)間信息傳遞時有些數(shù)據(jù)往往是共享的,程序可以在不同的場合通過不同的途徑訪問同一個數(shù)據(jù)對象,有時在無意之中的誤操作會改變有關(guān)數(shù)據(jù)的狀況,而這是我們所不希望出現(xiàn)的。

既要使數(shù)據(jù)能在一定范圍內(nèi)共享,又要保證其不被任意修改,這時可以使用const,即把形參中有關(guān)數(shù)據(jù)定義為常量。

const是一個C語言的關(guān)鍵字,它限定一個變量不允許被改變。使用const在一定程度上可以提高程序的安全性和可靠性。

【例5-9】const的例子。使用const類型限定符來保護(hù)數(shù)組不被修改。

1/*const的例子*/

2#include<stdio.h>

3#defineSIZE3

4voidmodify(constinta[]);/*函數(shù)原型*/

5intb[SIZE];/*全局量,在函數(shù)之外定義的量,b數(shù)組用于保存修改后的數(shù)組*/

6

7/*程序從函數(shù)main開始執(zhí)行*/

8intmain()

9{

10inta[SIZE]={3,2,1};/*初始化*/

11inti;/*計數(shù)器*/

12

13modify(a);/*調(diào)用函數(shù)*/

14printf("\nmodify函數(shù)運行后的a數(shù)組為:");

15for(i=0;i<SIZE;i++)

16{

17printf("%3d",a[i]);/*打印出函數(shù)執(zhí)行后的數(shù)組*/

18}

19

20printf("\nmodify函數(shù)運行后的b數(shù)組為:");

21for(i=0;i<SIZE;i++)/*打印出修改后的數(shù)組*/

22{

23printf("%3d",b[i]);

24}

25return0;

26}

27

28/*取得數(shù)組a中的值,處理后保存在數(shù)組b中*/

29voidmodify(constinta[])

30{

31inti;/*計數(shù)器*/

32for(i=0;i<SIZE;i++)

33{

34/*a[i]=a[i]*2;試圖修改數(shù)組a的值,編譯將會報錯*/

35b[i]=a[i]*2;

36}

37}程序結(jié)果:

modify函數(shù)運行后的a數(shù)組為:321

modify函數(shù)運行后的b數(shù)組為:642

【題目】處理3位學(xué)生四門課程的成績:

(1)求所有成績中的最低、最高成績;

(2)每個學(xué)生的平均成績;

(3)輸出結(jié)果。5.7函數(shù)設(shè)計的綜合例子

【問題分析】

(1)數(shù)據(jù):把3位學(xué)生四門課程的成績存儲在表5.26所示的二維數(shù)組中。

studentGrades[學(xué)生數(shù)][課程門數(shù)]

表5.26函數(shù)設(shè)計的綜合例子(1)

(2)函數(shù)設(shè)計:參見表5.27。

表5.27函數(shù)設(shè)計的綜合例子(2)

(3)程序?qū)崿F(xiàn):

1 /*函數(shù)設(shè)計的綜合例子——多個函數(shù)對二維數(shù)組的處理*/

2 #include<stdio.h>

3 #defineSTUDENTS3

4 #defineEXAMS4

5

6 /*函數(shù)原型*/

7 intminimum(constintgrades[][EXAMS],intpupils,inttests);

8 intmaximum(constintgrades[][EXAMS],intpupils,inttests);

9 doubleaverage(constintsetOfGrades[],inttests);

10 voidprintArray(constintgrades[][EXAMS],intpupils,inttests);

11

12 /*程序從函數(shù)main開始執(zhí)行*/

13 intmain()

14 {

15 intstudent;/*學(xué)生計數(shù)器*/

16

17 /*初始化3個學(xué)生(行)的成績*/

18 intstudentGrades[STUDENTS][EXAMS]

19 ={{77,68,86,73},

20 {96,87,89,78},

21 {70,90,86,81}

22 };

23 /*輸出數(shù)組studentGrades*/

24 printf("Thearrayis:\n");

25 printArray(studentGrades,STUDENTS,EXAMS);

26

27 /*確定最高分?jǐn)?shù)與最低分?jǐn)?shù)*/

28 printf("\n\nLowestgrade:%d\nHighestgrade:%d\n",

29 minimum(studentGrades,STUDENTS,EXAMS),

30 maximum(studentGrades,STUDENTS,EXAMS));

31 /*計算每個學(xué)生的平均分?jǐn)?shù)*/

32 for(student=0;student<=STUDENTS-1;student++)

33

{

34 printf("Theaveragegradeforstudent%dis%.2f\n",

35 student,average(studentGrades[student],EXAMS));

36 }/*結(jié)束for*/

37

38 return0;/*表示程序成功結(jié)束*/

39

40 }/*結(jié)束main*/

41

42 /*找出最低分?jǐn)?shù)*/

43 intminimum(constintgrades[][EXAMS],intpupils,inttests)

44 {

45 inti;/*計數(shù)器*/

46 intj;/*計數(shù)器*/

47 intlowGrade=100;/*初始化為可能的最高分?jǐn)?shù)*/

48

49

for(i=0;i<pupils;i++)/*循環(huán)數(shù)組grades的行*/

50

{

51

for(j=0;j<tests;j++)/*循環(huán)數(shù)組grades的列*/

52

{

53 if(grades[i][j]<lowGrade)

54 {

55 lowGrade=grades[i][j];

56 }

57 }

58 }

59 returnlowGrade;/*返回最低分?jǐn)?shù)*/

60 }/*函數(shù)minimum結(jié)束*/

61

62 /*找出最高分?jǐn)?shù)*/

63 intmaximum(constintgrades[][EXAMS],intpupils,inttests)

64 {

65 inti;/*學(xué)生計數(shù)器*/

66 intj;/*考試計數(shù)器*/

67 inthighGrade=0;/*初始化為可能的最低分?jǐn)?shù)*/

68

69 for(i=0;i<pupils;i++)/*循環(huán)數(shù)組grades的行*/

70

{

71 f

溫馨提示

  • 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)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論