在結構化程序設計中函數(shù)是將任務進行模塊劃分的基本單位PPT學習教案
《在結構化程序設計中函數(shù)是將任務進行模塊劃分的基本單位PPT學習教案》由會員分享,可在線閱讀,更多相關《在結構化程序設計中函數(shù)是將任務進行模塊劃分的基本單位PPT學習教案(109頁珍藏版)》請在裝配圖網(wǎng)上搜索。
1、會計學1 練習:編寫程序,輸入x,根據(jù)下面y和x的關系,計算y值并輸出3x-11 (x10)x (x1)2x-1 (1xx; if(x1) y=x; else if(1=x10) y=2*x-1; else y=3*x-11; coutx; if(x1) y=x; else if(1=x&x10) y=2*x-1; else y=3*x-11; coutx; if(x1) y=x; else if(1x10) y=2*x-1; else y=3*x-11; coutx; x=10?y=3x-11:y=2x-1 coutx; if(x1) y=x; else if(x10) y=2*x-1; e
2、lse y=3*x-11; couty;第4頁/共109頁3.1 函數(shù)的定義與調用 3. 5 作用域與標識符的可見性 3.4 函數(shù)調用機制 3.3 全局變量和局部變量 3.2 函數(shù)的參數(shù)傳遞,返回值及函數(shù)聲明 3.10 編譯預處理 3.9 頭文件與多文件結構 3.6 存儲類型與標識符的生命期 3.8 函數(shù)的一些高級議題 3.7 函數(shù)的遞歸調用 第5頁/共109頁3.1.1 函數(shù)概述3.1.2 函數(shù)的定義3.1.3 函數(shù)的調用 第6頁/共109頁函數(shù)是C+程序的基本組成模塊。通過函數(shù),可以把一個復雜任務分解成為若干個易于解決的小任務。充分體現(xiàn)逐步細化的設計思想。組成C+程序的若干函數(shù)中,有一個稱
3、為main()(Winmain())函數(shù),是程序執(zhí)行的入口,它可以調用其他函數(shù),但不可以被調用。而其他一般函數(shù)既可以調用也可以被調用。函數(shù)概念的引入:入口函數(shù):第7頁/共109頁main ( )fun2( )fun1( )fun3( )funa( )funb( )func( )圖3.1 函數(shù)調用層次關系第8頁/共109頁3.1.1結束庫函數(shù)和自定義函數(shù): 庫函數(shù)或標準函數(shù),是由編譯系統(tǒng)預定義的,如一些常用的數(shù)學計算函數(shù)、字符串處理函數(shù)、圖形處理函數(shù)、標準輸入輸出函數(shù)等。 庫函數(shù)都按功能分類,集中說明在不同的頭文件中。用戶只需在自己的程序中包含某個頭文件,就可直接使用該文件中定義的函數(shù)。 用戶根
4、據(jù)需要將某個具有相對獨立功能的程序定義為函數(shù),稱自定義函數(shù)。四個要素:返回值類型,函數(shù)名,參數(shù)列表和函數(shù)體第9頁/共109頁無參函數(shù)定義格式為:數(shù)據(jù)類型函數(shù)名(void)函數(shù)體說明: 數(shù)據(jù)類型指函數(shù)返回值類型,可以是任一種數(shù)據(jù)類型。沒有返回值應將返回值類型定義為void。 函數(shù)名采用合法標識符表示。 對無參函數(shù),參數(shù)括號中的void通常省略,但括號不能省略。 函數(shù)體由一系列語句組成。函數(shù)體可以為空,稱為空函數(shù)。 第10頁/共109頁例: 打印一個表頭void TableHead ( ) cout*endl;cout* example *endl;cout*=b?a:b; return(x);
5、有參函數(shù)的參數(shù)表中列出所有形式參數(shù)的類型和參數(shù)名稱。各參數(shù)即使類型相同也必須分別加以說明。 形式參數(shù)簡稱形參,只能是變量名,不允許是常量或表達式。 Why?第12頁/共109頁int f()string s;.return s;f2(int i).int f(int v1,int v2).double square(double x)return x*x;第13頁/共109頁問題:定義函數(shù)時究竟哪些變量應當作為函數(shù)的參數(shù)?哪些應當定義在函數(shù)體內(nèi)?原則:函數(shù)在使用時被看成 “黑匣子”,除了輸入輸出外,其他部分可不必關心。從函數(shù)的定義看出,函數(shù)頭正是用來反映函數(shù)的功能和使用接口,它所定義的是“做什
6、么”。即明確了“黑匣子”的輸入輸出部分,輸出就是函數(shù)的返回值,輸入就是參數(shù)。因此,只有那些功能上起自變量作用的變量才必須作為參數(shù)定義在參數(shù)表中;函數(shù)體中具體描述“如何做”,因此除參數(shù)之外的為實現(xiàn)算法所需用的變量應當定義在函數(shù)體內(nèi)。 C+中不允許函數(shù)的嵌套定義,即在一個函數(shù)中定義另一個函數(shù)。第14頁/共109頁函數(shù)調用: 所謂函數(shù)調用,就是使程序轉去執(zhí)行函數(shù)體。 在C+中,除了主函數(shù)外,其他任何函數(shù)都不能單獨作為程序運行。任何函數(shù)功能的實現(xiàn)都是通過被主函數(shù)直接或間接調用進行的。 無參函數(shù)的調用格式: 函數(shù)名( ) 有參函數(shù)的調用格式: 函數(shù)名(實際參數(shù)表)其中實際參數(shù)簡稱實參,用來將實際參數(shù)的值
7、傳遞給形參,因此可以是常量、具有值的變量或表達式?!纠?.1】 輸入兩個實數(shù),輸出其中較大的數(shù)第15頁/共109頁 函數(shù)的調用規(guī)則1、調用函數(shù)時,函數(shù)名必須與調用處的函數(shù)名完全一致。2、實參的個數(shù)必須與形參的個數(shù)一致。3、函數(shù)必須先聲明或定義,后調用。4、函數(shù)可以直接或間接地自己調用自己,稱為遞歸調用。int main() int add(int x, int y); int a=100,b=200,c ; c =add(a,b); .int add (int x, int y ) int z ; z=x+y; return(z);錯誤:c=ad(a,b);c=add(a);int add(i
8、nt , int );第16頁/共109頁 321 函數(shù)的參數(shù)傳遞及傳值調用 323 函數(shù)聲明322 函數(shù)返回值 第17頁/共109頁參數(shù)傳遞: 函數(shù)調用首先要進行參數(shù)傳遞,參數(shù)傳遞的方向是由實參傳遞給形參。 傳遞過程是,先計算實參表達式的值,再將該值傳遞給對應的形參變量。一般情況下,實參和形參的個數(shù)和排列順序應一一對應,并且對應參數(shù)應類型匹配(賦值兼容),即實參的類型可以轉化為形參類型。而對應參數(shù)的參數(shù)名則不要求相同。傳值調用和引用調用:按照參數(shù)形式的不同,C+有兩種調用方式:傳值調用和引用調用。傳值調用傳遞的是實參的值,本章介紹傳值調用。第18頁/共109頁在調用函數(shù)時,一般在主調函數(shù)和被
9、調用函數(shù)之間有 信息傳遞 這是由函數(shù)中的參數(shù)來完成的。調用函數(shù)和被調用函數(shù)之間的參數(shù)傳遞實際參數(shù) 形式參數(shù)主調用函數(shù)中的參數(shù)被調用函數(shù)中的參數(shù)(實參)(形參)int main() int a=5,b=10, c ; c=max(a,b); printf(“c=%dn”, c); return 0;int max(int x, int y) int t; if (xy) t=x; else t=y; return(t); 第19頁/共109頁yxa5b10510ct101010int main() int a=5,b=10, c ; c=max(a,b); printf(“c=%dn”, c);
10、 return 0; int max(int x, int y) int t; if (xy) t=x; else t=y; return(t); 信息傳遞原則:實參到形參單向值傳遞特點:實參與形參各占用不同的內(nèi)存單元第20頁/共109頁傳值調用:將實參的值復制給形參,在函數(shù)中參加運算的是形參,而實參不會發(fā)生任何改變。傳值調用起了一種隔離作用?!纠?.2】 實參和形參對應關系的示例。注意:【例1.3】中調用函數(shù)strcpy(s3, s2),卻實現(xiàn)了字符數(shù)組s2的內(nèi)容復制到字符數(shù)組s3中。這是因為數(shù)組名實際上代表存儲數(shù)組的內(nèi)存的首地址,復制給形參的是實參數(shù)組的首地址,結果參加運算的是實參數(shù)組。數(shù)
11、組作為參數(shù),定義時形參用數(shù)組名加一對方括號,調用時實參只用數(shù)組名 第21頁/共109頁100aFFC2200bFFC4int add (int x, int y) int z ; z=(+x)+(+y) ; return(z); int main() int a=100,b=200,c ; c =add(a,b); coutcendl; return 0; 100 xFFA2200yFFA4101201302z1094302cFFC6第22頁/共109頁 當形參值在函 數(shù)中發(fā)生變化時, 且不影響調用它的 實參值的變化。 用途 采用這種數(shù)據(jù)復制的參數(shù)傳遞方式,每次每個參數(shù)只能傳遞一個數(shù)據(jù)。缺點a
12、dd (a , b) ;int add ( x, y )第23頁/共109頁 A) 11 B) 20 C) 21 D) 31請寫出下列程序的運行結果 main() int x=6,y=7,z=8,r ; r=f (x-,y+,x+y),z-); coutr=ry) t=x; else t=y; return(t); 第29頁/共109頁 下面是一個使用結構化程序設計思想開發(fā)的企業(yè)管理報表程序的框架。它使用了函數(shù)聲明。void menu_print();void account_report();void engineering_report();void marketing_report();
13、int main() int choice; do menu_print();cinchoice; while(choice=4); switch(choice) case 1: account_report(); break; case 2: engineering_report(); break; case 3: marketing_report(); break; return 0;第30頁/共109頁void menu_print() cout”系統(tǒng)功能:”endl; cout”1財務報表”endl; cout”2工程報表”endl; cout”3市場報表”endl; cout”選擇業(yè)
14、務序號:”; void account_report() /生成財務報表void engineering_report() /生成工程報表 void marketing_report() /生成市場報表;第31頁/共109頁【例3.4】 輸出所有滿足下列條件的正整數(shù)m:10m1000且m、m2、m3均為回文數(shù)。分析:回文指左右對稱的序列。如121、353等就是回文數(shù)。判斷整數(shù)是否回文數(shù)用函數(shù)實現(xiàn),其思想是將該數(shù)各位拆開后反向組成新的整數(shù),如果該整數(shù)與原數(shù)相等則為回文數(shù)。m m*m m*m*m11 121 1331101 10201 1030301111 12321 1367631 運行結果:第
15、32頁/共109頁 第33頁/共109頁自由存儲區(qū) (動態(tài)數(shù)據(jù))棧區(qū)(函數(shù)局部數(shù)據(jù))(main()函數(shù)局部數(shù)據(jù))全局數(shù)據(jù)區(qū)(全局、靜態(tài))代碼區(qū)(程序代碼) 操作系統(tǒng)為一個C+程序的運行所分配的內(nèi)存分為四個區(qū)域,如圖3.3 所示:第34頁/共109頁存儲區(qū)域說明:(1)代碼區(qū)(Code area):存放程序代碼,即程序中各個函數(shù)的代碼塊;(2)全局數(shù)據(jù)區(qū)(Data area):存放全局數(shù)據(jù)和靜態(tài)數(shù)據(jù);分配該區(qū)時內(nèi)存全部清零,結果變量的所有字節(jié)自動初始化為零。(3)棧區(qū)(Stack area):存放局部變量,如函數(shù)中的變量等;分配棧區(qū)時不處理內(nèi)存,即變量取隨機值。(4)自由存儲區(qū)(Free sto
16、re area):存放與指針相關的動態(tài)數(shù)據(jù)。分配自由存儲區(qū)時不處理內(nèi)存。參見第七章。第35頁/共109頁在所有函數(shù)之外定義的變量稱為全局變量。全局變量在編譯時建立在全局數(shù)據(jù)區(qū),在未給出初始化值時系統(tǒng)自動初始化為全0。全局變量可定義在程序開頭,也可定義在中間位置,該全局變量在定義處之后的任何位置都是可以訪問的,稱為可見的?!纠?.5】 多個函數(shù)使用全局變量的例子。全局變量引入:第36頁/共109頁定義在函數(shù)內(nèi)或塊內(nèi)的變量稱為局部變量。程序中使用的絕大多數(shù)變量都是局部變量。局部變量在程序運行到它所在的塊時建立在棧中,該塊執(zhí)行完畢局部變量占有的空間即被釋放。局部變量在定義時可加修飾詞auto,但通常
17、省略。局部變量在定義時若未初始化,其值為隨機數(shù)。局部變量引入:【例3.6】 使用局部變量的例子。思考:如果定義一個對象/變量為全局模式還是局部模式?第37頁/共109頁 1、主函數(shù)中定義的變量也只用在主函數(shù)中有效;關于局部變量使用的幾點說明 2、不同函數(shù)中可以使用相同的變量名,且它們代 表不同的存儲單元,互不干擾; 3、形式參數(shù)也是局部變量。其它函數(shù)是不能調用 該形參的; 4、在一個函數(shù)內(nèi)部,可以在復合語句中定義變量 ,這些變量只能在本復合語句中有效。第38頁/共109頁局部變量占用的內(nèi)存是在程序執(zhí)行過程中“動態(tài)”地建立和釋放的。這種“動態(tài)”是通過棧由系統(tǒng)自動管理進行的。(1)建立??臻g;(6
18、)恢復現(xiàn)場:取主調函數(shù)運行狀態(tài)及返回地址,釋放棧空間;(7)繼續(xù)主調函數(shù)后續(xù)語句。(5)釋放被調函數(shù)中局部變量占用的棧空間;(4)執(zhí)行被調函數(shù)函數(shù)體;(3)為被調函數(shù)中的局部變量分配空間,完成參數(shù)傳遞;(2)保護現(xiàn)場:主調函數(shù)運行狀態(tài)和返回地址入棧;調用過程:第39頁/共109頁void fun1(int, int);void fun2(float);int main() int x=1;y=2; fun1(x, y); return 0;void fun1(int a,int b) float x=3; fun2(x);void fun2(float y) int x; x棧頂棧頂棧底棧底y
19、3fun2() fun1()運行狀態(tài)及返回地址運行狀態(tài)及返回地址x3b2a1fun1() main()運行狀態(tài)及返回地址運行狀態(tài)及返回地址y2x1main() 操作系統(tǒng)運行狀態(tài)及返回地址操作系統(tǒng)運行狀態(tài)及返回地址此圖例說明在程序執(zhí)行過程中怎樣通過?!皠討B(tài)”地建立和釋放局部變量占用的內(nèi)存的地址地址.0XFE8020X5984D0XFE154第40頁/共109頁3 文件作用域 2 函數(shù)聲明作用域 作用域:指標識符能夠被使用的范圍。只有在作用域內(nèi)標識符才可以被訪問(稱為可見)。本節(jié)重點討論局部域和文件域(全局域),其中局部域包括塊域和函數(shù)聲明域。任何標識符作用域的起始點均為標識符說明處。下面分別介紹
20、:1 塊作用域 第41頁/共109頁 函數(shù)中定義的標識符,包括形參和函數(shù)體中定義的局部變量,作用域都在該函數(shù)內(nèi),也稱作函數(shù)域。塊指一對大括號括起來的程序段。塊中定義的標識符,作用域在塊內(nèi)。復合語句是一個塊。函數(shù)也是一個塊。復合語句中定義的標識符,作用域僅在該復合語句中?!纠?.7】 輸入兩數(shù),按從大到小的順序保存。塊的引入:第42頁/共109頁由VC+平臺運行,結果如下:輸入兩整數(shù):3 5調用前:實參a=3,b=5調用中交換前:形參a=3,b=5交換后:形參a=5,b=3調用后:實參a=3,b=5 交換失敗局部變量具有局部作用域使得程序在不同塊中可以使用同名變量。這些同名變量各自在自己的作用域
21、中可見,在其它地方不可見。【例3.8】設計函數(shù)完成兩數(shù)交換,用主函數(shù)進行測試。第43頁/共109頁 對于塊中嵌套其它塊的情況,如果嵌套塊中有同名局部變量,服從局部優(yōu)先原則,即在內(nèi)層塊中屏蔽外層塊中的同名變量,換句話說,內(nèi)層塊中局部變量的作用域為內(nèi)層塊;外層塊中局部變量的作用域為外層除去包含同名變量的內(nèi)層塊部分。如果塊內(nèi)定義的局部變量與全局變量同名,塊內(nèi)仍然局部變量優(yōu)先,但與塊作用域不同的是,在塊內(nèi)可以通過域運算符“:”訪問同名的全局變量?!纠?.9】 顯示同名變量可見性。第44頁/共109頁 函數(shù)聲明不是定義函數(shù),在作函數(shù)聲明時,其中的形參作用域只在聲明中,即作用域結束于右括號。正是由于形參不
22、能被程序的其他地方引用,所以通常只要聲明形參個數(shù)和類型,形參名可省略。第45頁/共109頁文件作用域也稱全局作用域。定義在所有函數(shù)之外的標識符,具有文件作用域,作用域為從定義處到整個源文件結束。文件中定義的全局變量和函數(shù)都具有文件作用域。如果某個文件中說明了具有文件作用域的標識符,該文件又被另一個文件包含,則該標識符的作用域延伸到新的文件中。如cin和cout是在頭文件iostream中說明的具有文件作用域的標識符,它們的作用域也延伸到嵌入iostream的文件中。第46頁/共109頁存儲類型(storage class)決定標識符的存儲區(qū)域,即編譯系統(tǒng)在不同區(qū)域為不同存儲類型的標識符分配空間
23、。由于存儲區(qū)域不同,標識符的生命期也不同。所謂生命期,指的是標識符從獲得空間到空間釋放之間的期間,標識符只有在生存期中、并且在其自己的作用域中才能被訪問。 第47頁/共109頁自動變量為用auto說明的變量,通常auto缺省。局部變量都是自動變量,生命期開始于塊的執(zhí)行,結束于塊的結束,其原因是自動變量的空間分配在棧中,塊開始執(zhí)行時系統(tǒng)自動分配空間,塊執(zhí)行結束時系統(tǒng)自動釋放空間。故自動變量的生命期和作用域是一致的。為提高程序運行效率,可以將某些變量保存在寄存器中,即用register說明為寄存器變量,但不提倡使用。C+中關于存儲類型的說明符(storage class specifier)有四個
24、:auto、register、static和extern。其中用auto和register修飾的稱為自動存儲類型,用static修飾的稱為靜態(tài)存儲類型,用extern修飾的稱為外部存儲類型。1 自動存儲類型第48頁/共109頁static說明的變量稱為靜態(tài)變量。根據(jù)定義的位置不同,還分為局部靜態(tài)變量和全局靜態(tài)變量,也稱內(nèi)部靜態(tài)變量和外部靜態(tài)變量。靜態(tài)變量均存儲在全局數(shù)據(jù)區(qū),如果程序未顯式給出初始化值,系統(tǒng)自動初始化為全0,且初始化只進行一次;靜態(tài)變量占有的空間要到整個程序執(zhí)行結束才釋放,故靜態(tài)變量具有全局生命期。局部靜態(tài)變量是定義在塊中的靜態(tài)變量,當塊第一次被執(zhí)行時,編譯系統(tǒng)在全局數(shù)據(jù)區(qū)為其開
25、辟空間并保存數(shù)據(jù),該空間一直到整個程序結束才釋放。局部靜態(tài)變量具有局部作用域,但卻具有全局生命期?!纠?.10】 自動變量與局部靜態(tài)變量的區(qū)別第49頁/共109頁 int f( int a) auto int b=0; static int c=3; b=b+1;c=c+1; return(a+b+c); int main() int a=2, i ; for(i=0; i 3; i +) cout f(a)endl; 0b3c1舉例2a2a4701580691第50頁/共109頁 fun(int a, int b) static int m, i=2; i+=m+1; m=i+a+b; re
26、turn(m); int main() int k=4,m=1,p; p=fun(k,m); coutpendl; p=fun(k,m); coutpendl; 0m4k4a1m1b p2i388120178 17817第51頁/共109頁int main() fun(); fun(); void fun() static int a3=0,1,2; int i ; for(i =0; i 3; i +) ai +=ai ; for(i =0; i 3; i +) coutai ; coutendl; return; 0 12 a0 a1 a2024048第52頁/共109頁一個C+程序可以由
27、多個源程序文件組成。多文件程序系統(tǒng)可以通過外部存儲類型的變量和函數(shù)來共享某些數(shù)據(jù)和操作。在一個程序文件中定義的全局變量和函數(shù)缺省為外部的,即其作用域可以延伸到程序的其他文件中。其他文件如果要使用這個文件中定義的全局變量和函數(shù),應該在使用前用“extern”作外部聲明。外部聲明通常放在文件的開頭(函數(shù)總是省略extern)。外部變量聲明不同于全局變量定義,變量定義時編譯器為其分配存儲空間,而變量聲明則表示該全局變量已在其他地方定義過,編譯系統(tǒng)不再分配存儲空間。外部的全局變量或函數(shù)加上static修飾,就成為靜態(tài)全局變量或靜態(tài)函數(shù)。靜態(tài)的全局變量和函數(shù)作用域限制在本文件,其他文件即使使用外部聲明也
28、無法使用該全局變量或函數(shù)。 【例3.11】外部存儲類型的例子第53頁/共109頁全局變量的static:如果程序是由多個源文件組成時,此全局變量的作用域只限于本文件中。extern int x; int x;main() a1.cppstatic char cc; extern int x; a2.cpp extern char cc; a3.cpp第54頁/共109頁1. 靜態(tài)生命期 靜態(tài)生命期(Static extent或Static storage duration)指的是標識符從程序開始運行時就存在,具有存儲空間,到程序運行結束時消亡,釋放存儲空間。具有靜態(tài)生命期的標識符存放在全局數(shù)據(jù)
29、區(qū),如全局變量、靜態(tài)全局變量、靜態(tài)局部變量。具有靜態(tài)生命期的標識符在未被用戶初始化的情況下,系統(tǒng)會自動將其初始化為0。 函數(shù)駐留在代碼區(qū),也具有靜態(tài)生命期。所有具有文件作用域的標識符都具有靜態(tài)生命期。第55頁/共109頁2. 局部生命期 在函數(shù)內(nèi)部或塊中定義的標識符具有局部生命期(Automatic extent或Automatic storage duration),其生命期開始于執(zhí)行到該函數(shù)或塊的標識符定義處,結束于該函數(shù)或塊的結束處。具有局部生命期的標識符存放在棧區(qū)。具有局部生命期的標識符如果未被初始化,其內(nèi)容是隨機的,不可引用。 具有局部生命期的標識符必定具有局部作用域;但反之不然,靜
30、態(tài)局部變量具有局部作用域,但卻具有靜態(tài)生命期。第56頁/共109頁具有動態(tài)生命期(dynamic extent或dynamic storage duration)的標識符存放在自由存儲區(qū),由特定的函數(shù)調用或運算來創(chuàng)建和釋放,如用new運算符(或調用malloc()函數(shù))為變量分配存儲空間時,變量的生命期開始,而用delete運算符(或調用free()函數(shù))釋放空間或程序結束時,變量生命期結束。關于new運算符和delete運算符將在第七章中介紹。3. 動態(tài)生命期第57頁/共109頁1n 1)!-(n*n1n 1 0n 1 n! 遞歸是一種描述問題的方法,或稱算法。遞歸的思想可以簡單地描述為“自
31、己調用自己”。例如用如下方法定義階乘:可以看出是用階乘定義階乘,這種自己定義自己的方法稱為遞歸定義。遞歸的引入:第58頁/共109頁遞歸定義的階乘函數(shù):fac(int n)if (n=0|n=1) return 1;else return n*fac(n-1);只要設計主函數(shù)調用階乘函數(shù),即可實現(xiàn)計算階乘?!纠?.12】 求4!運行結果:4321126244!=24說明:cout”n4!=”fac(4)=0&ch=9?1:0;int main() char ch; while(cin.get(ch), ch!= n) if (IsNumber(ch) cout是數(shù)字字符 endl; else
32、cout不是數(shù)字字符 endl; return 0;因使用頻度很高,說明為內(nèi)聯(lián)函數(shù)。第71頁/共109頁3.9.1 頭文件標準庫頭文件:考慮標識符在其他文件中的可見性。使用頭文件是很有效的方法。如:#includeusing namespace std; 其中的iostream是在標準名字空間域std中定義的頭文件。對應的傳統(tǒng)方式的文件名為,頭文件以“.h”為后綴。 系統(tǒng)定義的頭文件中定義了一些常用的公用標識符和函數(shù),用戶只要將頭文件包含進自己的文件,就可使頭文件中定義的標識符在用戶文件中變得可見,也就可以直接使用頭文件中定義的標識符和函數(shù)。 第72頁/共109頁3.9.1 頭文件自定義頭文件
33、:除了系統(tǒng)定義的頭文件外,用戶還可以自定義頭文件。對于具有外部存儲類型的標識符,可以在其他任何一個源程序文件中經(jīng)聲明后引用,因此用戶完全可以將一些具有外部存儲類型的標識符的聲明放在一個頭文件中。具體地說,頭文件中可以包括:用戶構造的數(shù)據(jù)類型(如枚舉類型),外部變量,外部函數(shù)、常量和內(nèi)聯(lián)函數(shù)等具有一定通用性或常用的量,而一般性的變量和函數(shù)定義不宜放在頭文件中。第73頁/共109頁3.9.2 多文件結構 在開發(fā)較大程序時,通常將其分解為多個源程序文件,每個較小的程序用一個源程序文件建立。程序經(jīng)過建立、編譯、連接,成為一個完整的可執(zhí)行程序。多文件結構通過工程進行管理,在工程中建立若干用戶定義的頭文件
34、.h和源程序文件.cpp。頭文件中定義用戶自定義的數(shù)據(jù)類型,所有的程序實現(xiàn)則放在不同的源程序文件中。編譯時每個源程序文件單獨編譯,如果源程序文件中有編譯預處理指令,則首先經(jīng)過編譯預處理生成臨時文件存放在內(nèi)存,之后對臨時文件進行編譯生成目標文件.obj,編譯后臨時文件撤銷。所有的目標文件經(jīng)連接器連接最終生成一個完整的可執(zhí)行文件.exe。 圖3.11是一個多文件系統(tǒng)的開發(fā)過程。第74頁/共109頁3.9.2 多文件結構多文件結構編譯 預編譯編譯 預編譯 預編譯編譯圖3.11 C+程序開發(fā)過程file1.hfile1.cppfile2.hfile2.cppfilen.hfilen.cpp臨時文件1臨
35、時文件2臨時文件nfile1.objfile2.objfilen.objFilename.exe.libC+標準類庫連接運行第75頁/共109頁3.10.1 宏定義指令 3.10.2 文件包含指令 3.10.3 條件編譯指令 第76頁/共109頁1 不帶參宏定義用來產(chǎn)生與一個字符串對應的常量字符串,格式為:#define 宏名 常量串 預處理后文件中凡出現(xiàn)該字符串處均用其對應的常量串代替。替換過程稱為宏替換或宏展開。例如,如果使用指令#define PI 3.1415926則程序中可以使用標識符PI,編譯預處理后產(chǎn)生一個中間文件,文件中所有PI被替換為3.1415926。宏替換只是字符串和標識
36、符之間的簡單替換,預處理本身不做任何數(shù)據(jù)類型和合法性檢查,也不分配內(nèi)存單元。第77頁/共109頁2 帶參數(shù)的宏定義帶參宏定義的形式很象定義一個函數(shù),格式為:#define 宏名 ( 形參表 ) 表達式串 例如作如下宏定義:#define S(a,b) (a)*(b)/2程序中可使用S(a,b),預處理后產(chǎn)生中間文件,其中S(a,b)被替換成(a)*(b)/2。注意,宏定義時形參通常要用括號括起來,否則容易導致邏輯錯誤。例如,如果定義:#define S(a,b) a*b/2那么程序中的S(3+5,4+2)就會被宏展開為3+5*4+2/2,不符合定義的真正的意圖。帶參宏定義形式上象定義函數(shù),但它
37、與函數(shù)的本質不同,宏定義仍然只是產(chǎn)生字符串替代,不存在分配內(nèi)存和參數(shù)傳遞。 第78頁/共109頁文件包含用#include指令,預處理后將指令中指明的源程序文件嵌入到當前源程序文件的指令位置處。格式為:#include 或#include 文件名第一種方式稱為標準方式,預處理器將在include子目錄下搜索由文件名所指明的文件。這種方式適用于嵌入C+提供的頭文件,因為這些頭文件一般都存在C+系統(tǒng)目錄的include子目錄下。而第二種方式編譯器將首先在當前文件所在目錄下搜索,如果找不到再按標準方式搜索。這種方式適用于嵌入用戶自己建立的頭文件。第79頁/共109頁一個被包含的頭文件中還可以有#in
38、clude指令,即include指令可以嵌套,但是,如果同一個頭文件在同一個源程序文件中被重復包含,就會出現(xiàn)標識符重復定義的錯誤。例如:頭文件f2.h中包含了f1.h,如果文件f3.cpp中既包含f1.h,又包含f2.h,那么編譯將提示錯誤,原因是f1.h被包含了兩次,那么其中定義的標識符在f3.cpp中就被重復定義。避免重復包含可以用條件編譯指令。第80頁/共109頁1 用宏名作為編譯的條件格式為:#ifdef#else#endif2 表達式的值作為編譯條件格式為:#if #else#endif當希望在不同條件下編譯程序的不同部分。這種情況就要使用條件編譯指令。 其中程序段可以是程序也可以是
39、編譯預處理指令??梢酝ㄟ^在該指令前面安排宏定義來控制編譯不同的程序段。第81頁/共109頁例:在調試程序時常常要輸出調試信息,而調試完后不需要輸出這些信息,則可以把輸出調試信息的語句用條件編譯指令括起來。形式如下:#ifdef DEBUGcouta=atx=xendl;#endif在程序調試期間,在該條件編譯指令前增加宏定義:#define DEBUG調試好后,刪除DEBUG宏定義,將源程序重新編譯一次。條件編譯指令包括:#if、#else、#ifdef、#ifndef、#endif、#undef等。#ifndef與#ifdef作用一樣,只是選擇的條件相反。#undef指令用來取消#defin
40、e指令所定義的符號,這樣可以根據(jù)需要打開和關閉符號。第82頁/共109頁謝謝!第83頁/共109頁【例例3.1】main( )函數(shù)調用max(2.5,4.7 )函數(shù)max(2.5,4.7 )return 4.7 主程序后續(xù)語句【例3.1】 輸入兩個實數(shù),輸出其中較大的數(shù)。其中求兩個實數(shù)中的較大數(shù)用函數(shù)完成。程序如下:#include using namespace std;float max(float a,float b)return(a=b?a:b);int main()float x,y;cout輸入兩個實數(shù):xy;c o u t x 和 y 中 較 大 數(shù) 為max(x,y)endl;
41、return 0;形式參數(shù)實際參數(shù)第84頁/共109頁【例例3.2】調用power(4.6,3 )函數(shù)power(4.6,3 )return 97.336 主程序后續(xù)語句n= 3x= 4.6c= a【例3.2】 實參和形參對應關系的示例。float power(float x,int n) /求x的n次冪float p=1;while(n-) p*=x;return p; int main()int n=3;float x=4.6;char c=a;coutpower(x,n)=power(x,n)endl;coutpower(c,n)=power(c,n)endl;coutpower(n,x
42、)=power(n,x)endl;return 0;第85頁/共109頁【例例3.2】調用power(a,3 )函數(shù)power(97,3 )return 912673 主程序后續(xù)語句n= 3x= 4.6c= a【例32】 實參和形參對應關系。float power(float x,int n) /求x的n次冪float p=1;while(n-) p*=x;return p; int main()int n=3;float x=4.6;char c=a;coutpower(x,n)=power(x,n)endl;coutpower(c,n)=power(c,n)endl;coutpower(n
43、,x)=power(n,x)endl;return 0;第86頁/共109頁【例例3.2】調用power(3,4.6 )函數(shù)power(3,4)return 81 主程序后續(xù)語句n= 3x=4.6c= a【例32】 實參和形參對應關系。float power(float x,int n) /求x的n次冪float p=1;while(n-) p*=x;return p; int main()int n=3;float x=4.6;char c=a;coutpower (x,n)=power(x,n)endl;coutpower (c,n)=power(c,n)endl;coutpower (n
44、,x)=power(n,x)endl;return 0;第87頁/共109頁【例3.3】程序:float TriangleArea(float a, float b, float c) if (a+b=c)|(a+c=b)|(b+c=a) return -1; float s; s=(a+b+c)/2; /海倫公式 return sqrt(s*(s-a)*(s-b)*(s-c) ;int main() float a,b,c,area; cout輸入三角形三邊a,b,c:abc; area=TriangleArea(a,b,c); if(area=-1) cout(a,b, c )不能構成三角
45、形!endl; elsecout三角形(a,b,c )面積為:areaendl; return 0;第88頁/共109頁bool palindrome(int); /函數(shù)聲明int main() int m;coutsetw(10)msetw(20)m*m“setw(20)m*m*mendl;for(m=11;m1000;m+)if(palindrome(m)&palindrome(m*m) &palindrome(m*m*m)coutsetw(10)msetw(20)m*msetw(20)m*m*0);for(int j=0;ji;j+) n=n*10+digitj;return (n=m)
46、;【例例3.43.4】 輸出回文數(shù)輸出回文數(shù)第90頁/共109頁【例例3.5】打印200調用func( )函數(shù)func( )200*2=400打印400n=100n=100*2=200【例3.5】 多個函數(shù)使用全局變量的例子。int n=100;void func()n*=2; int main()n*=2;coutnendl;func();coutnendl; return 0;思考:C+為什么引入全局變量?第91頁/共109頁打印main()中的t=3.5調用fun( )函數(shù)fun( )打印fun()中的t=5 打印main()中的t=3.5t= 3.5t = 5【例3.6】 使用局部變量
47、的例子。void fun()auto int t=5;/ fun()中的局部變量,auto可省略coutfun()中的t=tendl;int main()float t=3.5;/main()函數(shù)中的局部變量coutmain()中的t=tendl;fun();coutmain()中的t=tendl;return 0;第92頁/共109頁【例3.7】 a= 3 b= 535a=3 b=5a=5 b=3【例3.7】 輸入兩數(shù),按從大到小的順序保存,并輸出結果。結果棧t = 3 int main() int a,b; /具有函數(shù)域 cout輸入兩整數(shù):ab; cout“a=atb=b=a)int t
48、; /具有塊域 t=a; a=b; b=t; /交換a,b的值 couta=atb=bendl; return 0;上述程序若在最后一個cout語句處增加:couttendl;則編譯時會提示錯誤,因為變量t的作用域只在if語句中,其它地方不可見。第93頁/共109頁【例3.8】設計函數(shù)完成兩數(shù)交換,用主函數(shù)進行測試。void swap(int,int);int main() int a,b; /a,b作用域為main() cout輸入兩整數(shù):ab; cout調用前:實參a=a, b=bendl; swap(a,b); /傳值 cout調用后:實參a=a,b=bendl; return 0;vo
49、id swap(int a,int b) /a,b作用域為swap() cout調用中endl; cout交換前:形參a=“ a,b=bendl; int t; t=a; a=b; b=t;/交換swap()中的a,b的值 cout交換后:形參a=a,b=bendl;第94頁/共109頁全局全局n= 100100 200 300內(nèi) i= 500內(nèi) j= 600內(nèi)n=500+600 =11001100 500 600100200+300=500500 500 200 300外部 i=200外部 j=300【例3.9】 顯示同名變量可見性。int n=100;#include int main()
50、 int i=200,j=300;cout ntitjendl; /內(nèi)部塊 int i=500,j=600,n; n=i+j; cout ntitj endl; /輸出局部變量n cout:nendl;/輸出全局變量n n=i+j;/修改全局變量cout ntitj endl;return 0;第95頁/共109頁【例3.10】 自動變量與局部靜態(tài)變量的區(qū)別 int st() static int t=100; /局部靜態(tài)變量 t+; return t;int at() int t=100; /自動變量 t+;return t;int main() int i; for(i=0;i5;i+)
51、coutat()t; coutendl; for(i=0;i5;i+) coutst()t; coutendl; return 0;i= 0t= 1001 2 3 4 5101101101101101第96頁/共109頁i= 0t=1001 21013 4 5102103104105【例3.10】 自動變量與局部靜態(tài)變量的區(qū)別 int st() static int t=100; /局部靜態(tài)變量 t+; return t;int at() int t=100; /自動變量 t+;return t;int main() int i; for(i=0;i5;i+) coutat()=t; cout
52、endl; for(i=0;i5;i+) coutst()t; coutendl; return 0;第97頁/共109頁【例3.11】外部存儲類型的例子。假定程序包含兩個源程序文件Ex4_11_1.cpp和Ex4_11_2.cpp,程序結構如下:/* Ex4_11_1.cpp ,由main()組成*/void fun2(); /外部函數(shù)聲明,等價于extern void fun2();int n; /全局變量定義int main() n=1; fun2(); / fun2()定義在文件Ex4_11_2.cpp中 coutn=nendl; return 0;/* Ex4_11_2.cpp,由f
53、un2()組成*/extern int n; /外部變量聲明,n定義在文件Ex4_11_1.cpp中void fun2() /fun2()被文件Ex4_11_1.cpp中的函數(shù)調用n=3; 運行結果:n=3第98頁/共109頁【例3.12】 求4!#include int fac(int n)int y; coutnt;if(n=0|n=1) y=1; else y=n*fac(n-1);coutyt;return y;int main()coutn4!=fac(4)endl;return o; n=4cout4;y=4*fac(3);fac(4)=cout2;y=2*fac(1); n=2c
54、out1;y=1;cout1;return 1; n=1 n=3cout3;y=3*fac(2);cout24;return 24;cout6;return 6;cout2;return 2;24第99頁/共109頁【例3.13】 漢諾塔問題。有A、B、C三根柱子,A柱上有n個大小不等的盤子,大盤在下,小盤在上。要求將所有盤子由A柱搬動到C柱上,每次只能搬動一個盤子,搬動過程中可以借助任何一根柱子,但必須滿足大盤在下,小盤在上。打印出搬動的步驟。 A柱B柱C柱第100頁/共109頁分析:1 A柱只有一個盤子的情況: A柱C柱;2 A柱有兩個盤子的情況:小盤A柱B柱,大盤A柱C柱,小盤B柱C柱。
55、3 A柱有n個盤子的情況:將此問題看成上面n-1個盤子和最下面第n個盤子的情況。n-1個盤子A柱B柱,第n個盤子A柱C柱,n-1個盤子B柱C柱。問題轉化成搬動n-1個盤子的問題,同樣,將n-1個盤子看成上面n-2個盤子和下面第n-1個盤子的情況,進一步轉化為搬動n-2個盤子的問題,類推下去,一直到最后成為搬動一個盤子的問題。這是一個典型的遞歸問題,遞歸結束于只搬動一個盤子。A柱B柱C柱第101頁/共109頁算法:1 n-1個盤子A柱B柱,借助于C柱;2 第n個盤子A柱C柱;3 n-1個盤子B柱C柱,借助于A柱;其中步驟1和步驟3繼續(xù)遞歸下去,直至搬動一個盤子為止。由此,可以定義兩個函數(shù),一個是
56、遞歸函數(shù),命名為hanoi(int n, char source, char temp, char target),實現(xiàn)將n個盤子從源柱source借助中間柱temp搬到目標柱target;另一個命名為move(char source, char target),用來輸出搬動一個盤子的提示信息。第102頁/共109頁void move(char source,char target) coutsourcetargetendl;void hanoi(int n,char source,char temp,char target) if(n=1) move(source,target); else
57、hanoi(n-1,source,target,temp); /將n-1個盤子搬到中間柱 move(source,target); /將最后一個盤子搬到目標柱hanoi(n-1,temp,source,target); /將n-1個盤子搬到目標柱 int main()int n;cout輸入盤子數(shù):n;hanoi(n,A,B,C);return 0;第103頁/共109頁【例3.14】 輸入一個整數(shù),用遞歸算法將整數(shù)倒序輸出。分析:在遞歸過程的遞推步驟中用求余運算將整數(shù)的各個位分離,并打印出來。void backward(int n)coutn%10;if(n10) return; else
58、backward(n/10);void main()int n;cout輸入整數(shù):n;cout原整數(shù):nendl反向數(shù):;backward(n);coutendl;return 0;第104頁/共109頁n=247cout7;backward(24); n=2cout2;return;n=24cout4;backward(2);backward(247) return; return; coutendl; 求余總是取當前整數(shù)的最右一位,所以先輸出余數(shù)后遞歸可實現(xiàn)倒序輸出。如果先遞歸后輸出余數(shù),則是在回歸的過程中輸出,實現(xiàn)的就是正序輸出。第105頁/共109頁【例3.15】采用遞推法求解Fibo
59、nacii數(shù)列,本例的遞歸調用過程參見圖3.10。int fib(int n)if(n=0) return 0;else if(n=1) return 1;else return fib(n-1)+fib(n-2);int main()int i;for(i=0;i=19;i+) /將19改為69,可以看出計算到后面越來越緩慢。if(i%5=0) coutendl;coutsetw(6)fib(i);coutendl; return 0;第106頁/共109頁【例例3.16】3+5=調用sum(3,5 )函數(shù)sum(3,5 )return 8 2.2+5.6=調用sum(2.2,5.6 )函數(shù)
60、double sum(2.2,5.6 )return 7.8 3.5+4+8=調用sum(3.5, 4, 8 )函數(shù)float sum(3.5, 4.0, 8.0 )return 15.5 結束87.815.5【例3.16】 重載函數(shù)的應用。int sum(int a,int b) return a+b;Double sum(double a,double b)return a+b;float sum(float a,float b,float c)return a+b+c;int main()cout3+5=sum(3,5) endl;cout2.2+5.6=“ sum(2.2,5.6)endl;cout3.5+4+8=“ sum(3.5,4,8)0; loops-); int main()delay(3);cout“延時3個時間單位endl;delay();/等同于delay(5)cout“延時5個時間單位endl; return 0;【例例3.163.16】123延時3個時間單位12345延時5個時間單位第108頁/共109頁
- 溫馨提示:
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. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。