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

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

第4章函數(shù)4.1函數(shù)的定義

4.2函數(shù)參數(shù)與返回值

4.3函數(shù)調用

4.4函數(shù)的嵌套調用4.5變量的作用域4.6變量的存儲類別

4.1函?數(shù)?的?定?義

4.1.1函數(shù)的基本概念

C程序中有一個函數(shù)是必須存在的,這就是main函數(shù)(又稱為主函數(shù))。main函數(shù)是唯一的,它是C程序執(zhí)行的入口,即程序開始執(zhí)行時,系統(tǒng)首先調用main函數(shù)執(zhí)行。

C程序中所有函數(shù)的定義是平行的,函數(shù)之間不存在嵌套或從屬的關系,但是函數(shù)之間可以相互調用。除main函數(shù)不能被其他函數(shù)調用外,其他函數(shù)都是一個可以反復使用的程序段。函數(shù)是通過被調用而執(zhí)行的。

【例4.1】

編寫程序計算兩個整數(shù)絕對值階乘之差。

程序如下:圖4.1輸入-7和2時的運行結果例4.1的程序由main和fac兩個函數(shù)組成。其中fac函數(shù)的功能是求整數(shù)的階乘。程序的執(zhí)行從main函數(shù)開始,首先調用函數(shù)printf輸出提示信息,調用函數(shù)scanf輸入數(shù)據(jù)。然后先后兩次調用函數(shù)fac:第一次調用fac函數(shù)時,由main函數(shù)轉到fac函數(shù)執(zhí)行,計算x絕對值的階乘,函數(shù)執(zhí)行完后,結果由return語句返回main函數(shù);第二次調用fac函數(shù)計算y絕對值的階乘。最后調用函數(shù)printf輸出計算結果,程序執(zhí)行結束。在執(zhí)行函數(shù)fac時還調用了函數(shù)abs計算n的絕對值。

從上面的例子可以看出,函數(shù)是有區(qū)別的。有一種函數(shù)可以直接使用,例如例4.1中的scanf、printf和abs函數(shù),它們是由C系統(tǒng)提供的,稱做C系統(tǒng)的系統(tǒng)函數(shù)或庫函數(shù)。還有一種函數(shù)用戶必須定義(即創(chuàng)建)后才能使用,例如例4.1中的fac函數(shù),稱做用戶自定義函數(shù)。使用C語言編程,一定要了解有哪些系統(tǒng)函數(shù)才能有效利用系統(tǒng)提供的資源。

4.1.2函數(shù)的定義

編寫C程序的主要工作就是編寫用戶自定義函數(shù),即所謂的函數(shù)定義。函數(shù)定義的一般形式如下:

類型標識符函數(shù)名(形式參數(shù)表列)

{??聲明部分

執(zhí)行部分

}輸入“23,4”時,程序運行結果如圖4.2所示。

編寫函數(shù)時,函數(shù)名要符合標識符的命名規(guī)則,例如,start_information和end_information。關于函數(shù)有如下說明:

(1)函數(shù)定義時的參數(shù)稱為形式參數(shù),簡稱形參。形式參數(shù)列表說明的是函數(shù)間要傳遞的數(shù)據(jù)。調用函數(shù)與被調用函數(shù)之間的數(shù)據(jù)傳遞就是依靠形式參數(shù)在調用時接收數(shù)據(jù)來完成的。圖4.2例4.2的運行結果

(2)形式參數(shù)列表由各個參數(shù)的名字和類型說明組成。形參列表中若有多個形參,形參之間用逗號分隔。例如,“intsum(intx1,intx2)”說明sum函數(shù)有兩個整型參數(shù)x1,x2,即調用函數(shù)時需要傳遞的數(shù)據(jù)是兩個整型數(shù)據(jù)。

(3)如果在形式參數(shù)列表中只列出參數(shù)名,則需要在其后說明每個參數(shù)的類型,函數(shù)定的形式變?yōu)?/p>

