C程序設(shè)計語言揣錦華第2章函數(shù).ppt
《C程序設(shè)計語言揣錦華第2章函數(shù).ppt》由會員分享,可在線閱讀,更多相關(guān)《C程序設(shè)計語言揣錦華第2章函數(shù).ppt(97頁珍藏版)》請在裝配圖網(wǎng)上搜索。
第2章函數(shù) 2 1函數(shù)的定義與使用2 2函數(shù)調(diào)用機制2 3遞歸函數(shù)2 4默認(rèn)參數(shù)的函數(shù)2 5內(nèi)聯(lián)函數(shù)2 6函數(shù)重載2 7函數(shù)模板2 8使用C 系統(tǒng)函數(shù) 2 1函數(shù)的定義與使用 在編輯一個大型程序時 即使各個函數(shù)的前后順序不同 程序執(zhí)行的開始點永遠是主函數(shù) 主函數(shù)按照調(diào)用與被調(diào)用關(guān)系調(diào)用子函數(shù) 子函數(shù)如果與其它子函數(shù)又存在調(diào)用與被調(diào)用關(guān)系 當(dāng)然還可以再調(diào)用其它子函數(shù) 在一對調(diào)用與被調(diào)用關(guān)系中 我們把調(diào)用其它函數(shù)的函數(shù)稱為主調(diào)函數(shù) 被其它函數(shù)調(diào)用的函數(shù)稱為被調(diào)函數(shù) 在一個較為復(fù)雜的大型程序中 一個函數(shù)很可能同時扮演兩種不同的角色 主調(diào)函數(shù)與被調(diào)函數(shù) 即既調(diào)用別的函數(shù) 被調(diào)函數(shù) 又被另外的函數(shù) 主調(diào)函數(shù) 調(diào)用 函數(shù)一般應(yīng)遵守先定義后調(diào)用的原則 否則應(yīng)在調(diào)用函數(shù)中先進行原形說明 2 1 1函數(shù)的定義一個完整的函數(shù)定義由兩部分組成 即函數(shù)頭與函數(shù)體 1 函數(shù)定義的一般語法形式 形式參數(shù)表 說明性語句序列 實現(xiàn)函數(shù)功能的語句系列 函數(shù)頭是指上述格式中的 形式參數(shù)表 其中函數(shù)名可由函數(shù)設(shè)計者命名 可以是任何一個不重復(fù)的合法的標(biāo)識符 唯一的例外是 主函數(shù)必須命名為main 函數(shù)體是指上述格式中被一對大括號括起的復(fù)合語句部分 該函數(shù)所應(yīng)實現(xiàn)的功能由相應(yīng)的復(fù)合語句完成 2 函數(shù)的類型和返回值函數(shù)頭部分的類型標(biāo)識符規(guī)定了函數(shù)的返回值類型 函數(shù)的返回值是返回給主調(diào)函數(shù)的處理結(jié)果 由函數(shù)體部分的return語句帶回 例如 returnvalue1 無返回值的函數(shù)其類型標(biāo)識符為void 不必有return語句 3 形式參數(shù)函數(shù)頭部分的形式參數(shù) 簡稱形參 表的內(nèi)容如下 類型l形參名1 類型2形參名2 類型n形參名n其中類型1 類型2 類型n是類型標(biāo)識符 表示形參的數(shù)據(jù)類型 int double float char bool等 形參名1 形參名2 形參名n是形參名 合法的自定義標(biāo)識符 形參是用來實現(xiàn)主調(diào)函數(shù)與被調(diào)函數(shù)之間的數(shù)據(jù)聯(lián)系 通常將函數(shù)所處理的數(shù)據(jù) 影響函數(shù)功能的因素或者函數(shù)處理的結(jié)果作為形參 對于無形參的函數(shù) 其形參表的內(nèi)容應(yīng)該為空 但代表函數(shù)的小括號對不能省略 函數(shù)在沒有被調(diào)用的時候其形參只是一個符號 它標(biāo)志著在形參出現(xiàn)的位置應(yīng)該有一個什么類型的數(shù)據(jù) 函數(shù)在被調(diào)用時才由主調(diào)函數(shù)將實際參數(shù) 簡稱實參 賦予形參 從這一點上說 C 中的函數(shù)與數(shù)學(xué)中的函數(shù)概念極其相似 例如 我們都熟悉的如下數(shù)學(xué)中的函數(shù)形式 f x 3x2 5x 2這個函數(shù)只有當(dāng)自變量x被賦以確定的值以后 才能計算出函數(shù)的值 2 1 2函數(shù)的調(diào)用如果沒有遵守先定義后調(diào)用的原則 調(diào)用函數(shù)之前先要在主調(diào)函數(shù)中聲明函數(shù)原型 在主調(diào)函數(shù)中 或所有函數(shù)之前 按如下形式進行函數(shù)原型聲明 含類型說明的形參表 如果是在所有函數(shù)之前聲明了函數(shù)原型 那么該函數(shù)原型在本程序文件中任何地方都有效 也就是說 在本程序文件中任何地方都可以依照該原型調(diào)用相應(yīng)的函數(shù) 如果是在某個主調(diào)函數(shù)內(nèi)部聲明了被調(diào)函數(shù)原型 那么該原型就只能在這個函數(shù)內(nèi)部有效 聲明了函數(shù)原型之后 便可以按如下形式調(diào)用子函數(shù) 實參1 實參2 實參n 實參列表中應(yīng)給出與函數(shù)原型中形參個數(shù)相同 類型相符的實參 每個實參都可以是常量 變量或表達式三者之一 實參與實參之間用逗號作為分隔符 注意 這里的逗號不是順序求值運算符 函數(shù)調(diào)用可以作為一條語句 這時函數(shù)可以沒有返回值 函數(shù)調(diào)用也可以出現(xiàn)在表達式中 這時就必須有一個明確的返回值 函數(shù)調(diào)用示例如下 例2 1 編寫一個函數(shù) 把華氏溫度轉(zhuǎn)換為攝氏溫度 公式為C F 32 5 9 公式中F代表華氏溫度 C代表攝氏溫度 在主函數(shù)中提示用戶輸入一個華氏溫度 并完成輸入及輸出 由函數(shù)完成轉(zhuǎn)化功能 程序代碼如下 includefloathstoss floatfHuashi 原型說明voidmain floatfHuashi cout fHuashi cout 華氏 fHuashi 度對應(yīng)攝氏溫度 hstoss fHuashi 度 endl 函數(shù)調(diào)用作為一個表達式出現(xiàn)在輸出語句中 floathstoss floatfHuashi floatfSheshi fSheshi fHuashi 32 5 9 return fSheshi 程序運行結(jié)果為輸入一個華氏溫度值 68華氏68度對應(yīng)攝氏20度 例2 2 編寫一個求x的n次方的函數(shù) 分析 求x的n次方 實際是求x自乘n次的乘積 程序代碼如下 includedoublepower doubledDishu intiMi 原型說明voidmain cout 底數(shù)1 8的3次冪是 power 1 8 3 endl 函數(shù)調(diào)用作為一個表達式出現(xiàn)在輸出語句中 doublepower doubledDishu intiMi intiCount doubledResult 1 0 for iCount 1 iCount iMi iCount dResult dResult dDishu return dResult 程序運行結(jié)果為底數(shù)1 8的3次冪是5 832 例2 3 輸入一個8位的二進制數(shù) 將其轉(zhuǎn)換為十進制數(shù)后再輸出 對于非法輸入 除0和1以外的任何字符 應(yīng)給出提示信息 分析 將二進制數(shù)轉(zhuǎn)換為十進制數(shù) 只要將二進制數(shù)的每一位乘以該位的權(quán) 然后相加 例如 110100112 1 27 1 26 0 25 1 24 0 23 0 22 1 21 l 20 21110 所以 如果輸入00001101 則應(yīng)輸出13 可以直接引用例2 2中的函數(shù)power來求2的各次方 程序代碼如下 includedoublepower doubledDishu intiMi 函數(shù)原型說明voidmain intiCount 8 intiValue 0 charcChar boolbFlag true cout0 cin cChar if cChar 1 iCount if bFlag cout 十進制值為 iValue endl doublepower doubledDishu intiMi intiCount doubledResult 1 0 for iCount 1 iCount iMi iCount dResult dResult dDishu return dResult 輸入符合要求時 僅有字符0和1 的程序運行結(jié)果為輸入一個8位的二進制數(shù) 11010011十進制值 211輸入不符合要求時 含有除0和1以外的任何字符 的程序運行結(jié)果為輸入一個8位的二進制數(shù) 110lao11這不是一個二進制數(shù) 不能正確轉(zhuǎn)換 例2 4 編寫一個函數(shù)可用來判斷任給的一個正整數(shù)是否為素數(shù) 或質(zhì)數(shù) 再編寫主程序完成輸入 調(diào)用和輸出 素數(shù)是指只能被1和它自身整除的數(shù) 分析 素數(shù)的逆定義就是 一但某數(shù)n能被2 3 n 1中的任何一個數(shù)除盡 只要除法中有一次余數(shù)為零 則n肯定不是一個素數(shù) 某數(shù)n若依次除以2 3 n 1 結(jié)果都除不盡 有余數(shù) 則n肯定是一個素數(shù) 程序代碼如下 includeintiIsprime intiNum voidmain intiNum cout iNum if iIsprime iNum 1 cout iNum 是一個素數(shù) endl elsecout iNum 不是一個素數(shù) endl intiIsprime intiNum intiChushu boolbFlag false for iChushu 2 iChushu iNum 1 iChushu if iNum iChushu 0 bFlag true break if bFlag false return1 elsereturn0 第一次程序運行結(jié)果為請輸入一個正整數(shù) 3131是一個素數(shù)第二次程序運行結(jié)果為請輸入一個正整數(shù) 119119不是一個素數(shù) 2 1 3函數(shù)的參數(shù)傳遞函數(shù)的參數(shù)用于在調(diào)用函數(shù)與被調(diào)用函數(shù)之間進行數(shù)據(jù)傳遞 在函數(shù)定義時 函數(shù)名后面括號內(nèi)的參數(shù)稱為形式參數(shù) 簡稱形參 在函數(shù)被調(diào)用時 函數(shù)名后面括號內(nèi)的參數(shù)稱為實際參數(shù) 簡稱實參 當(dāng)函數(shù)未被調(diào)用時 C 編譯系統(tǒng)并沒有給函數(shù)的形參分配相應(yīng)的內(nèi)存空間 函數(shù)的形參更不會有實際的值 只有在函數(shù)被調(diào)用時 C 編譯系統(tǒng)這時才為形參分配實際的存儲單元 并將實參與形參結(jié)合 實參可以是常量 變量或表達式 其類型必須與形參相符 函數(shù)的參數(shù)傳遞 指的就是形參與實參結(jié)合 簡稱形實結(jié)合 的過程 形實結(jié)合的方式有值調(diào)用和引用調(diào)用兩種 1 值調(diào)用值調(diào)用是指當(dāng)發(fā)生函數(shù)調(diào)用時 編譯系統(tǒng)為形參分配相應(yīng)的存儲空間并且直接將實參的值復(fù)制給形參 這樣形參和實參就各自擁有不同的存儲單元 且形參是實參的副本 因此 值調(diào)用過程是參數(shù)值的單向傳遞過程 一旦形參獲得了與實參相同的值就與實參脫離關(guān)系 以后不論形參發(fā)生多大的改變 都決不會反過來影響到實參 前面2 1 2節(jié)中的四道例題均屬于值調(diào)用方式 例2 5 從鍵盤輸入兩個整數(shù) 交換位置后輸出 交換未成功 includevoidswap inta intb voidmain intx y x 5 y 10 cout x x y y endl swap x y 交換x y的值 cout afterswap endl cout x x y y endl voidswap inta intb intt t a a b b t 程序運行結(jié)果為x 5y 10afterswapx 5y 10分析 從上面的程序運行結(jié)果可以看出 并沒有達到交換的目的 這是因為采用的傳遞方式不合乎問題的要求 在單向值傳遞方式中 形參值雖確實進行了交換 但這些改變對實參不起任何作用 執(zhí)行主調(diào)函數(shù)中的函數(shù)調(diào)用語句swap x y 后 編譯系統(tǒng)將實參x中的值5傳遞給虛參a 將實參y中的值10傳遞給虛參b 在swap函數(shù)中 a b中的值完成互換 返回主函數(shù)時 實參x y中的值不受虛參a b的影響 并未進行交換 2 引用調(diào)用顯而易見 值調(diào)用時參數(shù)的傳遞方式是實參單向復(fù)制其值給虛參 如果我們想使子函數(shù)中對形參所做的任何更改也能及時反映給主函數(shù)中的實參 即希望形參與實參的影響是互相的或稱是雙向的 又該怎么辦呢 這就需要改變調(diào)用方式 即采用第二種參數(shù)傳遞方式 引用調(diào)用 引用是一種特殊類型的變量 可以被認(rèn)為是某一個變量的別名 通過引用名與通過被引用的變量名訪問變量的效果是一樣的 這就是說 對形參的任何操作也就直接作用于實參 例如 inta b int注意 聲明一個引用時 必須同時對它進行初始化 使它與一個已存在的對象關(guān)聯(lián) 一旦一個引用被初始化后 就不能改變關(guān)聯(lián)對象 換言之 一個引用從它被聲明之后 就必須確定是哪個變量的別名 而且自始至終只能作為這一個變量的別名 不能另作他用 形參也可以引用的方式出現(xiàn)在形參表中 引用作為形參的情況與變量的引用稍有不同 這是因為 形參的初始化不在類型說明時進行 而是在執(zhí)行主調(diào)函數(shù)中的調(diào)用語句時 才為形參分配內(nèi)存空間 同時用實參來初始化形參 例2 6 使用引用調(diào)用改寫例2 5的程序 使兩實參中的數(shù)真正進行互換 includevoidswap int voidswap int 程序運行結(jié)果為x 5y 10afterswapx 10y 5 分析 子函數(shù)swap的兩個參數(shù)都是引用 當(dāng)被調(diào)用時 它們分別被初始化成為a和b的別名 因此 在子函數(shù)swap中將兩個參數(shù)的值進行交換后 交換結(jié)果可以返回主函數(shù)main 2 2函數(shù)調(diào)用機制 一個C 的源程序經(jīng)過編譯以后形成與源程序主名相同但后綴為 exe的可執(zhí)行文件 且存放在外存儲器中 當(dāng)該 exe的可執(zhí)行程序被運行時 首先從外存將程序代碼裝載到內(nèi)存的代碼區(qū) 然后從main函數(shù)的起始處開始執(zhí)行 程序在執(zhí)行過程中 如果遇到了對其它函數(shù)的調(diào)用 則暫停當(dāng)前函數(shù)的執(zhí)行 保存下一條指令的地址 即返回地址 作為從子函數(shù)返回后繼續(xù)執(zhí)行的入口點 并保存現(xiàn)場 主要是一些寄存器的內(nèi)容 然后轉(zhuǎn)到子函數(shù)的入口地址 執(zhí)行子函數(shù) 當(dāng)遇到return語句或者子函數(shù)結(jié)束時 則恢復(fù)先前保存的現(xiàn)場 并從先前保存的返回地址開始繼續(xù)執(zhí)行 圖2 1說明了函數(shù)調(diào)用和返回的過程 圖中標(biāo)號標(biāo)明了執(zhí)行順序 圖2 1函數(shù)調(diào)用和返回的示意圖 例2 7 求設(shè)N 10 X 2 4 6 8 即求N事件中每次取2 4 6 8的組合數(shù) 分析 這個問題需要反復(fù)利用兩個公式 N N X N X 設(shè)計兩個函數(shù) 一個求整數(shù)階乘的函數(shù)lJiecheng和一個求組合數(shù)的函數(shù)lComb 由主函數(shù)main調(diào)用lComb lComb又調(diào)用lJiecheng 程序代碼如下 includelonglJiecheng intn longrt 1 inti for i 1 i n i rt rt i returnrt longlComb intN intX returnlJiecheng N lJiecheng X lJiecheng N X voidmain longlJiecheng intn longlComb intN intX intiNum x do cout iNum while iNum 10 for x 2 x 10 x 2 cout C iNum x lComb iNum x endl 程序運行結(jié)果為請輸入事件數(shù) 大于等于8 11C 11 2 55C 11 4 330C 11 6 462C 11 8 165 2 3遞歸函數(shù) 遞歸函數(shù)又稱為自調(diào)用函數(shù) 其特點是 在函數(shù)內(nèi)部直接或間接地自己調(diào)用自己 所謂直接調(diào)用自身 就是指在一個函數(shù)的函數(shù)體中出現(xiàn)了對自身的調(diào)用語句 例如 voidfunc1 void func1 func1調(diào)用func1自身 所謂間接調(diào)用自身 就是一個函數(shù)func1調(diào)用另一個函數(shù)func2 而函數(shù)func2中又調(diào)用了函數(shù)func1 于是構(gòu)成間接遞歸 下面的例子屬于間接調(diào)用情況 voidfunc1 void func2 func1調(diào)用func2 voidfunc2 void func1 func2調(diào)用func1 func1函數(shù)就是通過func2實現(xiàn)間接遞歸 遞歸算法的實質(zhì)是將原有的問題分解為新的問題 而解決新問題時又用到了原有問題的解法 按照這一原則分解下去 每次出現(xiàn)的新問題都是原有問題的簡化的子集 而最終分解出來的問題 是一個已知解的問題 這便是有限的遞歸調(diào)用 例2 8 編寫函數(shù) 用遞歸的方法求n 的值 在主程序中實現(xiàn)任意輸入n值并輸出計算結(jié)果 分析 計算n 的公式如下 1 n 0 n n n 1 n 0 這是一個遞歸形式的公式 在描述階乘算法時 又用到了階乘 只不過求階乘的數(shù)在逐次減1 因而編程時也自然采用遞歸算法 遞歸的結(jié)束條件是n 0 程序代碼如下 includelongjc intn longrt if n 0 cout Dataerror endl elseif n 0 rt 1 遞歸的結(jié)束條件elsert n jc n 1 以參數(shù)減1的方式繼續(xù)遞歸returnrt voidmain longjc intn intn longresult do cout n while n 0 result jc n 首次調(diào)用處cout n result endl 程序運行結(jié)果為輸入一個正整數(shù) 66 720 例2 9 有5個人坐在一起 問第1個人多少歲 他說比第2個人大2歲 問第2個人多少歲 他說比第3個人大2歲 問第3個人多少歲 他說比第4個人大2歲 問第4個人多少歲 他說比第5個人大2歲 最后問第5個人 他說是12歲 請問第1個人多少歲 分析 這是一個遞歸問題 每一個人的年齡都比其后那個人的年齡大2 即 age 1 age 2 2age 2 age 3 2age 3 age 4 2age 4 age 5 2age 5 12可以用公式表示如下 12 n 5 age n age n 1 2 n 5 程序代碼如下 includeintage intn intss if n 5 ss 12 elsess age n 1 2 return ss voidmain intage intn cout 第一個人的年齡為 age 1 歲 endl 程序運行結(jié)果為第一個人的年齡為20歲 2 4默認(rèn)參數(shù)的函數(shù) 在函數(shù)定義中通過賦值運算就可指定默認(rèn)參數(shù)值 一旦程序在調(diào)用該函數(shù)時 如果給出實參 則用實參初始化形參 如果沒有給出實參 則C 編譯系統(tǒng)自動以預(yù)先賦值的默認(rèn)參數(shù)值作為傳入數(shù)值 一般情況下都將調(diào)用該函數(shù)時經(jīng)常用到的常數(shù)作為默認(rèn)參數(shù)值 這樣在調(diào)用時就無需每次都寫出該值了 指定默認(rèn)參數(shù)值可以使函數(shù)的使用更為簡單 同時也增強了函數(shù)的可重用性 例2 10 帶默認(rèn)形參值的函數(shù)例題 includeintmult intn intk 2 第二個形參具有默認(rèn)值 if k 2 return n n elsereturn mult n k 1 n voidmain cout endl mult 5 endl 形參n用實參來初始化為5 形參k采用默認(rèn)值2 實現(xiàn)5 5 cout mult 5 3 endl 用實參來初始化形參 n為5 k為3 實現(xiàn)5 5 5 程序運行結(jié)果為25125 默認(rèn)形參值必須按從右向左的順序定義 在有默認(rèn)值的形參右面 不能出現(xiàn)無默認(rèn)值的形參 因為在調(diào)用時 實參初始化形參是按從左向右的順序 例如 voidtry intj 3 intk 非法voidtry intj intk 2 intm 非法voidtry intj intk 7 合法voidtry intj intk 2 intm 3 合法voidtry intj 3 intk 2 intm 3 合法 默認(rèn)形參值應(yīng)該在函數(shù)原型中給出 例如 intmulti intx 2 inty 5 默認(rèn)形參值在函數(shù)原型中給出voidmain multi 并非無參調(diào)用 而是采用默認(rèn)值 x取值2 y取值5 intmulti intx inty return x y 在相同的作用域內(nèi) 默認(rèn)形參值的說明應(yīng)保持唯一 但如果在不同的作用域內(nèi) 允許說明不同的默認(rèn)形參 這里的作用域是指直接包含著函數(shù)原型說明的大括號所界定的范圍 對作用域概念的詳細(xì)介紹請參閱第5章 例如 intadd intx 2 inty 5 全局默認(rèn)形參值voidmain intadd intx 1 inty 9 局部默認(rèn)形參值 add 此處調(diào)用時 采用局部默認(rèn)形參值 x取值1 y取值9 voidfunc void add 此處調(diào)用時 采用全局默認(rèn)形參值 x取值2 y取值5 2 5內(nèi)聯(lián)函數(shù) 內(nèi)聯(lián)函數(shù) 也稱在線函數(shù) 是在C 中為提高程序運行效率而引入的 所有函數(shù)調(diào)用時都會產(chǎn)生一些額外的開銷 主要是系統(tǒng)棧的保護 代碼的傳遞 系統(tǒng)棧的恢復(fù)以及參數(shù)傳遞等 對于一些函數(shù)體很小但又經(jīng)常使用的函數(shù) 由于被調(diào)用的頻率非常高 這種額外開銷也就很可觀 有時甚至?xí)\行效率產(chǎn)生本質(zhì)的影響 使用內(nèi)聯(lián)函數(shù)正是解決這一問題的手段 內(nèi)聯(lián)函數(shù)不是在調(diào)用時發(fā)生轉(zhuǎn)移 而是在編譯時將函數(shù)體嵌入在每一個調(diào)用語句處 這樣就相對節(jié)省了參數(shù)傳遞 系統(tǒng)棧的保護與恢復(fù)等的開銷 內(nèi)聯(lián)函數(shù)在定義時使用關(guān)鍵字inline區(qū)別于一般函數(shù) 其語法形式如下 含類型說明的形參表 函數(shù)體 例如 inlineintmul inta intb returna b 當(dāng)程序中出現(xiàn)mul 2 3 4 的函數(shù)調(diào)用時 編譯程序就會將其擴展為 2 3 4 關(guān)鍵字inline是一個編譯命令 編譯程序在遇到這個命令時將記錄下來 在處理內(nèi)聯(lián)函數(shù)的調(diào)用時 編譯程序就試圖產(chǎn)生擴展碼 這樣從使用者的角度來看 內(nèi)聯(lián)函數(shù)在語法上與一般函數(shù)沒有什么區(qū)別 只是在編譯程序生成目標(biāo)代碼時才區(qū)別處理 注意 內(nèi)聯(lián)函數(shù)體內(nèi)一般不能有循環(huán)語句和switch語句 內(nèi)聯(lián)函數(shù)的定義必須出現(xiàn)在第一次被調(diào)用之前 對內(nèi)聯(lián)函數(shù)不能進行異常接口聲明 如果違背了上述注意事項中的任一項 編譯程序就會無視關(guān)鍵字inline的存在 像處理一般函數(shù)一樣處理 不生成擴展代碼 因此 只有很簡單而使用頻率很高的函數(shù)才被說明為內(nèi)聯(lián)函數(shù) 內(nèi)聯(lián)函數(shù)會擴大目標(biāo)代碼 使用時要謹(jǐn)慎 例2 11 內(nèi)聯(lián)函數(shù)例題 include includeinlineintmax inta intb if a b returna elsereturnb voidmain inta b c d a 210 b 150 c 20 d max a b d max d c 編譯時兩個調(diào)用處均被替換為max函數(shù)體語句 cout Thebiggestof setw 5 a setw 5 b setw 5 c is d endl 程序運行結(jié)果為Thebiggestof21015020is210 2 6函數(shù)重載 函數(shù)的重載也稱多態(tài)函數(shù) C 編譯系統(tǒng)允許為兩個或兩個以上的函數(shù)取相同的函數(shù)名 但是形參的個數(shù)或者形參的類型不應(yīng)相同 編譯系統(tǒng)會根據(jù)實參和形參的類型及個數(shù)的最佳匹配 自動確定調(diào)用哪一個函數(shù) 這就是所謂的函數(shù)重載 對于沒有重載機制的C語言 每個函數(shù)必須有其不同于其它函數(shù)的名稱 即使操作是相同的 僅僅數(shù)據(jù)的類型不相同 也需要定義名稱完全不同的函數(shù) 這樣就顯得重復(fù)且效率低下 例如 定義求平方函數(shù) 就必須對整數(shù)的平方 浮點數(shù)的平方以及雙精度數(shù)的平方分別用不同的函數(shù)名 intisq intx inty floatfsq floatx floaty doubledsq doublex doubley 程序在調(diào)用這三個不同類型的函數(shù)時 是以名字加以區(qū)別的 需要記住并區(qū)別它們的名稱 顯然 這樣就造成了代碼的重復(fù) 使用起來也不方便 更不利于代碼的維護 對于具有重載機制的C 語言 允許功能相近的函數(shù)在相同的作用域內(nèi)以相同函數(shù)名定義 因而使函數(shù)方便使用 便于記憶 也使程序設(shè)計更加靈活 仍以上例而言 在C 中只要用一個函數(shù)名即可 如square 然后以賦給此函數(shù)的參數(shù)類型來決定是要計算int型 float型 還是double型的數(shù)的平方 上例在C 中的定義形式如下 intsquare intx floatsquare floatx doublesquare doublex 要計算square 3 時 C 自動使用第一種形式 計算square 3 25 時 C 自動使用第三種形式 計算square 3 25f 時 C 自動使用第二種形式 但是決不可以定義兩個具有相同名稱 相同參數(shù)類型和相同參數(shù)個數(shù) 只是函數(shù)返回值不同的重載函數(shù) 例如 以下定義是C 不允許的 intfunc intx floatfunc intx 由此可見 C 是按函數(shù)的參數(shù)表分辨相同名稱的函數(shù) 如果參數(shù)表相同 則認(rèn)為是錯誤的說明 C 允許重載函數(shù)有數(shù)量不同的參數(shù)個數(shù) 當(dāng)函數(shù)名相同而參數(shù)個數(shù)不同時 C 會自動按參數(shù)個數(shù)定向到正確的要調(diào)用的函數(shù) 下例說明了C 的這一特性 例2 12 重載函數(shù)應(yīng)用例題 includeintadd intx inty intsum sum x y return sum intadd intx inty intz intsum sum x y z return sum voidmain inta b a add 5 10 b add 5 10 20 cout a a b b endl 程序運行結(jié)果為a 15b 35 2 7函數(shù)模板 有很多時候 我們希望所設(shè)計的算法可以處理多種數(shù)據(jù)類型 但是 即使這一算法被設(shè)計為重載函數(shù) 也只是使用相同的函數(shù)名 函數(shù)體仍然要分別定義 如下面兩個求較小值的函數(shù) intsmall intx inty returnx y x y doublesmall doublex doubley returnx y x y 考察以上兩個函數(shù) 有如下特點 只有參數(shù)類型不同 返回值類型不同 功能則完全一樣 類似這樣的情況 可以使用函數(shù)模板 從而避免函數(shù)體的重復(fù)定義 函數(shù)模板可以用來創(chuàng)建一個通用功能的函數(shù) 以支持多種不同形參 簡化重載函數(shù)的函數(shù)體設(shè)計 它的最大特點是把函數(shù)所使用的數(shù)據(jù)類型作為參數(shù) 函數(shù)模板的定義形式如下 函數(shù)定義 例2 13 定義一個能交換兩個變量值的函數(shù) 要求用模板函數(shù)實現(xiàn) includetemplatevoidswap T voidmain intm 1 n 8 doubleu 5 5 v 99 3 cout m m n n endl cout u u v v endl swap m n 整型swap u v 雙精度型cout m與n u與v交換以后 endl cout m m n n endl cout u u v v endl 程序運行結(jié)果為m 1n 8u 5 5v 99 3m與n u與v交換以后 m 8n 1u 99 3v 5 5分析 編譯系統(tǒng)從調(diào)用swap 時 根據(jù)實參的類型推導(dǎo)出函數(shù)模板的類型參數(shù) 于調(diào)用swap m n 由于實參m及n為int類型 所以 推導(dǎo)出模板中類型參數(shù)T為int 當(dāng)類型參數(shù)的含義確定后 編譯器將以函數(shù)模板為樣板生成一個函數(shù) intswap int x int y intz z y y x x z 同樣 對于調(diào)用swap u v 由于實參u v為double類型 所以 推導(dǎo)出模板中類型參數(shù)T為double 接著 編譯器將以函數(shù)模板為樣板 生成如下函數(shù) doubleswap double x double y doublez z y y x x z 因此 當(dāng)主函數(shù)第一次調(diào)用swap 時 執(zhí)行的實際上是由函數(shù)模板生成的函數(shù) intswap int x int y 當(dāng)主函數(shù)第二次調(diào)用swap 時 執(zhí)行的實際上是由函數(shù)模板生成的函數(shù) doubleswap double x double y 2 8使用C 系統(tǒng)函數(shù) C 不僅允許我們根據(jù)需要自定義函數(shù) 而且C 的系統(tǒng)庫中還提供了幾百個常用函數(shù)可供程序員使用 如求平方根函數(shù) sqrt 求浮點數(shù)或雙精度數(shù)的絕對值函數(shù) fabs 對數(shù)函數(shù) log 指數(shù)函數(shù) exp 三角函數(shù)等都屬于數(shù)學(xué)函數(shù) 輸入 輸出格式控制函數(shù)有setw setprecision 等 由前面已學(xué)習(xí)的知識可知 調(diào)用函數(shù)之前必須先聲明函數(shù)原型 系統(tǒng)函數(shù)的原型聲明已經(jīng)全部由系統(tǒng)提供了 并且已分類存在于不同的頭文件中 程序員需要做的事情 就是用include指令嵌入相應(yīng)的頭文件 然后便可以使用系統(tǒng)函數(shù)了 例如 要使用基本輸入 輸出流函數(shù)cin cout 函數(shù) 就必須嵌入頭文件iostream h 若要使用數(shù)學(xué)函數(shù) 如求絕對值函數(shù)abs fabs 三角函數(shù)sin cos tan 開平方函數(shù)sqrt 對數(shù)值函數(shù)log 以e為底的指數(shù)函數(shù)exp 就要嵌入頭文件math h 同樣 要使用輸入 輸出格式控制函數(shù)setw setprecision 就要嵌入頭文件iomanip h 例2 14 系統(tǒng)函數(shù)應(yīng)用例題 從鍵盤輸入一個角度值 求出該角度的正弦值 余弦值和正切值 分析 系統(tǒng)函數(shù)中提供了求正弦值 余弦值和正切值的函數(shù) sin cos 及tan 函數(shù)的說明在頭文件math h中 同樣 系統(tǒng)函數(shù)中也提供了輸入 輸出格式控制函數(shù) 如輸出域?qū)捒刂坪瘮?shù)setw 輸出精度控制函數(shù)setprecision 函數(shù)的說明在頭文件iomanip h中 因此 需要用到這些系統(tǒng)函數(shù)時 就必須將該函數(shù)所屬的頭文件以 include或 include 頭文件名 的形式寫在程序代碼開始部分 程序代碼如下 include include includeconstdoublepi 3 14159265 voidmain doublea b cin a b a pi 180 cout sin a setw 10 sin b endl cout cos a setw 10 cos b endl cout tan a setw 10 tan b endl 程序運行結(jié)果為輸入 30sin 30 0 5cos 30 0 866025tan 30 0 57735 充分利用系統(tǒng)函數(shù) 可以大大減少編程的工作量 提高程序的運行效率和可靠性 要使用系統(tǒng)函數(shù) 應(yīng)該注意以下兩點 了解所使用的C 開發(fā)環(huán)境提供了哪些系統(tǒng)函數(shù) 不同的編譯系統(tǒng)提供的系統(tǒng)函數(shù)有所不同 確定要使用的系統(tǒng)函數(shù)的聲明在哪個頭文件中 這也可以在庫函數(shù)參考手冊或聯(lián)機幫助中查到 例如 在MSDNLibraryVisualStudio6 0中查找VC 6 0系統(tǒng)函數(shù)的分類列表 首先在 活動子集 欄選擇VisualC Documentation 然后按如下路徑選擇 VisualC Documentation UsingVisualC VisualC Programmer sGuide Run TimeLibraryReference Run TimeRoutinesbyCategory Run TimeRoutinesbyCategory 如圖2 2 該幫助系統(tǒng)中將函數(shù)按如下分類列出 獲取參數(shù) Argumentaccess 浮點支持 Floating pointsupport 緩沖區(qū)操作 Buffermanipulation 輸入與輸出 Inputandoutput 字節(jié)分類 Byteclassification 國際化 Internationalization 字符分類 Characterclassification 內(nèi)存分配 Memoryallocation 數(shù)據(jù)轉(zhuǎn)換 Dataconversion 處理機與環(huán)境控制 Processandenvironmentcontrol 調(diào)試 Debug 查找與排序 Searchingandsorting 目錄控制 Directorycontrol 字符串操作 Stringmanipulation 錯誤處理 Errorhandling 系統(tǒng)調(diào)用 Systemcalls 異常處理 Exceptionhandling 時間管理 Timemanagement 文件處理 Filehandling 圖2 2MSDNLibraryVisualStudio6 0窗口- 1.請仔細(xì)閱讀文檔,確保文檔完整性,對于不預(yù)覽、不比對內(nèi)容而直接下載帶來的問題本站不予受理。
- 2.下載的文檔,不會出現(xiàn)我們的網(wǎng)址水印。
- 3、該文檔所得收入(下載+內(nèi)容+預(yù)覽)歸上傳者、原創(chuàng)作者;如果您是本文檔原作者,請點此認(rèn)領(lǐng)!既往收益都?xì)w您。
下載文檔到電腦,查找使用更方便
14.9 積分
下載 |
- 配套講稿:
如PPT文件的首頁顯示word圖標(biāo),表示該PPT已包含配套word講稿。雙擊word圖標(biāo)可打開word文檔。
- 特殊限制:
部分文檔作品中含有的國旗、國徽等圖片,僅作為作品整體效果示例展示,禁止商用。設(shè)計者僅對作品中獨創(chuàng)性部分享有著作權(quán)。
- 關(guān) 鍵 詞:
- 程序設(shè)計語言 揣錦華第 函數(shù)
鏈接地址:http://www.820124.com/p-8616246.html