版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第四章 模塊化程序設(shè)計(jì),主講人:韓維良 2020年8月27日,C語(yǔ)言程序設(shè)計(jì),C語(yǔ)言支持模塊化程序設(shè)計(jì)的功能: (1) C語(yǔ)言用函數(shù)組織程序: 一個(gè)程序由一個(gè)或多個(gè)源程序文件組成; 每一個(gè)源程序文件就是一個(gè)程序模塊; 每一個(gè)程序模塊由一個(gè)或多個(gè)函數(shù)組成。 程序設(shè)計(jì)的任務(wù)就是設(shè)計(jì)一個(gè)個(gè)函數(shù),并且確定它們之間的調(diào)用關(guān)系。 在設(shè)計(jì)函數(shù)時(shí)要使每個(gè)函數(shù)都具有各自獨(dú)立的功能和明顯的界面。,C語(yǔ)言程序設(shè)計(jì),(2) 通過(guò)給變量定義不同的存儲(chǔ)類別,控制模塊內(nèi)部及外部的信息交換。 (3) 具有編譯預(yù)處理功能,為程序的調(diào)試、移植提供了方便,也支持了模塊化程序設(shè)計(jì)。,C語(yǔ)言程序設(shè)計(jì),第一節(jié) 函 數(shù) 一、設(shè)計(jì)C語(yǔ)言程序
2、就是設(shè)計(jì)函數(shù) 用C語(yǔ)言設(shè)計(jì)程序,任務(wù)只有一種,就是編寫(xiě)函數(shù),至少也要編寫(xiě)一個(gè)main函數(shù)。 執(zhí)行C程序也就是執(zhí)行相應(yīng)的main函數(shù)。即從main函數(shù)的第一個(gè)前花括號(hào)開(kāi)始,依次執(zhí)行后面的語(yǔ)句,直到最后的后花括號(hào)為止。,C語(yǔ)言程序設(shè)計(jì),模塊化程序設(shè)計(jì)有一個(gè)原則:就是每個(gè)模塊的規(guī)模一般不能太大(一般要控制在4060行之間),以便于閱讀,便于檢查其中的錯(cuò)誤。 在C語(yǔ)言中,減少主函數(shù)規(guī)模的一項(xiàng)基本措施就是通過(guò)調(diào)用其它函數(shù)來(lái)實(shí)現(xiàn)主函數(shù)需要的一些功能。,一般C語(yǔ)言程序的執(zhí)行過(guò)程,程序結(jié)構(gòu)圖,大學(xué)信息管理系統(tǒng),菜單函數(shù),C語(yǔ)言程序設(shè)計(jì),二、函數(shù)結(jié)構(gòu) 一個(gè)C語(yǔ)言函數(shù)的結(jié)構(gòu)形式如下: 函數(shù)頭 函數(shù)體 ,C語(yǔ)言程序
3、設(shè)計(jì),1. 函數(shù)頭 函數(shù)頭結(jié)構(gòu): 函數(shù)類型 函數(shù)名(形式參數(shù)表列) 一個(gè)函數(shù)的函數(shù)頭的結(jié)構(gòu)如下: (1)函數(shù)類型:指定函數(shù)值的類型,即函數(shù)返回值的類型。 (2)函數(shù)名:必須采用合法的用戶標(biāo)識(shí)符。 (3)圓括號(hào):是“函數(shù)運(yùn)算符”,表示進(jìn)行函數(shù)運(yùn)算,函數(shù)運(yùn)算符具有很高的運(yùn)算優(yōu)先級(jí)別。,C語(yǔ)言程序設(shè)計(jì),(4)形式參數(shù)表:由寫(xiě)在一對(duì)圓括號(hào)(函數(shù)運(yùn)算符)中的一系列參數(shù)組成。 每一個(gè)參數(shù)由一個(gè)類型符和一個(gè)參數(shù)名組成。參數(shù)名是合法的標(biāo)識(shí)符。 函數(shù)可以沒(méi)有參數(shù),這時(shí)在函數(shù)運(yùn)算符內(nèi)寫(xiě)一個(gè)“void”,也可以空白,但小括號(hào)不能省略。,C語(yǔ)言程序設(shè)計(jì),2. 函數(shù)體 函數(shù)體由一些語(yǔ)句組成。 主要是三種類型的語(yǔ)句: 聲
4、明語(yǔ)句:聲明在函數(shù)中要使用的變量等程序?qū)嶓w。 可執(zhí)行語(yǔ)句:用來(lái)實(shí)現(xiàn)函數(shù)的功能,包括若干流程控制 語(yǔ)句和表達(dá)式語(yǔ)句。 return語(yǔ)句:停止本函數(shù)的執(zhí)行,使流程返回到調(diào)用處。,C語(yǔ)言程序設(shè)計(jì),編譯器將函數(shù)分為三類進(jìn)行處理: 純粹計(jì)算型函數(shù),如sqrt()和sin()。將返回一個(gè)計(jì)算結(jié)果。 完成一項(xiàng)具體工作,返回完成的成敗。如printf()執(zhí)行成功時(shí),返回顯示的字節(jié)數(shù);失敗時(shí),返回一個(gè)負(fù)整數(shù)。 函數(shù)不產(chǎn)生返回值,其類型應(yīng)定義為void。 C99規(guī)定,對(duì)于非void類型的函數(shù),必須使用有返回值的return語(yǔ)句。,int absolutevalue (int x) /* 絕對(duì)值函數(shù) */ retu
5、rn (x=0?x:-x); void spc (int n) /* n空格函數(shù) */ int i; for (i=0; in;i+) printf (); return; /* 可以不要return語(yǔ)句 */ ,float y(float x) if (x0) return (x*x-x+1); else return (x*x*x-x+3); ,func(int n) if (n10) return (2*n+3); else return; ,平行的兩個(gè)返回語(yǔ)句,返回值不同,編譯時(shí)可能出現(xiàn)警告錯(cuò)誤,但不影響使用,結(jié)果不可預(yù)測(cè)。,C語(yǔ)言程序設(shè)計(jì),3. 函數(shù)中變量的作用域 作用域指的是一個(gè)程
6、序段中的變量的作用范圍,在一個(gè)函數(shù)中定義的變量只在本函數(shù)中有效,在其它函數(shù)中不能使用這個(gè)變量。 因此說(shuō),該變量的作用域是它所在的函數(shù)(從定義該變量的行開(kāi)始到函數(shù)末尾)。即使在不同的函數(shù)中定義了同名的變量,它們也是指不同的變量。,#include int func(int x) x=5; return x+3; int main(void) printf(x=%dn,x); return 0; ,這個(gè)程序企圖在main函數(shù)中使用func函數(shù)中的變量x。編譯這個(gè)程序,系統(tǒng)將給出如下編譯錯(cuò)誤: c(12) : error C2065: x : undeclared identifier (未聲明的標(biāo)
7、識(shí)符 ),C語(yǔ)言程序設(shè)計(jì),4. 空函數(shù) 空函數(shù)是一個(gè)不產(chǎn)生任何有效操作的函數(shù),但它卻是一個(gè)合法的C函數(shù)。 例如函數(shù) void null(void) 就是一個(gè)空函數(shù)。 空函數(shù)多使用在模塊化程序的設(shè)計(jì)或測(cè)試中。有一些函數(shù)還未編寫(xiě),可用空函數(shù)進(jìn)行調(diào)試,這樣就可以調(diào)試程序的其它部分,等以后再逐步補(bǔ)上。,C語(yǔ)言程序設(shè)計(jì),三、函數(shù)定義與函數(shù)聲明 1、函數(shù)定義 函數(shù)定義是按照C語(yǔ)言的語(yǔ)法規(guī)則引入新的函數(shù),并提供如下信息: 函數(shù)的返回值類型(如果有); 參數(shù)的個(gè)數(shù)及類型和名稱; 調(diào)用函數(shù)時(shí)要執(zhí)行的代碼; 函數(shù)的有效性(不能嵌套定義)。,C語(yǔ)言程序設(shè)計(jì),函數(shù)的定義 類型說(shuō)明符 函數(shù)名(類型名 形式參數(shù)1 , 類
8、型名 形式參數(shù)2 , ) /* 函數(shù)的首部 */ 說(shuō)明部分 /* 函數(shù)體 */ 語(yǔ)句部分 ,C語(yǔ)言程序設(shè)計(jì),其中類型說(shuō)明符和函數(shù)名部分共稱為函數(shù)頭。 類型說(shuō)明符即本函數(shù)的類型,實(shí)為函數(shù)返回值的類型。 函數(shù)名是由用戶定義的標(biāo)識(shí)符,函數(shù)名后有一個(gè)括號(hào),其內(nèi)容為形參表。 在形參表中給出的參數(shù)稱為形式參數(shù),即形式參數(shù)變量的定義,各參數(shù)定義之間用逗號(hào)間隔。在進(jìn)行函數(shù)調(diào)用時(shí),主調(diào)函數(shù)將賦予這些形式參數(shù)實(shí)際的值。 當(dāng)形參表中無(wú)參數(shù)時(shí),括號(hào)不可少。 中的內(nèi)容稱為函數(shù)體。 在函數(shù)體中也有類型說(shuō)明, 這是對(duì)函數(shù)體內(nèi)部所用到的變量的類型說(shuō)明。,注意:函數(shù)不能嵌套定義。 void fun1() int fun2()
9、,而應(yīng)該為如下形式: void fun1() int fun2() ,C語(yǔ)言程序設(shè)計(jì),2、函數(shù)的返回值及其類型 (1) return語(yǔ)句 函數(shù)的返回值通過(guò)函數(shù)體內(nèi)的return語(yǔ)句實(shí)現(xiàn)。 return 返回值表達(dá)式 ; 或 return (返回值表達(dá)式); 如果沒(méi)有返回值,格式中的左、右圓括號(hào)可以省略,即寫(xiě)為: return ; 功能:返回調(diào)用函數(shù),并將“返回值表達(dá)式”的值帶給調(diào)用函數(shù)。,C語(yǔ)言程序設(shè)計(jì),說(shuō)明: 1)函數(shù)的返回值只能有一個(gè)。 2)當(dāng)函數(shù)中不需要指明返回值時(shí),可以寫(xiě)成: return; 也可以不寫(xiě)。函數(shù)運(yùn)行到右花括號(hào)自然結(jié)束。 3)一個(gè)函數(shù)體內(nèi)可以有多個(gè)返回語(yǔ)句,不論執(zhí)行到哪一個(gè)
10、,函數(shù)都結(jié)束,回到主調(diào)函數(shù)。 4)當(dāng)函數(shù)沒(méi)有指明返回值,即return; 或沒(méi)有返回語(yǔ)句時(shí),函數(shù)執(zhí)行后實(shí)際上不是沒(méi)有返回值,而是返回一個(gè)不確定的值,有可能給程序帶來(lái)某種意外的影響。,C語(yǔ)言程序設(shè)計(jì),(2)函數(shù)返回值的類型 函數(shù)定義時(shí)的類型就是函數(shù)返回值的類型。從理論上,C語(yǔ)言要求函數(shù)定義的類型應(yīng)當(dāng)與返回語(yǔ)句中表達(dá)式的類型保持一致。當(dāng)兩者不一致時(shí),系統(tǒng)自動(dòng)進(jìn)行轉(zhuǎn)換,將函數(shù)返回語(yǔ)句中表達(dá)式的類型轉(zhuǎn)換為函數(shù)定義時(shí)的類型。 如果定義函數(shù)缺省函數(shù)類型,則系統(tǒng)一律按int型處理。,C語(yǔ)言程序設(shè)計(jì),3、函數(shù)聲明 函數(shù)聲明是對(duì)所用到的函數(shù)的特征進(jìn)行必要的聲明。 編譯系統(tǒng)以函數(shù)聲明為檢測(cè)依據(jù):檢測(cè)形參與實(shí)參類型
11、是否一致,返回值的類型是否正確,以保證調(diào)用表達(dá)式與函數(shù)之間的參數(shù)正確傳遞。 聲明語(yǔ)句提供的必要信息包括:函數(shù)名,函數(shù)的類型,函數(shù)參數(shù)的個(gè)數(shù)、排列次序以及每個(gè)參數(shù)的類型。,C語(yǔ)言程序設(shè)計(jì),函數(shù)的定義可以按任意的次序,但在主調(diào)函數(shù)中,要調(diào)用另一個(gè)函數(shù),則需要對(duì)被調(diào)函數(shù)先做聲明(或者說(shuō)明)。 所謂聲明,就是把函數(shù)的類型、函數(shù)的名稱、函數(shù)形參的類型及個(gè)數(shù)、順序通知編譯系統(tǒng),便于在調(diào)用時(shí)進(jìn)行檢查。 函數(shù)聲明的一般形式: 函數(shù)類型 函數(shù)名(參數(shù)類型1 , 參數(shù)類型2) ; 或 函數(shù)類型 函數(shù)名(參數(shù)類型1 參數(shù)名1 , 參數(shù)類型2 參數(shù)名2) ;,C語(yǔ)言程序設(shè)計(jì),說(shuō)明: (1)如果被調(diào)函數(shù)的返回值為int
12、類型,則不管被調(diào)函數(shù)位置如何均不需要在主調(diào)函數(shù)中說(shuō)明。 (2) 如果被調(diào)用函數(shù)的聲明放在源文件的開(kāi)頭,則該聲明對(duì)整個(gè)源文件都有效。 (3) 如果被調(diào)用函數(shù)的聲明是在調(diào)用函數(shù)定義的內(nèi)部,則該聲明僅對(duì)該調(diào)用函數(shù)有效。,C語(yǔ)言程序設(shè)計(jì),(4) 在函數(shù)調(diào)用中,有下面幾種情況可以省略聲明: a. 如果調(diào)用函數(shù)和被調(diào)用函數(shù)是在同一個(gè)源文件中,而且被調(diào)用函數(shù)的定義是在調(diào)用函數(shù)之前。 b. 函數(shù)的返回值是整數(shù)或字符。 c. 所有被調(diào)用函數(shù)的聲明都是在源文件開(kāi)頭。 d. 如果被調(diào)用函數(shù)不是在源文件開(kāi)頭,而是在源文件中間且在所有函數(shù)之外某處被聲明時(shí),則在被聲明之后引用它時(shí),不必再聲明,但在被聲明之前引用它時(shí),需要
13、對(duì)其進(jìn)行聲明。 (5) 如果調(diào)用函數(shù)和被調(diào)用函數(shù)的定義是在同一源文件中,應(yīng)該先說(shuō)明或定義被調(diào)用函數(shù)。,設(shè)有一函數(shù)的定義為: double func (double a, int b, char c) /* 函數(shù)體*/ 與之相應(yīng)的函數(shù)聲明應(yīng)為: double func (double x, int y, char z); /* 注意末尾的分號(hào) */,33,C語(yǔ)言程序設(shè)計(jì),例求二實(shí)數(shù)之和 main ( ) float add(float,float); float a, b, c; scanf(%f%f, 說(shuō)明:調(diào)用過(guò)程中參數(shù)的對(duì)應(yīng)關(guān)系。,C語(yǔ)言程序設(shè)計(jì),例 定義一個(gè)求兩個(gè)整數(shù)中極大值的max()
14、函數(shù)。 /*功能:求2個(gè)整數(shù)中的較大數(shù) */ /*形參:2個(gè),整型 */ /*返回值: 2個(gè)整數(shù)中的較大數(shù) */ int max(int n1,int n2) /*函數(shù)定義 */ int z; z= n1 n2 ? n1 : n2; return (z); ,C語(yǔ)言程序設(shè)計(jì),void main( void ) int max(int n1, int n2); /*對(duì)被調(diào)函數(shù)說(shuō)明*/ int num1,num2; printf(input two numbers: ); scanf(%d%d, printf (%f+%f=%fn, x,y, add(x,y); float add (unsign
15、ed int a, unsigned int b) printf(a=%u, b=%un, a,b); return (a+b); ,分析結(jié)果為什么錯(cuò)誤? 如何改正?,3、傳值調(diào)用的虛實(shí)結(jié)合過(guò)程 程序進(jìn)行編譯時(shí),并不為形式參數(shù)分配存儲(chǔ)空間。 只有在被調(diào)用時(shí),形式參數(shù)才臨時(shí)地占有存儲(chǔ)空間,其過(guò)程如下: (1)調(diào)用開(kāi)始,系統(tǒng)為形參開(kāi)辟一個(gè)臨時(shí)存儲(chǔ)區(qū),形參與實(shí)參各占一個(gè)獨(dú)立的存儲(chǔ)空間。 (2)將各實(shí)參之值傳遞給對(duì)應(yīng)形參,形參得到了實(shí)參的值。這種虛實(shí)結(jié)合方式稱為“值結(jié)合”。,(3)函數(shù)返回時(shí),臨時(shí)存儲(chǔ)區(qū)也被撤銷。 特別注意:在C程序中實(shí)參與形參是傳值調(diào)用(call by value) 的特點(diǎn)。即實(shí)參與
16、形參是“單向的值傳遞” 即函數(shù)中對(duì)形參變量的操作不會(huì)影響到調(diào)用函數(shù)中的實(shí)參變量,即形參值不能傳回給實(shí)參。,#include void swap (int x, int y); int main(void) int a=3, b=5; swap (a,b); printf (a=%d, b=%dn, a,b); return 0; void swap (int x, int y) int temp; temp=x, x=y, y=temp; /* 交換變量的值 */ printf(x=%d,y=%dn,x,y); ,執(zhí)行結(jié)果: x=5,y=3 a=3,b=5,企圖交換變量a,b的值,沒(méi)有成功,五
17、、函數(shù)的嵌套調(diào)用,語(yǔ)言的函數(shù)定義是互相平行、獨(dú)立的 函數(shù)不能嵌套定義 可以嵌套調(diào)用函數(shù) 調(diào)用一個(gè)函數(shù)的過(guò)程中,又可以調(diào)用另一個(gè)函數(shù)。,函數(shù)的嵌套調(diào)用的過(guò)程,main函數(shù),調(diào)用a函數(shù),結(jié)束,a函數(shù),調(diào)用b函數(shù),b函數(shù),C語(yǔ)言程序設(shè)計(jì),例一個(gè)偶數(shù)為兩個(gè)素?cái)?shù)之和。 德國(guó)數(shù)學(xué)家哥德巴赫(GoLdbach)在1725年寫(xiě)給歐拉(Euler)的信中寫(xiě)下了以下猜想:任何不小于6的偶數(shù)都是兩個(gè)素?cái)?shù)之和(俗稱為1+1)。如633,1257等等。 兩個(gè)多世紀(jì)過(guò)去了,這一猜想既無(wú)法證明也沒(méi)被推翻。試設(shè)計(jì)程序驗(yàn)證這一猜想是否成立。 對(duì)于一個(gè)偶數(shù),找出一個(gè)小于它的數(shù),判斷是否是素?cái)?shù),如果是就計(jì)算該偶數(shù)與該素?cái)?shù)的差并判斷
18、它是否是素?cái)?shù)。如果兩者都是素?cái)?shù)則猜想得到驗(yàn)證。 問(wèn)題表現(xiàn)為:任意輸入一個(gè)偶數(shù),可將其分解為兩個(gè)素?cái)?shù)之和。,50,C語(yǔ)言程序設(shè)計(jì),#include main() void even(int x); int a; printf(“請(qǐng)輸入一個(gè)偶數(shù):”); scanf(“%d”, ,51,C語(yǔ)言程序設(shè)計(jì),void even(int x) int isprime(int a); int i; for(i=2;i=x/2;i+) if ( isprime(i) ,C語(yǔ)言程序設(shè)計(jì),int isprime(int a) int i; for(i=2;i=a/2;i+) if(a%i=0) return 0;
19、return 1; 注意兩個(gè)返回語(yǔ)句。,C語(yǔ)言程序設(shè)計(jì),例輸入一個(gè)由若干個(gè)單詞組成的文本串,每個(gè)單詞之間用空格、換行符、跳格符(制表符)分隔,且分隔符可以不至一個(gè)(如連續(xù)的兩個(gè)空格),以作為輸入的結(jié)束標(biāo)志,統(tǒng)計(jì)此文本串單詞的個(gè)數(shù)? 如輸入:This is a student. 分析:因?yàn)橛?jì)算機(jī)無(wú)法直接識(shí)別單詞,所以從輸入的文本串中逐個(gè)讀取每一個(gè)字符,當(dāng)讀到每一個(gè)單詞的第一個(gè)字母時(shí),計(jì)數(shù)器加1 。 如何知道讀取到的字符是單詞的第一個(gè)字母呢? 如果讀取到的字符是分隔符,則不是單詞的一部分; 如果讀取到的字符不是分隔符,且它的上一個(gè)字符是分隔符,則它是單詞的第一個(gè)字母,計(jì)數(shù)器加1。 如果讀取到的字符
20、不是分隔符,且它的上一個(gè)字符也不是分隔符,則它是單詞的非首字母,計(jì)數(shù)器不加1。,C語(yǔ)言程序設(shè)計(jì),當(dāng)前讀取到的字符是否是單詞的一部分,可用一個(gè)狀態(tài)變量來(lái)表示,如果是單詞的一部分,則用1表示,反之用0表示。 #include #define IN 1 #define OUT 0 int countword(); main() int n; n=countword(); printf(“單詞數(shù)為:%dn”,n); ,55,C語(yǔ)言程序設(shè)計(jì),int countword() /*沒(méi)有形參*/ int c,nw,state; state=OUT; nw=0; while(c=getchar()!=) if(
21、c= |c=n|c=t) state=OUT; else if(state=OUT) state=IN; nw+; return(nw); ,六、遞歸函數(shù) 一個(gè)函數(shù)可以調(diào)用另一個(gè)函數(shù)。 遞歸函數(shù)一個(gè)函數(shù)自己調(diào)用自己(直接地或間接地調(diào)用自己)。 前者稱為直接遞歸調(diào)用函數(shù),后者稱為間接遞歸調(diào)用函數(shù)。 1.遞歸調(diào)用次數(shù)有限 2.程序執(zhí)行有規(guī)律 3.有結(jié)束調(diào)用的條件,C語(yǔ)言程序設(shè)計(jì),遞歸調(diào)用是指一個(gè)函數(shù)直接或間接地調(diào)用自己。這種函數(shù)稱為遞歸函數(shù)。自己調(diào)用自己,即要解決一個(gè)問(wèn)題,轉(zhuǎn)化為一個(gè)用同樣的方法解決的新問(wèn)題,只是參數(shù)在不斷地遞增或者遞減。 在遞歸調(diào)用中,主調(diào)函數(shù)又是被調(diào)函數(shù)。執(zhí)行遞歸函數(shù)將反復(fù)調(diào)用
22、其自身。 對(duì)于一些特定的問(wèn)題,用遞歸算法來(lái)解決,可以簡(jiǎn)化問(wèn)題的復(fù)雜程度。,8/27/2020,58,8/27/2020,59,C語(yǔ)言程序設(shè)計(jì),例:用遞歸調(diào)用求n!。 要用遞歸法解決此問(wèn)題,必須明確兩個(gè)問(wèn)題: 、遞歸算法 n!=n*(n-1)! (n-1)!=(n-1)*(n-2)!; 求n的階乘的問(wèn)題,轉(zhuǎn)化為用同樣的方法求(n-1)的階乘。 如:4!4*3! 3!3*2! 如果編寫(xiě)成一個(gè)函數(shù),則調(diào)用如下: f(n)=n*f(n-1); 不斷地自己調(diào)用自己。,C語(yǔ)言程序設(shè)計(jì),、遞歸終結(jié)條件 遞歸到一定的程度后,必須終止。 如求階乘時(shí),當(dāng)求到1!時(shí),必須停止遞歸。 f(1)=1 這一條是必須的,否
23、則將會(huì)沒(méi)完沒(méi)了的進(jìn)行下去。 通常用條件判斷, 滿足某種條件后就不再作遞歸調(diào)用,然后逐層返回。,C語(yǔ)言程序設(shè)計(jì),例如有函數(shù)f如下: int f(int x) z=f(x1); return z; 上頁(yè)中的函數(shù)是一個(gè)遞歸函數(shù)。 但是運(yùn)行該函數(shù)將無(wú)休止地調(diào)用其自身,這當(dāng)然是不正確的。為了防止遞歸調(diào)用無(wú)終止地進(jìn)行, 必須在函數(shù)內(nèi)有終止遞歸調(diào)用的手段。,C語(yǔ)言程序設(shè)計(jì),例 用遞歸法計(jì)算n!。 #include long f(int n) long y; if(n1) y=n*f(n-1); else y=1; return(y); ,64,C語(yǔ)言程序設(shè)計(jì),main() int n; long y; pr
24、intf(“input a inteager number:”); scanf(%d, 程序運(yùn)行情況如下: input a inteager number: 5 5!=120,C語(yǔ)言程序設(shè)計(jì),程序說(shuō)明: 程序中給出的函數(shù)f是一個(gè)遞歸函數(shù)。主函數(shù)調(diào)用f 后即進(jìn)入函數(shù)f執(zhí)行,如果n0,n=0或n=1時(shí)都將結(jié)束函數(shù)的執(zhí)行,否則就遞歸調(diào)用f函數(shù)自身。由于每次遞歸調(diào)用的實(shí)參為n-1,即把n-1 的值賦予形參n,最后當(dāng)n-1的值為1時(shí)再作遞歸調(diào)用,形參n的值也為1,將使遞歸終止。然后可逐層退回。,C語(yǔ)言程序設(shè)計(jì),如求4!的過(guò)程分解如下:,C語(yǔ)言程序設(shè)計(jì),例:用遞歸法求菲波那契數(shù)列第40項(xiàng)的值,該數(shù)列為:1
25、,1,2,3,5,8,13,21, 規(guī)律:每一項(xiàng)為其前兩項(xiàng)的和。 遞歸算法如下: fib(n)=fib(n-1)+fib(n-2); 遞歸的終結(jié)條件如下: fib(1)=1; fib(2)=1;,C語(yǔ)言程序設(shè)計(jì),#include main() int n; long fib(int); /*第40項(xiàng)的值很大*/ printf(“請(qǐng)輸入項(xiàng)數(shù):”); scanf(“%d”, ,69,C語(yǔ)言程序設(shè)計(jì),long fib(int n) long result; if(n=1|n=2) result=1; else result=fib(n-1)+fib(n-2); return result; ,第二節(jié)
26、 變量的存儲(chǔ)屬性 變量是對(duì)程序中數(shù)據(jù)存儲(chǔ)的抽象。 C語(yǔ)言程序中變量都有類型,數(shù)據(jù)類型是變量的運(yùn)算屬性的抽象,決定了該變量的取值范圍和可以施加的運(yùn)算種類。 除此之外,變量還有一些屬性,例如: 一個(gè)變量在程序的哪個(gè)范圍內(nèi)是可以使用的變量的可用域; 它什么時(shí)候生成以及什么時(shí)候被撤消變量的生存期;,它存儲(chǔ)在什么哪種類型的存儲(chǔ)器中以及用什么機(jī)制進(jìn)行存儲(chǔ)變量的存儲(chǔ)區(qū)。 這些都稱為變量的存儲(chǔ)屬性。,一、變量的作用域與生存期 在函數(shù)中形參變量只在被調(diào)用期間才分配內(nèi)存單元,調(diào)用結(jié)束立即釋放。形參變量只有在函數(shù)內(nèi)才是有效的,離開(kāi)該函數(shù)就不能再使用了。 如:貨幣的使用范圍,校園卡的使用范圍。 1. 局部變量和全局變
27、量 變量的可用域是指一個(gè)變量在程序的哪個(gè)域內(nèi)才是可以被識(shí)別的,也稱為可見(jiàn)(或可用)的。 變量可分為兩種: 全局可用全局變量 局部可用局部變量。,C語(yǔ)言程序設(shè)計(jì),局部變量:在一個(gè)函數(shù)或者復(fù)合語(yǔ)句(如函數(shù)體、循環(huán)體)內(nèi)部定義的變量是局部變量,它只在該函數(shù)或者復(fù)合語(yǔ)句范圍內(nèi)有效。而在其它函數(shù)內(nèi)不能使用。 只有在包含變量定義的函數(shù)內(nèi)部,才能使用被定義的變量,在此函數(shù)之外就不能使用這些變量了。又稱為內(nèi)部變量。 例如: int f1(int a) /*函數(shù)f1*/ int b,c; /*a,b,c作用域:僅限于函數(shù)f1()中*/,C語(yǔ)言程序設(shè)計(jì),int f2(int x) /*函數(shù)f2*/ int y,z
28、; /*x,y,z作用域:僅限于函數(shù)f2()中*/ main() int m,n; /*m,n作用域:僅限于函數(shù)main()中*/ 由于局部變量只在一個(gè)局部范圍中使用,因此在不同的函數(shù)中可以定義同名的局部變量,它們互不干擾,各自分配不同的獨(dú)立存貯單元。這種特性便于進(jìn)行模塊化設(shè)計(jì),不同的模塊由不同的程序員設(shè)計(jì),各模塊中使用的變量名由用戶自己確定,即便相同也不會(huì)彼此影響。,75,C語(yǔ)言程序設(shè)計(jì),#include main() void fun1(); void fun2(); int x=1; printf(“x=%dn”,x); int x=3; printf(“x=%dn”,x); print
29、f(“x=%dn”,x); fun1(); printf(“x=%dn”,x); fun2(); printf(“x=%dn”,x); fun1(); ,C語(yǔ)言程序設(shè)計(jì),fun1() int x=5; printf(“x=%dn”,x); fun2() int x=7; printf(“x=%dn”,x); 說(shuō)明: 四個(gè)X分別分配了不同的存貯單元。 同一函數(shù)的兩次調(diào)用分配了不同的單元。,#include int main(void) /* printf(a1=%d,a); */ int a=3; printf(a2=%d,a); int b=5; printf(b1=%d,b); /* pri
30、ntf(b2=%d,b); */ printf(a3=%d,a); return 0; ,則運(yùn)行可以得到如下結(jié)果: a2=3 b1=5 a3=3,C語(yǔ)言程序設(shè)計(jì),全局變量:也稱為外部變量,是在函數(shù)外部定義的變量,作用域?yàn)閺亩x全局變量位置開(kāi)始到源程序結(jié)束,是多個(gè)函數(shù)間進(jìn)行數(shù)據(jù)傳遞的一種手段。 全局變量可以在其作用范圍內(nèi),由各函數(shù)所共用。 在函數(shù)中使用全局變量,一般應(yīng)作全局變量說(shuō)明。 只有在函數(shù)內(nèi)經(jīng)過(guò)說(shuō)明的全局變量才能使用。 全局變量的說(shuō)明符為extern。 但在一個(gè)函數(shù)之前定義的全局變量,在該函數(shù)內(nèi)使用可不再加以說(shuō)明。,C語(yǔ)言程序設(shè)計(jì),例如: int a,b; /*外部變量*/ void f1
31、() /*函數(shù)f1*/ float x,y; /*外部變量*/ int f2() /*函數(shù)f2*/ ,C語(yǔ)言程序設(shè)計(jì),main() /*主函數(shù)*/ /*全局變量x,y作用域 全局變量a,b作用域*/ 從上例可以看出a、b、x、y 都是在函數(shù)外部定義的外部變量,都是全局變量。但x,y 定義在函數(shù)f1之后,而在f1內(nèi)又無(wú)對(duì)x,y的說(shuō)明,所以它們?cè)趂1內(nèi)無(wú)效。 a,b定義在源程序最前面,因此在f1,f2及main內(nèi)不加說(shuō)明也可使用。,81,C語(yǔ)言程序設(shè)計(jì),#include int a=3,b=5; main() void fun(); printf(“a=%d,b=%dn”,a,b); fun();
32、 printf(“a=%d,b=%dn”,a,b); void fun() int c; c=a;a=b;b=c; printf(“a=%d,b=%dn”,a,b); ,C語(yǔ)言程序設(shè)計(jì),【例】輸入長(zhǎng)方體的長(zhǎng)寬高l,w,h。求體積及三個(gè)面x*y,x*z,y*z的面積。 int s1,s2,s3; int vs( int a,int b,int c) int v; v=a*b*c; s1=a*b; s2=b*c; s3=a*c; return v; ,C語(yǔ)言程序設(shè)計(jì),main() int v,l,w,h; printf(ninput length,width and height: ); scan
33、f(%d%d%d, 程序運(yùn)行結(jié)果如下: input length,width and height:4 5 6 v=120 s1=20 s2=30 s3=24,C語(yǔ)言程序設(shè)計(jì),程序說(shuō)明: 本程序中定義了三個(gè)外部變量s1,s2,s3,用來(lái)存放三個(gè)面積,其作用域?yàn)檎麄€(gè)程序。函數(shù)vs用來(lái)求正方體體積和三個(gè)面積,函數(shù)的返回值為體積v。由主函數(shù)完成長(zhǎng)寬高的輸入及結(jié)果輸出。 由于語(yǔ)言規(guī)定函數(shù)返回值只有一個(gè),當(dāng)需要增加函數(shù)的返回?cái)?shù)據(jù)時(shí),用外部變量是一種很好的方式。本例中,如不使用外部變量,在主函數(shù)中就不可能取得v,s1,s2,s3四個(gè)值。而采用了外部變量,在函數(shù)vs中求得的s1,s2,s3值在main中仍然
34、有效。因此外部變量是實(shí)現(xiàn)函數(shù)之間數(shù)據(jù)傳輸?shù)挠行侄巍?C語(yǔ)言程序設(shè)計(jì),當(dāng)在函數(shù)外定義了一個(gè)全局變量后,定義點(diǎn)之后的函數(shù)都可以使用該變量. 當(dāng)全局變量的值在一個(gè)函數(shù)中改變后,另一個(gè)函數(shù)使用的就是改變后的值. 從定義開(kāi)始到程序結(jié)束,全局變量自始至終占用存儲(chǔ)空間. 全局變量的使用使函數(shù)間的聯(lián)系加強(qiáng),與程序設(shè)計(jì)”低耦合”的原則相違背,所以很少使用。,例同名局部變量 #include int main(void) int a=3; printf(a1=%d,a); int a=5; printf(a2=%d,a); return 0; ,例演示全局變量 #include void a() int a=1
35、; printf(a1=%dn,a); printf(x1=%dn,x); int x=3; * 定義外部變量 */ void b() printf(x2=%dn,x); int main(void) a(); b(); printf(x3=%dn,x); return 0; ,例演示全局變量與局部變量同名 #include int x=3; /* 定義外部變量 */ int main(void) int x=5; printf(x=%dn,x); return 0; ,2. 動(dòng)態(tài)變量與靜態(tài)變量 運(yùn)行中的程序,在內(nèi)存中被分成代碼區(qū)和數(shù)據(jù)區(qū)兩大部分。 數(shù)據(jù)區(qū)又分為靜態(tài)存儲(chǔ)區(qū)、自動(dòng)存儲(chǔ)區(qū)和動(dòng)態(tài)分配
36、區(qū)三部分。 自動(dòng)存儲(chǔ)區(qū)是按棧組織的存儲(chǔ)區(qū)。 除特別聲明的外,局部變量通常被存放在棧區(qū)。 這些變量在進(jìn)入所在的塊時(shí)被創(chuàng)建,所在的塊結(jié)束時(shí)被撤銷,其值不再保留。并且,變量必須有程序員顯式地進(jìn)行初始化,否則它們的初始值是不確定的。,靜態(tài)存儲(chǔ)區(qū)是在程序編譯時(shí)就分配的存儲(chǔ)區(qū)。 分配在靜態(tài)存儲(chǔ)區(qū)的變量在程序開(kāi)始執(zhí)行時(shí)被創(chuàng)建并自動(dòng)初始化(數(shù)值變量被初始化為0),當(dāng)程序結(jié)束時(shí)才被撤銷。 所以常稱靜態(tài)變量的生存期是永久的。 全局變量就是被分配在靜態(tài)存儲(chǔ)區(qū)的。,/* 企圖交換兩個(gè)變量的值*/ #include void swap(void);/* 說(shuō)明函數(shù) */ int a=3, b=5;/* 聲明外部變量 */
37、 int main(void) printf (a=%d, b=%dn,a, b); swap(); printf (a=%d, b=%dn, a,b); return 0; void swap(void) int c;/* 聲明自動(dòng)變量*/ c=a; a=b; b=c;/* 交換變量的值 */ ,二、C語(yǔ)言中變量的存儲(chǔ)類型 根據(jù)可用域和生存期,變量有4種存儲(chǔ)類型: 局部自動(dòng)類型,在函數(shù)內(nèi)部用標(biāo)識(shí)符auto或register聲明。 靜態(tài)局部類型,在函數(shù)內(nèi)部,使用static聲明。 靜態(tài)全局類型,在函數(shù)外部,使用static聲明,也稱靜態(tài)外部變量。 全局類型,不需要標(biāo)識(shí)符聲明。在函數(shù)外部直接聲明
38、即可,通稱外部變量。,1、auto存儲(chǔ)類型和register存儲(chǔ)類型 使用auto聲明的變量是局部變量,編譯器將其分配在自動(dòng)存儲(chǔ)區(qū)。 其格式為: auto 數(shù)據(jù)類型變量名=初值表達(dá)式,; 其中方括號(hào)表示可省略,省略auto,系統(tǒng)隱含認(rèn)為此變量為auto。 函數(shù)的參數(shù)(形參)也是一種自動(dòng)變量。,C語(yǔ)言程序設(shè)計(jì),自動(dòng)變量的類型說(shuō)明符為auto; 語(yǔ)言規(guī)定,函數(shù)內(nèi)凡未加存儲(chǔ)類型說(shuō)明的變量均視為自動(dòng)變量,也就是說(shuō)自動(dòng)變量可省去說(shuō)明符auto。 在前面所學(xué)的程序中定義的變量凡未加存儲(chǔ)類型說(shuō)明符的都是自動(dòng)變量。,C語(yǔ)言程序設(shè)計(jì),例如: int a,b,k; char c; 等價(jià)于: auto int a,
39、b,k; auto char c; ,C語(yǔ)言程序設(shè)計(jì),自動(dòng)變量的特點(diǎn): 自動(dòng)變量的作用域僅限于定義該變量的函數(shù)或復(fù)合語(yǔ)句內(nèi)。 自動(dòng)變量存貯在自動(dòng)存貯區(qū),只有在使用它,即定義該變量的函數(shù)被調(diào)用時(shí)才給它分配存儲(chǔ)單元,開(kāi)始它的生存期。函數(shù)調(diào)用結(jié)束,釋放存儲(chǔ)單元,結(jié)束生存期。因此函數(shù)調(diào)用結(jié)束之后,自動(dòng)變量的值不能保留。 未初始化時(shí),自動(dòng)變量的值是不確定的。 由于自動(dòng)變量的作用域和生存期都局限于定義它的函數(shù)或復(fù)合語(yǔ)句內(nèi),因此不同的函數(shù)中允許使用同名的變量而不會(huì)混淆。,C語(yǔ)言程序設(shè)計(jì),寄存器變量的說(shuō)明符是register。 存放在CPU的寄存器中,使用時(shí),不需要訪問(wèn)內(nèi)存,而直接從寄存器中讀寫(xiě), 這樣可提高
40、訪問(wèn)效率。 特點(diǎn):加快運(yùn)算速度,函數(shù)運(yùn)行完即消失、使用有限。 如定義一個(gè)頻繁使用的變量為寄存器類型: register int i;,C語(yǔ)言程序設(shè)計(jì),2、靜態(tài)局部類型 類型說(shuō)明符:static,屬于靜態(tài)存儲(chǔ)方式; 在一個(gè)函數(shù)內(nèi)部,可以用static定義一個(gè)變量,稱為靜態(tài)局部變量。其作用域仍在定義它的函數(shù)內(nèi)部,但其生存期卻程序運(yùn)行期。 函數(shù)調(diào)用結(jié)束后,并不釋放所占用的存貯空間(總是占用固定的存貯空間),在程序運(yùn)行期間,始終存在,但除了定義它的函數(shù)以外,別的函數(shù)不能使用。整個(gè)程序運(yùn)行結(jié)束后,才釋放占用的空間。,C語(yǔ)言程序設(shè)計(jì),靜態(tài)局部變量的特點(diǎn): (1)靜態(tài)局部變量在每次調(diào)用函數(shù)結(jié)束后能夠保留調(diào)用
41、結(jié)束后的值不變,留待下一次調(diào)用,變量值具有繼承性。 (2)靜態(tài)局部變量只限于被本函數(shù)使用,不能被其他函數(shù)使用 (3)靜態(tài)局部變量屬于靜態(tài)存儲(chǔ)類別,在整個(gè)程序運(yùn)行期間都不釋放;而動(dòng)態(tài)存儲(chǔ)變量屬于動(dòng)態(tài)存儲(chǔ)類別,函數(shù)調(diào)用結(jié)束即釋放,再次調(diào)用又將重新分配空間。 (4)在定義靜態(tài)局部變量時(shí),如果不賦初值,系統(tǒng)自動(dòng)賦值為0或空字符(對(duì)字符型變量)。,99,C語(yǔ)言程序設(shè)計(jì),#include func() static int b=10; b=b+2; return b; main() int i; for(i=1;i4;i+) printf(“%d,b=%dn”,i,func(); ,#include vo
42、id increment(void); int main(void) increment ( ); increment ( ); increment ( ); return 0; void increment(void) int x=0; /*auto*/ x+; printf (%dn,x); ,運(yùn)行結(jié)果: 1 1 1,#include void increment(void); int main(void) increment ( ); increment ( ); increment ( ); return 0; void increment(void) static int x=0;
43、/*使用了static說(shuō)明符 */ x+; printf (%dn,x); ,運(yùn)行結(jié)果: 1 2 3,3、靜態(tài)全局類型 在多文件程序中,用static聲明外部變量,使該外部變量的作用域僅限于所在的文件,而不用static聲明的外部變量的作用域?yàn)檎麄€(gè)程序。 例如:某個(gè)程序中要用到大量函數(shù),而有幾個(gè)函數(shù)需要共同使用幾個(gè)全局變量時(shí),可以將這幾個(gè)函數(shù)組織在一個(gè)文件中,而將這幾個(gè)全局變量用static定義為靜態(tài)的,以保證它們不會(huì)與其他文件中的變量發(fā)生名字沖突,保證文件的獨(dú)立性。,static unsigned int r; int random(void) r=(r*123+59)%65536; ret
44、urn(r); /*產(chǎn)生r的初值*/ unsigned randomstart(unsigned int seed)r=seed; #include int main(void) int i, n; printf (please enter the seed:); scanf(%d, ,C語(yǔ)言程序設(shè)計(jì),4、外部變量的定義與聲明 外部變量的類型說(shuō)明符為extern。 外部變量的特點(diǎn): (1) 外部變量和全局變量是對(duì)同一類變量的兩種不同角度的提法。全局變量是從它的作用域提出的,外部變量從它的存儲(chǔ)方式提出的,表示了它的生存期。 (2)當(dāng)一個(gè)源程序由若干個(gè)源文件組成時(shí), 在一個(gè)源文件中定義的外部變量在
45、其它的源文件中也有效。 一個(gè)變量被定義點(diǎn)之前的函數(shù)使用或者被別的文件中的函數(shù)使用時(shí),應(yīng)用extern聲明。,對(duì)外部變量(靜態(tài)全局變量除外),除可以定義一次外,還可以多次進(jìn)行聲明(引用性聲明)。 (1)通過(guò)聲明將外部變量的作用域在本文件范圍內(nèi)擴(kuò)充向前引用 通常,一個(gè)外部變量的作用域是從其定義點(diǎn)到本文件末尾。對(duì)于位于定義點(diǎn)之前的函數(shù),可以用extern聲明使變量的作用域擴(kuò)充到需要用到它的函數(shù)。,#include void gx(), gy (); void main(void) extern int x,y; /*聲明x,y是外部變量,作用域擴(kuò)充至此*/ printf (1:x=%dt y=%dn
46、, x, y); y=246; gx(); gy(); void gx() extern int x, y; /*聲明x,y是外部變量*/ x=135; printf(2:x=%dt y=%dn, x, y); int x, y; /*定義x,y是外部變量 */ void gy() printf(3:x=%dt y=%dn, x, y); ,(2)利用聲明語(yǔ)句將作用域擴(kuò)大到其他文件建立對(duì)象的外部鏈接 假設(shè)一個(gè)程序由兩個(gè)以上的文件組成。當(dāng)一個(gè)全局變量定義在文件file1中時(shí),在另外的文件中使用extern聲明,可以通知編譯系統(tǒng)一個(gè)信息:“此變量到外部去找”?;蛘哒f(shuō)在鏈接時(shí),告訴鏈接器:“到別的文
47、件中找這個(gè)變量的定義”。,* file1.c */ #include int x, y; char ch; void main(void) x=12; y=24; f1(); printf(%cn, ch); ,* file2.c */ extern int x,y; extern char ch; f1( ) printf (%d, %dn, x,y); ch=a; ,(3) 全局變量的副作用 如果沒(méi)有外部變量,函數(shù)只能通過(guò)參數(shù)與外界發(fā)生數(shù)據(jù)聯(lián)系,有了外部變量以后,增加了一條與外界傳遞數(shù)據(jù)的渠道,但也會(huì)產(chǎn)生一些副作用.,/* 例能否輸出5行 *?*/ #include int i; void
48、 main(void) void prt(); for(i=0; i5; i+) /* 輸出5行 */ prt(); void prt() /* 輸出一行5個(gè)* */ for(i=0; i5; i+) printf (%c, *); printf(n); ,三、通過(guò)const聲明將變量存儲(chǔ)在只讀區(qū) C語(yǔ)言可以開(kāi)辟一個(gè)只讀區(qū)。數(shù)據(jù)是以變量形式存儲(chǔ)的,只讀的,不可修改。也就是把變量定義為只讀變量。 定義只讀變量的方法是在聲明變量時(shí)使用修飾符const。 格式為: const 數(shù)據(jù)類型 變量1=初始表達(dá)式1,變量2=初始表達(dá)式2, 如:const double X=3.14159265;,C語(yǔ)言程序
49、設(shè)計(jì),第三節(jié) 模塊的編譯與鏈接 一、分別編譯 C語(yǔ)言是一種支持模塊化程序設(shè)計(jì)的語(yǔ)言,它允許將一個(gè)大型程序分成多個(gè)程序文件分別進(jìn)行編譯。 這樣的好處在于: 當(dāng)程序的一個(gè)局部有錯(cuò)誤或?qū)植窟M(jìn)行了修改時(shí),可以只重新編譯該局部,不需要將整個(gè)程序都重新編譯。 某些經(jīng)過(guò)考驗(yàn)的函數(shù)的目標(biāo)代碼可以添加為的庫(kù)函數(shù),供其他程序中使用。,C語(yǔ)言程序設(shè)計(jì),二、用項(xiàng)目管理多文件程序的編譯與鏈接過(guò)程 多文件程序的編譯、鏈接過(guò)程是比較麻煩的。為了方便用戶進(jìn)行多文件程序的編譯、鏈接,各種程序開(kāi)發(fā)軟件都提供了用項(xiàng)目(project)管理多文件程序的編譯和鏈接過(guò)程。其使用方法因開(kāi)發(fā)工具而異,請(qǐng)參考有關(guān)手冊(cè)。,C語(yǔ)言程序設(shè)計(jì),三、
50、頭文件 用戶顯式地保證程序一致性的基本方法是保持聲明的一致性。 保持聲明一致性的簡(jiǎn)單辦法是提供一個(gè)頭文件,讓頭文件中的信息作為各模塊之間的接口信息,有利于提供可重用的模塊。 使用頭文件將把程序分為程序頭和程序體兩部分。,好的頭文件應(yīng)包含如下一些內(nèi)容: 類型定義 如定義一個(gè)枚舉類型: enum color RED,BLUE,GREEN,YELLOW; 函數(shù)聲明 如: extern int strlen const char*; 嵌入函數(shù)聲明 如:inline char get() return *p+; 數(shù)據(jù)聲明 如:extern int a;,常量定義 如: const float pi=3.
51、141593; 包含指令 如: #include 宏定義 如:#define case break; case 注釋,好的頭文件不能包含以下內(nèi)容: 一般函數(shù)定義 數(shù)據(jù)定義 如: int a; 常量聚集定義 如: const tbl=/* */; 用戶頭文件是由用戶自己定義的頭文件。 系統(tǒng)將用雙引號(hào)方式進(jìn)行搜索。 #include 頭文件名.h,程序員可以用它們建立各文件之間的信息窗口。 應(yīng)當(dāng)注意,修改了頭文件時(shí),所有涉及該頭文件的程序都應(yīng)重新編譯,所以在編制頭文件時(shí)應(yīng)盡量考慮周全。 當(dāng)使用很多頭文件時(shí),常有重復(fù)嵌入的情形發(fā)生,在這種情形下,應(yīng)防止標(biāo)識(shí)符重復(fù)定義的錯(cuò)誤。 為避免錯(cuò)誤,應(yīng)使用條件編
52、譯來(lái)測(cè)試有無(wú)重復(fù)定義。,C語(yǔ)言程序設(shè)計(jì),第四節(jié) 宏定義與宏替換 編譯預(yù)處理是以“#”開(kāi)頭的一些命令,它通知編譯系統(tǒng):在進(jìn)行正式編譯前應(yīng)當(dāng)先進(jìn)行一些前期工作(即編譯預(yù)處理)。 目前,C語(yǔ)言的編譯預(yù)處理功能主要有如下一些: (1)文件包含,使用命令:#include。 (2)宏定義,使用命令:#define、#undef。 (3)條件編譯,使用命令:#if、#ifdef、#ifndef、#else、#endif、#elif、defind。,(4)提供行號(hào)信息,使用命令:#line。 (5)編譯雜注,使用命令:#progma。 (6)錯(cuò)誤信息,使用命令:#error。 在這些編譯預(yù)處理中,應(yīng)用最多的
53、就是對(duì)宏的處理。 它允許程序員使用define定義并應(yīng)用宏名字書(shū)寫(xiě)C語(yǔ)言程序,同時(shí)也指示編譯器在正式編譯前通過(guò)宏替換,使程序能按照C語(yǔ)言的語(yǔ)法進(jìn)行編譯。,一、字符串宏定義及其基本格式 define命令最簡(jiǎn)單的應(yīng)用就是定義一個(gè)符號(hào)常量。 格式為: define 宏名 字符串 編譯預(yù)處理時(shí),預(yù)處理程序?qū)殉绦蛭募性谠摵甓x之后的所有宏名,用#define命令中定義的字符串(稱為宏體)替換,這個(gè)過(guò)程稱為宏替換。 符號(hào)常數(shù)的定義就是這種宏定義的一種應(yīng)用。 #define PI 3.14159265 #define RADIUS 2.0,使用宏定義的好處是: (1) 提高了程序的可讀性。 如果人們看到
54、以下語(yǔ)句 return (2.0*3.1415926536*2.0); 和 return (3.1415926536*2.0*2.0); 是否能很快地看出它們?cè)谟?jì)算什么呢?顯然不能。 如果寫(xiě)成下面的形式: return (2.0*PI*RADIUS); 和 return (PI*RADIUS*RADIUS); 可以看出:這是在計(jì)算圓周長(zhǎng)和圓面積。 使用宏定義可以提高可理解性。,(2) 易修改性好。 如要將RADIUS的值由2.0修改為3.0,只要在define命令中修改一處便可。 而在不使用宏定義的文件中,要將3處的2.0修改為3.0,而且很可能也錯(cuò)把前一個(gè)返回語(yǔ)句也修改成 return (3
55、.0*3.1415926536*3.0);,(3) 宏定義可以給程序設(shè)計(jì)帶來(lái)許多方便。,二、使用宏需注意的問(wèn)題 (1)在#define命令中,宏名字與字符串(宏體)之間用一個(gè)或多個(gè)空格分隔。 (2)宏名字的使用 宏名字不能用引號(hào)括起來(lái)。 如:#define YES 1 printf(YES); 將不進(jìn)行宏定義。,宏名中不能含有空格。 例如想用“A NAME”定義“SMISS”,而寫(xiě)成: #define A NAME SMISS 則實(shí)際進(jìn)行的宏定義是A為宏名字,宏體是“NAME SMISS”。 C程序員一般都習(xí)慣用大寫(xiě)字母定義宏名字。這樣的表示方法使宏名與變量名有明顯的區(qū)別,以避免混淆。此外有助
56、于快速識(shí)別要發(fā)生宏替換的位置,提高程序的可讀性。 不能進(jìn)行宏名字的重定義。,(3)定義一個(gè)宏名字以后,就可以在后面使用這個(gè)宏名字了,包括在后面的宏定義中使用。 例如求圓的周長(zhǎng)和面積的程序可以改寫(xiě)為 #include #define PI 3.1415926 #define R 1.0 #define CIRCUM 2.0*PI*R /* 使用了前面定義的R和PI */,#define AREAPI*R*R int main(void) printf(“The circum is %f and area is %fn”,CIRCUM,AREA); ,/*下面是另外一種形式的宏定義: */ #in
57、clude #define PI 3.14159265 #define RADIUS 1.0 #define CIRCUM return(2.0*PI* RADIUS); /*分號(hào)是return語(yǔ)句的一部分 */ #define AREA return(PI* RADIUS* RADIUS); double circum( ) CIRCUM double area( ) AREA int main(void) printf(The circum is %f and area is %fn,circum(),area(); ,(4)不能進(jìn)行的宏替換。 不可以替換作為用戶標(biāo)識(shí)符中的成分。 例如在前
58、面的例子中,不可以用“R”替換“CIRCUM”中的“R”。 不能替換字符串常量中的成分。 舉例如下:,#include #define PI 3.14159265 #define RADIUS 1.0 #define CIRCUM return(2.0*PI* RADIUS); #define AREA return(PI* RADIUS* RADIUS); int main(void) printf(“The CIRCUM is %f ”, CIRCUM); printf(“ and AREA is %fn”, AREA ); 運(yùn)行結(jié)果為: The CIRCUM is 6.283185 and AREA is 3.141593不會(huì)用宏名字“CIRCUM”和“AREA”替換格式串“CIRCUM”和“AREA”。,(5)一行中寫(xiě)不下的宏定義,應(yīng)在前一行結(jié)
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026年蘭州成功學(xué)校高三年級(jí)輔導(dǎo)教師招聘筆試備考題庫(kù)及答案解析
- 2026年吉林省吉勤服務(wù)集團(tuán)有限責(zé)任公司社會(huì)化公開(kāi)招聘(29人)考試備考題庫(kù)及答案解析
- 2026年河北承德市承德縣公開(kāi)招聘消防設(shè)施操作員8名考試備考試題及答案解析
- 2026年蘭州新區(qū)石化產(chǎn)業(yè)投資集團(tuán)有限公司急需緊缺人員招聘112人筆試備考題庫(kù)及答案解析
- 2026銅川市新區(qū)文家中學(xué)教師招聘考試備考試題及答案解析
- 2026中國(guó)農(nóng)業(yè)科學(xué)院第一批招聘359人考試備考試題及答案解析
- 2026年昆明市五華區(qū)普吉街道社區(qū)衛(wèi)生服務(wù)中心招聘非事業(yè)編制工作人員(1人)考試備考題庫(kù)及答案解析
- 2026年國(guó)家海洋環(huán)境監(jiān)測(cè)中心面向社會(huì)公開(kāi)招聘工作人員14人考試備考題庫(kù)及答案解析
- 2026重慶現(xiàn)代制造職業(yè)學(xué)院招聘考試參考試題及答案解析
- 2026年平安銀行西安分行實(shí)習(xí)生招募筆試模擬試題及答案解析
- 國(guó)家開(kāi)放大學(xué)最新《監(jiān)督學(xué)》形考任務(wù)(1-4)試題解析和答案
- 天然氣輸氣管線陰極保護(hù)施工方案
- 高血壓?jiǎn)柧碚{(diào)查表
- QC成果提高花崗巖磚鋪裝質(zhì)量
- GB/T 25156-2010橡膠塑料注射成型機(jī)通用技術(shù)條件
- GB/T 25085.3-2020道路車輛汽車電纜第3部分:交流30 V或直流60 V單芯銅導(dǎo)體電纜的尺寸和要求
- GB/T 242-2007金屬管擴(kuò)口試驗(yàn)方法
- GB/T 21776-2008粉末涂料及其涂層的檢測(cè)標(biāo)準(zhǔn)指南
- 第六單元作文素材:批判與觀察 高一語(yǔ)文作文 (統(tǒng)編版必修下冊(cè))
- 全新版尹定邦設(shè)計(jì)學(xué)概論1課件
- 水源點(diǎn)改遷工程
評(píng)論
0/150
提交評(píng)論