(4)如果函數(shù)不需要數(shù)據(jù)傳遞,則形式參數(shù)表為空,但“()”不能省略。例如start_information()和end_information()。

(5)花括號內的內容稱為“函數(shù)體”。聲明部分對函數(shù)內使用的變量進行定義和聲明,以及對被調用函數(shù)進行的聲明。執(zhí)行部分是實現(xiàn)函數(shù)功能的語句序列。

4.2函數(shù)參數(shù)與返回值

4.2.1函數(shù)的參數(shù)

函數(shù)的參數(shù)分為形參和實參兩種。形參出現(xiàn)在函數(shù)定義中,在整個函數(shù)體內都可以使用,若離開該函數(shù)則不能使用;實參出現(xiàn)在主調函數(shù)中。形參和實參的功能是作數(shù)據(jù)傳送,發(fā)生函數(shù)調用時,主調函數(shù)把實參的值傳送給被調函數(shù)的形參,從而實現(xiàn)主調函數(shù)向被調函數(shù)的數(shù)據(jù)傳送。

函數(shù)的形參和實參具有以下特點。

(1)形參變量只有在被調用時才分配內存單元,在調用結束時,即刻釋放所分配的內存單元。因此形參只有在函數(shù)內部有效,函數(shù)調用結束返回主調函數(shù)后,就不能再使用該形參變量。

(2)實參可以是常量、變量、表達式、函數(shù)等,無論實參是何種類型的量,在進行函數(shù)調用時,它們都必須具有確定的值,以便把這些值傳送給形參。因此應預先用賦值、輸入等辦法使實參獲得確定值。

(3)實參和形參在數(shù)量、類型、順序上應嚴格一致,否則會發(fā)生“類型不匹配”的錯誤。

(4)函數(shù)調用中發(fā)生的數(shù)據(jù)傳送是單向的,即只能把實參的值傳送給形參,而不能把形參的值反向地傳送給實參。因此在函數(shù)調用過程中,形參的值發(fā)生改變對實參的值不會有影響。圖4.3例4.3運行結果4.2.2函數(shù)的返回值

函數(shù)的返回值是指函數(shù)被調用后,執(zhí)行函數(shù)體的程序段所取得并返回給主調函數(shù)的值,如調用正弦函數(shù)取得的正弦值、調用max函數(shù)取得的最大值等。

(1)函數(shù)的值只能通過return語句返回主調函數(shù)。

return語句格式為

return(<表達式>);

return語句有如下兩個功能:

①return語句將表達式的計算結果返回給主調函數(shù);

②結束return語句所在函數(shù)的執(zhí)行,返回到調用該函數(shù)的主調函數(shù)中繼續(xù)執(zhí)行。圖4.4例4.4的運行結果程序說明:程序執(zhí)行到product函數(shù)的return語句時,return語句將s的值返回到main函數(shù),在結束product函數(shù)的執(zhí)行后,返回main函數(shù)繼續(xù)執(zhí)行。return語句返回的s值在main函數(shù)中賦值給了變量p。

(2)函數(shù)返回值的類型應為定義函數(shù)時函數(shù)的類型。若函數(shù)類型與return語句中表達式值的類型不一致,則以函數(shù)類型為準進行類型轉換。例如,如果product函數(shù)為

return語句返回值是float類型,而函數(shù)類型為double,則將返回值轉換成double類型返回。

(3)沒有返回值的函數(shù)用void定義其函數(shù)類型。否則,函數(shù)即使不用return語句返回值,函數(shù)仍將返回一個不確定的值。如例4.2中的start_information和end_information函數(shù)。

(4)如果return語句中沒有返回值,語句格式為

return;

(5)?return語句可以出現(xiàn)多次,但是每次函數(shù)調用只能有一條return語句被執(zhí)行。例如下面的example函數(shù): 4.3函數(shù)調用

4.3.1函數(shù)的聲明

在C程序中,一個函數(shù)可以被調用需要以下兩個前提。

(1)函數(shù)已存在?;蛘吆瘮?shù)是系統(tǒng)函數(shù)(庫函數(shù)),或者函數(shù)是用戶已定義完的函數(shù)。

(2)對于庫函數(shù),只要在主調函數(shù)所在的文件用include命令包含相應的頭文件即可;對于用戶自定義的函數(shù),除下面將要提到的三種情況外都需要在調用函數(shù)前對其進行聲明,或者在主調函數(shù)所在文件用include命令包含被調用函數(shù)的所在文件。所謂函數(shù)定義,是指編寫不存在的函數(shù),函數(shù)只能定義一次。而函數(shù)聲明是對存在的準備調用的函數(shù)進行聲明,讓編譯系統(tǒng)可以在編譯階段對函數(shù)的調用進行合法性檢查,判斷形參與實參的類型及個數(shù)是否一致,函數(shù)聲明可以多次。

函數(shù)聲明格式就是照寫已定義的函數(shù)首部,再加上分號,即

類型標識符函數(shù)名(形式參數(shù)表列);輸入“1.5,1.2”時,結果如圖4.5所示。

C語言規(guī)定,在下列三種情況下,調用函數(shù)前可以不對被調用函數(shù)進行聲明:

(1)被調函數(shù)的返回值類型是整型或字符型。例如例4.1,被調用函數(shù)fac的返回值是整型,main函數(shù)可不必聲明它而直接調用。

(2)在函數(shù)的外部已對該函數(shù)聲明,且聲明在主調函數(shù)的前面。如例4.5。圖4.5例4.5的運行結果圖4.6例4.6的運行結果

(3)被調用函數(shù)的定義和調用函數(shù)在同一個文件內,且出現(xiàn)在調用函數(shù)之前。例如例4.3,函數(shù)product出現(xiàn)在函數(shù)main之前,則main函數(shù)可以不對product函數(shù)聲明而直接調用。

調用一個函數(shù)前進行函數(shù)聲明是一種良好的程序設計習慣,除了增加程序的正確性,把錯誤改正在初級階段外,還能提高程序的可讀性。

4.3.2函數(shù)的調用

函數(shù)的調用就是主調函數(shù)通過數(shù)據(jù)傳遞使用被調用函數(shù)功能的過程。數(shù)據(jù)傳遞是通過形參和實參完成的。

函數(shù)調用的一般形式是:

函數(shù)名(實際參數(shù)表列)說明:

(1)調用函數(shù)時的參數(shù)稱為實際參數(shù),簡稱實參。實參可以是變量、常量或表達式,是有確定值的參數(shù)。

(2)函數(shù)的形參與實參要求個數(shù)相等,并且對應的形參和實參的類型相同。若被調函數(shù)是無參函數(shù),則實參表列為空。

(3)數(shù)據(jù)傳遞是通過形參接收實參的數(shù)值來完成的。函數(shù)調用時,形參被分配內存單元,并接收對應實參傳來的值。

【例4.7】

將三個實數(shù)按由小到大順序輸出并且輸出它們的和。

程序如下:圖4.7例4.7運行結果例4.7的main函數(shù)執(zhí)行過程中依次調用了函數(shù)start_information、函數(shù)sort和函數(shù)end_information。start_information和end_information是無參數(shù)、無返回值函數(shù),被main調用時無需數(shù)據(jù)傳遞,執(zhí)行完畢返回main函數(shù)執(zhí)行即可。sort函數(shù)是既有參數(shù),也有函數(shù)返回值的函數(shù)。sort函數(shù)的調用過程是一個完整的函數(shù)調用過程,其調用過程具體如下:

(1)為函數(shù)的形參x1、x2、x3分配內存單元,計算各個實參表達式a+1、3.0、a的值為5.0、3.0、4.0,并一一對應地賦值給相應形參x1、x2、x3。

(2)進入sort函數(shù)體,執(zhí)行函數(shù)中的語句,實現(xiàn)函數(shù)的排序輸出功能。

(3)執(zhí)行到return語句時,計算return語句中表達式x3+x2+x1的值并向主調函數(shù)返回其值,釋放形參及sort函數(shù)內的變量所占內存,返回main函數(shù)繼續(xù)執(zhí)行。

函數(shù)調用可以有不同的方式,例如例4.8。圖4.8例4.8的運行結果在例4.8中出現(xiàn)了三種函數(shù)調用方式,也就是一般函數(shù)的三種調用方式:

(1)具有返回值的函數(shù)可參加表達式的計算。例如例4.8的語句“t=max(x,y)+10;”中的max函數(shù)。

(2)具有返回值的函數(shù)可作為其他函數(shù)的實參。例如例4.8的語句“printf("\nthemaximumis:%f",max(t,z));”中,max函數(shù)作為printf函數(shù)中的一個參數(shù);

(3)只完成一定功能而沒有返回值的函數(shù)可單獨成為一個語句,例如例4.8的語句:

end_information();

程序說明:若是按自左向右順序求值的系統(tǒng),輸出結果應該是:44。所以該編譯系統(tǒng)是按自右向左順序求值的。圖4.9例4.9的運行結果4.3.3函數(shù)調用的數(shù)據(jù)傳遞方式

C語言中,函數(shù)的實參和形參之間的數(shù)據(jù)傳遞是單方向的值傳遞方式。只能將實參的值傳遞給形參,而不能將形參的值傳遞給實參。形參值的變化不影響實參。

當調用函數(shù)時,給形參分配內存單元,將實參的值賦給形式參數(shù)。函數(shù)執(zhí)行完后,形參占用的空間被釋放,實參仍為調用前的值。

【例4.10】

形參值的變化不影響實際參數(shù)的值。

程序如下:

程序說明:main函數(shù)調用函數(shù)change時,系統(tǒng)給形參x、y分配空間,將實參a的值賦給形參x,實參b的值賦給形參y。執(zhí)行change函數(shù)時,x、y重新被賦值。change函數(shù)執(zhí)行完x、y占用的空間被釋放。形參x、y的變化影響不到實參a、b,因此main函數(shù)內輸出為“a=3,b=4”。圖4.10例4.10的運行結果

4.4函數(shù)的嵌套調用

4.4.1函數(shù)的嵌套調用

C語言中,函數(shù)不允許嵌套定義,但可以嵌套調用,即在調用一個函數(shù)的過程中,被調用函數(shù)調用另一個函數(shù)。

【例4.11】

求兩個整數(shù)的最小公倍數(shù)。

程序如下:圖4.11例4.11的運行結果例4.11的程序運行過程如圖4.12所示。從main函數(shù)開始執(zhí)行,輸入兩個整數(shù)后調用multiple函數(shù),multiple函數(shù)用調用了divisor函數(shù)。divisor函數(shù)執(zhí)行完返回multiple函數(shù)執(zhí)行,multiple函數(shù)執(zhí)行完返回main函數(shù)執(zhí)行。main函數(shù)執(zhí)行完,程序執(zhí)行結束。圖4.12嵌套調用圖4.13例4.12的運行結果4.4.2函數(shù)的遞歸調用

函數(shù)可以直接或間接地調用自身,這種調用方式稱為函數(shù)的遞歸調用。例如,例4.13和例4.14都屬于函數(shù)的遞歸調用,例4.13直接調用自身,例4.14是間接的調用自身。

注意:雖然遞歸是直接或間接的調用自身,但和調用其他函數(shù)一樣每次被調用都需要重新開辟空間,并不共用同一內存空間。因此調用自身和調用其他函數(shù)的調用過程沒有

區(qū)別。例4.13和例4.14的遞歸調用是無休止的自身調用。顯然無休止的調用是不合理的,也是不允許的。合理的遞歸調用應是有限的,是滿足一定條件能停止的遞歸調用。例4.15就是一個合理的遞歸調用。

【例4.15】

求n!的遞歸程序。

程序如下:圖4.14例4.15的運行結果如圖4.15所示,例4.15在輸入3時的遞歸調用過程為:從main函數(shù)調用fac函數(shù)求3!開始,變成fac函數(shù)調用fac函數(shù)求2!,再變成fac函數(shù)調用fac函數(shù)求1!。然后再返回1!的值,得到2!,返回2!的值,得到3!,返回main函數(shù)輸出。圖4.15遞歸調用由例4.15看出,函數(shù)遞歸調用的過程可分為遞歸過程和回溯過程兩個階段。

(1)遞歸過程:將原始問題不斷轉化為規(guī)模更小且處理方式相同的新問題。

(2)回溯過程:從已知條件出發(fā),沿遞歸的逆過程逐一求值返回,直至遞歸初始處,則完成遞歸調用。

通過fac函數(shù)執(zhí)行過程的分析可以看出遞歸算法解決問題的方式:將初始問題轉化為解決方法相同的新問題,而新問題的規(guī)模要比原始問題小;新問題又可以轉化為規(guī)模更小的問題;這樣處理問題直至最終歸結到可以簡單解決的問題——遞歸的終結條件。遞歸調用會占用大量內存和時間,使得執(zhí)行效率低。但采用遞歸方法編寫的程序簡潔、可讀性好。其優(yōu)點使遞歸方法成為解決某些問題的最佳方法,例如漢諾塔問題。

【例4.16】

漢諾塔問題:古代有一座梵塔,塔內有a、b、c三個底座,上面可放盤子。初始a座上有n個盤子,這些盤子大小各不相同,大盤在下,小盤在上,依次排列。要求將a座上n個盤子移至c座上,每次只能移動一個,但要求移動過程中保持3個座上始終小盤子在上,大盤子在下。移動過程中可以借助b座實現(xiàn)移動。編寫程序求出盤子的移動步驟。

問題分析:這個問題可用遞歸思想分析,將n個盤子由a座移動到c座可分為如下三個過程:

(1)先將a座上n-1個盤子借助c座移至b座;

(2)再將a座上最下面一個盤子移至c座;

(3)最后將b座上n-1個盤子借助a座移至c座。

這樣就把移動n個盤子的問題轉化為移動n-1個盤子的問題。按這種思路,再將移動n-1個盤子的問題轉化為移動n-2個盤子的問題,直至移動一個盤子。程序如下:

圖4.16例4.16的運行結果

4.5變量的作用域

編寫程序時,除了要了解變量占用內存大小和運算規(guī)則外,還需要知道變量的作用域和存儲類型。

變量只能在它的作用范圍內使用,即變量在它的作用域之外不能被引用。變量的作用域直接與變量定義的位置相關。在函數(shù)內部(或復合語句內部)定義的變量稱為內部變量。內部變量的作用域是定義它的函數(shù)(或復合語句)。在函數(shù)外任意位置定義的變量稱為外部變量。外部變量的作用域是從定義或聲明的位置開始,直至它所在源程序文件的結束。

【例4.17】

注意變量的作用域。例4.17中main函數(shù)的內部變量x、y和函數(shù)f1的內部變量x、y雖然同名,卻是完全不相關的變量。因為它們的作用域完全不同,是不同的變量,不產生沖突。如圖4.17所示。

作用域不同的同名變量有時會出現(xiàn)作用域的部分重疊,這時系統(tǒng)通常都選擇作用域范圍小的變量有效。例如例4.18函數(shù)f1的內部變量a、b和全局變量a、b重疊,但是執(zhí)行f1時,有效的是內部變量a、b。圖4.17相關變量的作用域圖4.18例4.18的運行結果內部變量有助于實現(xiàn)信息隱蔽,即使不同的函數(shù)定義了同名的內部變量,也不會相互影響。而外部變量的使用增加了函數(shù)之間傳遞數(shù)據(jù)的途徑。如果一個函數(shù)需要返回兩個或兩個以上的計算結果時,可以使用外部變量傳遞數(shù)據(jù)。例如,例4.19使用外部變量將函數(shù)f1計算的四個結果傳送到了main函數(shù)中。

【例4.19】

求兩個數(shù)的和、差、積、商。

程序如下:輸入“8811”時,程序的運行結果如圖4.19所示。

外部變量的使用會降低函數(shù)的通用性。過多使用外部變量,會使函數(shù)之間的依賴性增加,耦合性增高。這種情況不利于程序的結構化設計方式。因此,除非真正需要,建議避免使用外部變量。圖4.19例4.19的運行結果

4.6變量的存儲類別

根據(jù)變量在程序運行期間是否需占用固定的存儲單元,變量的存儲類別可分為以下兩類。

(1)動態(tài)存儲:程序運行期間不需要長期占用內存單元。動態(tài)存儲的變量有auto(自動)類型和register(寄存器)類型。

(2)靜態(tài)存儲:靜態(tài)存儲的變量在編譯時被分配空間,在整個程序運行期間一直占用固定的內存空間,程序運行結束才釋放內存空間??梢杂胹tatic、extern定義和聲明靜態(tài)存儲類別的變量。

C程序運行時占用的內存空間通常分為程序區(qū)、靜態(tài)存儲區(qū)和動態(tài)存儲區(qū)三部分。動態(tài)存儲類別的變量可存放在兩個地方——動態(tài)存儲區(qū)和寄存器。靜態(tài)存儲類別的變量只能存放于靜態(tài)存儲區(qū)中。

定義變量時需要說明存儲類別。因此,完整的變量定義形式應為

存儲類別數(shù)據(jù)類型變量列表;4.6.1內部變量的存儲類別

內部變量可存放于內存的動態(tài)存儲區(qū)、靜態(tài)存儲區(qū)和寄存器。但無論內部變量存放在何處,它的作用域是不變的。

1.auto(自動)變量

C系統(tǒng)默認內部變量的存儲類型是auto類型。例如,函數(shù)內部的語句“inta;”和語句“autointa;”是完全等價的。

自動變量在其定義所在的函數(shù)(或復合語句)開始執(zhí)行時才分得內存空間,在該函數(shù)(或復合語句)執(zhí)行期間占用內存空間。在函數(shù)(或復合語句)執(zhí)行結束時自動變量占用的空間被系統(tǒng)收回。

例4.20中的函數(shù)f1被調用時,系統(tǒng)在動態(tài)存儲區(qū)內分配空間給auto變量a、b。當f1結束時,系統(tǒng)回收變量a、b所占內存空間。圖4.20例4.20的運行結果

2.register(寄存器)變量

register變量和auto變量不同之處在于register變量被存放在寄存器中,因此比auto變量存取速度快得多。通常將頻繁使用的變量放在寄存器中,以提高程序的執(zhí)行速度。例如循環(huán)體內涉及的內部變量可定義為register變量。

計算機中寄存器的數(shù)量是有限的,而且寄存器的數(shù)據(jù)長度也是有限的。因此register變量不能定義太多,也不能是數(shù)據(jù)類型太大的變量(如數(shù)組、結構體等類型的變量)。

現(xiàn)今register變量定義通常是不必要的。優(yōu)化的編譯系統(tǒng)能夠識別使用頻繁的變量,并將其放到寄存器之中。

3.static(靜態(tài))變量

static變量存放在內存中的靜態(tài)存儲區(qū)。static內部變量在整個程序運行期間占用固定的內存單元。即使static內部變量所在的函數(shù)執(zhí)行結束后,static內部變量也不釋放存儲單元。因而再次調用static內部變量所在函數(shù)時,static內部變量的值為上次調用結束時的值。

系統(tǒng)在編譯時為static變量分配空間并賦初值,對于

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論