C語(yǔ)言程序設(shè)計(jì) 課件 梁偉 第5、6章 數(shù)組、函數(shù)_第1頁(yè)
C語(yǔ)言程序設(shè)計(jì) 課件 梁偉 第5、6章 數(shù)組、函數(shù)_第2頁(yè)
C語(yǔ)言程序設(shè)計(jì) 課件 梁偉 第5、6章 數(shù)組、函數(shù)_第3頁(yè)
C語(yǔ)言程序設(shè)計(jì) 課件 梁偉 第5、6章 數(shù)組、函數(shù)_第4頁(yè)
C語(yǔ)言程序設(shè)計(jì) 課件 梁偉 第5、6章 數(shù)組、函數(shù)_第5頁(yè)
已閱讀5頁(yè),還剩152頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

第5章數(shù)組5.1一維數(shù)組5.2二維數(shù)組與多維數(shù)組5.3字符數(shù)組5.4數(shù)組的綜合示例本章小結(jié)

C語(yǔ)言提供了多種數(shù)據(jù)類(lèi)型,除了前面介紹的整型、實(shí)型和字符型等基本數(shù)據(jù)類(lèi)型外,還有一些擴(kuò)展的數(shù)據(jù)類(lèi)型,如數(shù)組、指針、結(jié)構(gòu)等。由于它們是由基本數(shù)據(jù)類(lèi)型按一定規(guī)則組成的,所以被稱(chēng)為復(fù)合數(shù)據(jù)類(lèi)型或構(gòu)造數(shù)據(jù)類(lèi)型。

5.1一維數(shù)組

一維數(shù)組是最簡(jiǎn)單的數(shù)組,數(shù)組元素只有一個(gè)下標(biāo)。5.1.1一維數(shù)組的定義及引用1.一維數(shù)組的定義在C語(yǔ)言中,與變量的定義一樣,數(shù)組也遵循“先定義后使用”的原則。一維數(shù)組的定義格式為類(lèi)型說(shuō)明符數(shù)組名[常量表達(dá)式];

例如:

shortscore[8];

表示定義一個(gè)數(shù)組,數(shù)組名為score,共有8個(gè)元素,每個(gè)元素的數(shù)據(jù)類(lèi)型均為短整型。

當(dāng)定義了一個(gè)數(shù)組之后,C編譯程序會(huì)為所定義的數(shù)組在內(nèi)存中開(kāi)辟一串連續(xù)的存儲(chǔ)單元,本例定義的score數(shù)組在內(nèi)存中的排列如圖5-1所示。

圖5-1數(shù)組在內(nèi)存中的排列

在定義一維數(shù)組時(shí),應(yīng)注意以下幾點(diǎn):

(1)類(lèi)型說(shuō)明符用來(lái)說(shuō)明數(shù)組元素屬于何種數(shù)據(jù)類(lèi)型,如int、char、float或double等。

(2)數(shù)組名由用戶(hù)自定義,與變量名的命名一樣,遵循標(biāo)識(shí)符命名規(guī)則。

(3)數(shù)組名后必須用“方括號(hào)”括起常量表達(dá)式,不能用其他括號(hào)。

(4)常量表達(dá)式定義數(shù)組的長(zhǎng)度,表示數(shù)組的元素個(gè)數(shù)。

(5)常量表達(dá)式中一般包括整型常量、字符常量或符號(hào)常量,但不能包括實(shí)型(符號(hào))常量或字符串(符號(hào))常量。

(6)常量表達(dá)式中不能包括變量。

(7)數(shù)組元素的下標(biāo)從0開(kāi)始,上例定義的數(shù)組的8個(gè)元素分別是score[0]、score[1]、score[2]、score[3]、score[4]、score[5]、score[6]和score[7]。注意最大下標(biāo)是7而不是8。

(8)相同類(lèi)型的數(shù)組、變量可放在一起定義,中間用逗號(hào)隔開(kāi)。

2.一維數(shù)組的引用

C語(yǔ)言規(guī)定數(shù)組不能以整體形式參與各種運(yùn)算。參與各種運(yùn)算的只能是數(shù)組元素,即

在程序中不能一次引用整個(gè)數(shù)組而只能逐個(gè)引用數(shù)組元素。一維數(shù)組元素的引用形式為

數(shù)組名[下標(biāo)]

其中,下標(biāo)可以是整型常量、整型變量或整型表達(dá)式。

數(shù)組元素與普通變量的表現(xiàn)形式不同,但實(shí)質(zhì)是相同的,它也是一種變量。因此,一個(gè)數(shù)組元素可以像普通變量那樣參與賦值、算術(shù)運(yùn)算、輸入和輸出等操作。下面介紹一維數(shù)組的輸入、輸出操作,以便讀者熟練掌握一維數(shù)組元素的引用。

1)一維數(shù)組的輸入

我們可以在程序運(yùn)行期間用賦值語(yǔ)句或從鍵盤(pán)輸入語(yǔ)句scanf()為數(shù)組元素賦值。一般用一個(gè)循環(huán)語(yǔ)句來(lái)賦值。例如:

2)一維數(shù)組的輸出

一維數(shù)組的輸出是指用輸出語(yǔ)句printf()將數(shù)組的元素逐個(gè)輸出。例如:

從這些示例可以看出,數(shù)組元素是一種帶下標(biāo)的變量,它跟普通變量一樣參與賦值、輸入和輸出等操作。但是,絕對(duì)不能把“數(shù)組名”當(dāng)成變量一樣使用。例如,定義

inta[100];

intb[10]={1,2,3,4,5,6,7,8,9,10};

后,采用如下語(yǔ)句進(jìn)行數(shù)據(jù)輸入輸出操作:

scanf("%d",&a);

printf("%d",b);

則是錯(cuò)誤的,無(wú)法輸入或輸出整個(gè)數(shù)組。

例5-1從鍵盤(pán)輸入10個(gè)數(shù),將這10個(gè)數(shù)逆序輸出,然后求出這10個(gè)數(shù)的和并輸出。

5.1.2一維數(shù)組的初始化

數(shù)組的初始化是指在定義數(shù)組的同時(shí)為數(shù)組元素賦初始值。一維數(shù)組在定義時(shí)進(jìn)行初始化的格式為

類(lèi)型說(shuō)明符數(shù)組名[常量表達(dá)式]={值1,值2,…,值n};

其中,大括號(hào)中的各個(gè)值依次對(duì)應(yīng)數(shù)組中的各個(gè)元素。各個(gè)值之間用逗號(hào)隔開(kāi)。例如,數(shù)組定義及初始化語(yǔ)句為

intx[5]={1,2,3,4,5};

則有x[0]=1,x[1]=2,x[2]=3,x[3]=4,x[4]=5。

在初始化一維數(shù)組時(shí),應(yīng)注意以下幾點(diǎn):

(1)若“{}”中初值的個(gè)數(shù)小于數(shù)組元素個(gè)數(shù),則只有數(shù)組的前部分元素對(duì)應(yīng)獲得初值,后部分沒(méi)有獲得初值的元素則置相應(yīng)類(lèi)型的默認(rèn)值(如int型置整數(shù)0,char型置字符'\0',float型置實(shí)數(shù)0.000?000等)。例如,定義

intx[5]={1,2,3};

則有x[0]=1,x[1]=2,x[2]=3,x[3]=0,x[4]=0。

(2)若“{}”中初值的個(gè)數(shù)等于數(shù)組元素個(gè)數(shù),則在數(shù)組定義時(shí)可省略元素個(gè)數(shù),此時(shí)數(shù)組長(zhǎng)度由{}中值的個(gè)數(shù)來(lái)決定。例如,定義

intx[]={1,2,3,4,5};

就相當(dāng)于intx[5]={1,2,3,4,5}。

(3)若“{}”中初值的個(gè)數(shù)大于數(shù)組元素個(gè)數(shù),則編譯時(shí)會(huì)出現(xiàn)“toomanyinitializers”之類(lèi)的錯(cuò)誤,表示初值個(gè)數(shù)太多。例如,定義

intx[5]={1,2,3,4,5,6};

是不對(duì)的。因?yàn)槌踔祩€(gè)數(shù)6超過(guò)了定義的數(shù)組長(zhǎng)度5。

5.1.3一維數(shù)組的應(yīng)用

例5-2查找最大值。

解題思路第一個(gè)for語(yǔ)句逐個(gè)輸入10個(gè)數(shù)到數(shù)組a中。然后把a(bǔ)[0]送到max中。在第二個(gè)for語(yǔ)句中,將a[1]~a[9]逐個(gè)與max中的數(shù)進(jìn)行比較,若比max的值大,則把該數(shù)組元素送入max中,因此max的值在已比較過(guò)的數(shù)組元素中總是最大的。比較結(jié)束,輸出max的值。

例5-3從鍵盤(pán)上任意輸入10個(gè)整數(shù),要求按從小到大的順序顯示出來(lái)。排序的方法有很多種,本例采用冒泡法。

解題思路冒泡法的基本思想:通過(guò)將相鄰兩個(gè)數(shù)進(jìn)行比較和交換,使排序碼(數(shù)值)較小的數(shù)逐漸從底部移向頂部,排序碼較大的數(shù)逐漸從頂部移向底部。這就像水底的氣泡一樣逐漸向上冒,故而得名冒泡法。

由A[0]~A[n?-?1]組成的n個(gè)數(shù)據(jù),進(jìn)行冒泡排序的過(guò)程描述如下:

首先將相鄰的A[n?-?1]與A[n?-?2]進(jìn)行比較,如果A[n?-?1]的值小于A[n?-?2]的值,則交換兩者的位置,使較小的數(shù)上浮,較大的數(shù)下沉;接著比較A[n?-?2]與A[n?-?3],同樣使小的數(shù)上浮,大的數(shù)下沉;依次類(lèi)推,直到比較完A[1]和A[0]后,A[0]為具有最小排序碼(數(shù)值)的元素,此時(shí)第一趟排序結(jié)束。

然后在A[1]~A[n?-?1]區(qū)間內(nèi),進(jìn)行第二趟排序,使剩余元素中排序碼最小的元素上浮到A[1]。重復(fù)進(jìn)行n-1趟排序后,整個(gè)排序過(guò)程結(jié)束。

5.2二維數(shù)組與多維數(shù)組

前面介紹的一維數(shù)組,它的數(shù)組元素只有一個(gè)下標(biāo),說(shuō)明只用一個(gè)表示數(shù)組長(zhǎng)度的常量表達(dá)式即可。如果一維數(shù)組的每個(gè)元素本身也是一個(gè)一維數(shù)組,則形成了一個(gè)二維數(shù)組。這時(shí)就要用兩個(gè)下標(biāo)來(lái)表示它的每個(gè)數(shù)組元素。多維數(shù)組是指二維及以上的數(shù)組,通常被表示為數(shù)組的數(shù)組,即一個(gè)數(shù)組的元素是其他數(shù)組。

5.2.1二維數(shù)組的定義及引用

1.二維數(shù)組的定義

二維數(shù)組的定義格式為

類(lèi)型說(shuō)明符數(shù)組名[常量表達(dá)式1][常量表達(dá)式2];

例如:

inta[3][4];

定義了一個(gè)二維數(shù)組,數(shù)組名為a,數(shù)組元素有3行4列,每個(gè)數(shù)組元素都是一個(gè)整型數(shù)據(jù)。

在定義二維數(shù)組時(shí),應(yīng)注意以下幾點(diǎn):

(1)類(lèi)型說(shuō)明符、數(shù)組名及常量表達(dá)式的要求與一維數(shù)組的相同。

(2)常量表達(dá)式1和常量表達(dá)式2各在一個(gè)方括號(hào)內(nèi),例如,定義不能寫(xiě)成

inta[3,4];

(3)二維數(shù)組可以看成一種特殊的一維數(shù)組,其特殊之處就在于它的元素又是一個(gè)一維數(shù)組。例如,二維數(shù)組a[3][4]可以理解為它有3個(gè)元素a[0]、a[1]、a[2],每一個(gè)元素卻又是一個(gè)包含4個(gè)元素的一維數(shù)組,如圖5-2所示。

圖5-2二維數(shù)組a[3][4]的“組成”

(4)二維數(shù)組的元素在內(nèi)存中的存放順序?yàn)椤鞍葱写娣拧?,即先順序存放第一行的元素,再存放第二行的元素,依次?lèi)推,如圖5-3所示。從圖中可以看出,最右邊的下標(biāo)變化最快,最左邊的下標(biāo)變化最慢。這一特點(diǎn)也適用于二維以上的多維數(shù)組。圖5-3二維數(shù)組在內(nèi)存中的存放方式

2.二維數(shù)組的引用

二維數(shù)組元素的引用格式為

數(shù)組名[下標(biāo)1][下標(biāo)2]

5.2.2二維數(shù)組的初始化

二維數(shù)組的初始化跟一維數(shù)組初始化一樣,也有3種方法。

(1)在定義數(shù)組的同時(shí)為數(shù)組元素賦初值。

①按行對(duì)二維數(shù)組賦初值。例如:

inta[3][4]={{88,78,98,85},{86,92,76,71},{82,96,84,77}};

其初始化結(jié)果可用一個(gè)二維表表示,如圖5-4所示。這種賦初值方法比較直觀,即把內(nèi)層的第一個(gè)大括號(hào)內(nèi)的數(shù)據(jù)賦給第一行的元素,第二個(gè)大括號(hào)內(nèi)的數(shù)據(jù)賦給第二行的元素,依次類(lèi)推即可。圖5-4二維數(shù)組的初始化

也可以用這種方法只給數(shù)組中部分元素賦初值。例如:

inta[3][4]={{88}{0,0,76}};

其初始化結(jié)果可用一個(gè)二維表表示,如圖5-5所示。圖5-5二維數(shù)組的部分賦值

②把所有的數(shù)據(jù)寫(xiě)在一個(gè)花括號(hào)里,系統(tǒng)按數(shù)組的“按行存放”排列次序?qū)Ω鱾€(gè)元素賦初值。例如:

inta[3][4]={88,78,98,85,86,92,76,71,82,96,84,77};

其效果也如圖5-4所示。

③如果對(duì)全部元素賦初值,則在定義中可省略第一維的長(zhǎng)度,但第二維長(zhǎng)度不可省,例如:定義

inta[3][4]={88,78,98,85,86,92,76,71,82,96,84,77};

與定義

inta[][4]={88,78,98,85,86,92,76,71,82,96,84,77};

是等價(jià)的。這是因?yàn)橄到y(tǒng)編譯器可以根據(jù)數(shù)據(jù)總個(gè)數(shù)和列數(shù)來(lái)確定行數(shù),故行數(shù)可以缺省。

(2)在程序運(yùn)行時(shí),用賦值語(yǔ)句為數(shù)組元素賦值。例如:

for(i=0;i<100;i++)

for(j=0;j<200;j++)

a[i][j]=0; //常用于對(duì)所有的數(shù)組元素賦一個(gè)初始狀態(tài)值

(3)在程序運(yùn)行時(shí),用輸入語(yǔ)句為數(shù)組元素賦值。例如:

for(i=0;i<100;i++)

for(j=0;j<200;j++)

scanf("%d",&a[i][j]);

例5-4用二維數(shù)組保存3個(gè)班的英語(yǔ)成績(jī)(每個(gè)班20人),并求每個(gè)班的平均成績(jī)。

5.2.3二維數(shù)組的應(yīng)用

例5-5上三角矩陣是指主對(duì)角線(xiàn)以下的元素都為0的矩陣;主對(duì)角線(xiàn)為從矩陣的左上角至右下角的連線(xiàn)。試編寫(xiě)程序,判斷一個(gè)給定的方陣是否為上三角矩陣。

例5-6應(yīng)用數(shù)組構(gòu)造n為6的楊輝三角形,并輸出。楊輝三角形如圖5-6所示。圖5-6楊輝三角形

解題思路楊輝三角形是一種在數(shù)學(xué)中非常著名的三角形排列形式。它是一個(gè)用于表示二項(xiàng)式系數(shù)的數(shù)列。楊輝三角形的結(jié)構(gòu)特點(diǎn)和生成方式如下:

(1)楊輝三角形是一個(gè)下三角矩陣。

(2)第一行和第二行只有元素1。

(3)從第三行開(kāi)始,每行的第一個(gè)和最后一個(gè)元素都是1。

(4)對(duì)于中間的元素,它等于上一行中兩個(gè)相鄰元素之和。例如,第n行的第k個(gè)元素等于上一行的第k-1和第k個(gè)元素之和。

數(shù)學(xué)表達(dá)式是:C(n,k)?=?C(n?-?1,k?-?1)?+?C(n?-?1,k)。

5.2.4多維數(shù)組

二維數(shù)組實(shí)際上是一種最簡(jiǎn)單的多維數(shù)組。C語(yǔ)言允許使用高于二維的多維數(shù)組,如三維數(shù)組、四維數(shù)組甚至更高維數(shù)的數(shù)組,允許使用的數(shù)組的最大維數(shù)由不同的C編譯器

決定。在實(shí)際應(yīng)用中,經(jīng)常用到的是一維、二維和三維數(shù)組,四維以上的數(shù)組極少使用。

多維數(shù)組的定義格式為

類(lèi)型說(shuō)明符數(shù)組名[常量表達(dá)式1][常量表達(dá)式2]……[常量表達(dá)式n];

其中,維數(shù)由常量表達(dá)式的個(gè)數(shù)n來(lái)決定。若n為3,則是一個(gè)三維數(shù)組。例如:

floata[2][3][4];

定義了一個(gè)三維數(shù)組,它可以理解為,三維數(shù)組a包含2個(gè)二維數(shù)組(a[0]和a[1]),每個(gè)二維數(shù)組包含3個(gè)一維數(shù)組,而每個(gè)一維數(shù)組包含4個(gè)float型的數(shù)組元素(如a[0][0]包含a[0][0][0]、a[0][0][1]、a[0][0][2]和a[0][0][3]),如圖5-7所示。圖5-7三維數(shù)組a[2][3][4]的“組成”

a[2][3][4]在內(nèi)存中的存放順序,如圖5-8所示。圖5-8三維數(shù)組在內(nèi)存的存放順序

在多維數(shù)組中,引用數(shù)組元素時(shí)其下標(biāo)個(gè)數(shù)要與維數(shù)相等。由圖5-7可知,對(duì)于三維數(shù)組,引用數(shù)組元素時(shí)其下標(biāo)個(gè)數(shù)應(yīng)當(dāng)為3,形如a[i][j][k]。若下標(biāo)個(gè)數(shù)小于維數(shù),則不能代表數(shù)組元素,而只相當(dāng)于數(shù)組名,如a、a[i]和a[i][j]分別代表三維、二維和一維數(shù)組名。

引入多維數(shù)組可以使編程更為靈活,因?yàn)槎嗑S數(shù)組的每一維都可以根據(jù)實(shí)際情況的不同而賦予不同的含義,從而使多維數(shù)組能描述比較復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。

例5-7某年級(jí)共有4個(gè)班,每班各有30名學(xué)生,有6個(gè)科目的考試成績(jī)。求各班每個(gè)學(xué)生的平均成績(jī)并輸出。

5.3字符數(shù)組

在字符數(shù)組中,每個(gè)元素為一個(gè)字符。例如,用一個(gè)一維的字符數(shù)組來(lái)存放字符串“Iamastudent”,字符串中的字符是逐個(gè)被存放到數(shù)組元素中的。由于字符是以ASCII碼的形式存儲(chǔ),因此理解了數(shù)值數(shù)組后,字符數(shù)組也就很容易理解了。

5.3.1字符數(shù)組的定義及引用

1.字符數(shù)組的定義

用來(lái)存放字符型(char)數(shù)據(jù)的數(shù)組是字符數(shù)組。字符數(shù)組中的每一個(gè)元素都可以存放一個(gè)字符,因此一個(gè)字符數(shù)組不僅可以存放多個(gè)字符,也可存放字符串(字符串是含有結(jié)束標(biāo)志的字符數(shù)組)。因?yàn)樽址麛?shù)組在存放字符串時(shí),字符串末尾的結(jié)束符'\0'也一并存放,所以,一個(gè)字符串用一維數(shù)組來(lái)存放時(shí),數(shù)組元素個(gè)數(shù)一定要比字符數(shù)多一個(gè)。

例如:

charc[13]="Howareyou!";

定義了一個(gè)字符數(shù)組c,存放的字符串中字符數(shù)為12,考慮還有1個(gè)字符串結(jié)束符?'\0',因此定義的數(shù)組長(zhǎng)度不能少于13。

一維字符數(shù)組的定義格式如下:

char數(shù)組名[數(shù)組長(zhǎng)度];

例如:

charc[7];

定義了一個(gè)名為c的長(zhǎng)度為7的一維字符數(shù)組,c的每個(gè)元素可存儲(chǔ)一個(gè)字符,整個(gè)字符數(shù)組可存儲(chǔ)一個(gè)字符個(gè)數(shù)少于7的字符串。

二維字符數(shù)組的定義格式如下:

char數(shù)組名[行長(zhǎng)度][列長(zhǎng)度];

例如:

charstr[4][9];

定義了一個(gè)名為str的4行9列的二維字符數(shù)組,每行可存儲(chǔ)一個(gè)字符個(gè)數(shù)少于9的字符串,一共可存儲(chǔ)4個(gè)字符串。

二維字符數(shù)組元素存儲(chǔ)的順序與二維數(shù)值數(shù)組完全相同,在此不再贅述。

此外,也可用整型數(shù)組存儲(chǔ)字符串,但會(huì)有一半的存儲(chǔ)空間被浪費(fèi)。

2.字符數(shù)組元素的引用

字符數(shù)組可以與數(shù)值數(shù)組一樣,按元素引用和賦值,此時(shí)的下標(biāo)形式、取值范圍也與數(shù)值數(shù)組相同。

5.3.2字符數(shù)組的初始化

為字符數(shù)組元素指定初值,稱(chēng)為字符數(shù)組的初始化。字符數(shù)組的初始化也有兩種方法:

(1)在定義的同時(shí)給數(shù)組賦初值。若提供的初值(字符)個(gè)數(shù)大于數(shù)組長(zhǎng)度,則按語(yǔ)法錯(cuò)誤處理(如編譯時(shí)會(huì)出現(xiàn)諸如Error:Toomanyinitializersinfunctionmain之類(lèi)的錯(cuò)誤信息);若初值個(gè)數(shù)等于數(shù)組長(zhǎng)度,則數(shù)組長(zhǎng)度值可以省略不寫(xiě);若初值個(gè)數(shù)小于數(shù)組長(zhǎng)度,則只將這些初值字符賦給前面的數(shù)組元素,其余的元素自動(dòng)置為空字符(即?'\0')。

例如,定義:

charc[8]={'G','O','O','D'};

后,數(shù)組在內(nèi)存中的存放如圖5-9所示(圖中假設(shè)首地址為2000)。圖5-9數(shù)組在內(nèi)存中的存放

(2)用字符串常量對(duì)字符數(shù)組進(jìn)行初始化。例如:

例5-8請(qǐng)編寫(xiě)一個(gè)程序,其功能是:將一個(gè)數(shù)字字符串轉(zhuǎn)換為一個(gè)整數(shù)(不得調(diào)用C語(yǔ)言提供的將字符串轉(zhuǎn)換為整數(shù)的函數(shù))。例如,若輸入字符串"-1688",則程序要能把它轉(zhuǎn)換為整數(shù)值-1688并輸出。

5.3.3字符串

在前面我們提到了字符串常量。所謂字符串常量就是用雙引號(hào)括起來(lái)的一組字符。但實(shí)際上,字符串是一種字符型數(shù)組,并且這個(gè)數(shù)組的最后一個(gè)單元的值是?'\0'?。也就是說(shuō),字符串是一種以?'\0'?結(jié)尾的字符數(shù)組。這個(gè)結(jié)尾的字符?'\0'?唯一的作用就是標(biāo)識(shí)字符串的結(jié)束。比如,字符串常量?"china"?地內(nèi)存中的存放如圖5-10所示。圖5-10字符串在內(nèi)存中的存放

5.3.4字符數(shù)組和字符串的輸入與輸出

1.字符數(shù)組的輸入與輸出

1)用%c格式輸入/輸出

用%c格式輸入時(shí),每個(gè)字符都有效。

例5-9從鍵盤(pán)輸入一個(gè)學(xué)生姓名的全拼字母,并輸出。

例5-10用%s格式改寫(xiě)例5-9的程序。

例5-11輸入一個(gè)英文單詞,若字母為小寫(xiě),則將其轉(zhuǎn)換為大寫(xiě)字母并輸出。

2.字符串的輸入與輸出

1)字符串的輸入

除了可以通過(guò)初始化使字符數(shù)組各元素得到初值外,也可以使用getchar()函數(shù)、scanf()

函數(shù)或gets()函數(shù)輸入字符串(或字符數(shù)組)。

(1)逐個(gè)字符輸入。

(2)整個(gè)字符串一次輸入。

2)字符串的輸出

字符串(或字符數(shù)組)的輸出可以使用putchar()函數(shù)、printf()函數(shù)或puts()函數(shù)來(lái)實(shí)現(xiàn)。

(1)逐個(gè)字符輸出。

(2)整個(gè)字符串一次輸出。

5.3.5常用字符串處理函數(shù)

C語(yǔ)言提供了豐富的字符串操作函數(shù),除了上面介紹的用于字符串輸入輸出的gets()和puts()函數(shù)外,還有很多其他專(zhuān)門(mén)的字符串操作函數(shù),這些函數(shù)包含在頭文件“string.h”中。因此,若需使用這些函數(shù),應(yīng)在程序之前加上語(yǔ)句:

#include<string.h>

下面介紹幾種常用的字符串操作函數(shù),這里寫(xiě)出這些函數(shù)實(shí)現(xiàn)的參考程序作為字符串操作的例子。

1.strlen(字符數(shù)組)

strlen(字符數(shù)組)的功能是測(cè)試字符串的長(zhǎng)度。函數(shù)值為字符串的實(shí)際長(zhǎng)度,不包括結(jié)束符?'\0'。

2.strcpy(字符數(shù)組1,字符數(shù)組2)

strcpy(字符數(shù)組1,字符數(shù)組2)的功能是把字符數(shù)組2中的字符串復(fù)制到字符數(shù)組1中去(即給一個(gè)字符數(shù)組賦值)。例如:

chars1[8],s2[]="GOOD";

strcpy(s1,s2);

執(zhí)行后,s1數(shù)組的狀態(tài)如圖5-11所示。圖5-11s1數(shù)組的狀態(tài)

3.strcat(字符數(shù)組1,字符數(shù)組2)

strcat(字符數(shù)組1,字符數(shù)組2)的功能是把字符數(shù)組2中的字符串連接到字符數(shù)組1的字符串后面。

連接前后數(shù)組的狀態(tài)如圖5-12所示。

圖5-12連接前后的數(shù)組狀態(tài)

4.strcmp(字符數(shù)組1,字符數(shù)組2)

strcmp(字符數(shù)組1,字符數(shù)組2)的功能是對(duì)字符數(shù)組1中的字符串和字符數(shù)組2中的字符串進(jìn)行比較。比較規(guī)則為:按字符ASCII的大小自左至右逐個(gè)比較兩個(gè)字符串的字符,直到出現(xiàn)不同的字符或遇到?'\0'?為止。若全部字符相同,返回值為0;若字符串1>字符串2,則返回值為一個(gè)正數(shù);若字符串1<字符串2,則返回值為一個(gè)負(fù)數(shù)。

5.3.6字符數(shù)組的應(yīng)用

例5-12有3個(gè)字符串,要求找出其中“最大”者。

解題思路如果將兩個(gè)字符進(jìn)行比較,所謂“大”者是指字符的ASCII碼較大的那個(gè)字符。例如,字符?'a'大于字符?'A'。如果是字符串,則從第一個(gè)字符開(kāi)始一一進(jìn)行比較,如果第一個(gè)字符相同,就比較下一個(gè)字符,直到出現(xiàn)不同為止。如果字符串中都是英文字母,有一個(gè)簡(jiǎn)單的判定方法:按英文字典的順序,字典中位置在后的較大,例如?"girl">"boy","then"<"they"。

題目要求處理3個(gè)字符串,需要定義一個(gè)二維的字符數(shù)組(取名str),假定每個(gè)字符串不超過(guò)19個(gè)字符,則可定義二維字符數(shù)組的大小為3?×?20,即有3行20列,每一行可以容納20個(gè)字符(包括最后的結(jié)束符?'0')。可以把str[0]、str[1]、str[2]看作3個(gè)一維字符數(shù)組,它們各有20個(gè)元素?,F(xiàn)用gets()函數(shù)分別讀取3個(gè)字符串。經(jīng)過(guò)兩次比較,就可得到最大者,把它放在一維字符數(shù)組string中。為敘述方便,把str[0]、str[1]、str[2]分別簡(jiǎn)稱(chēng)為串0、串1、串2。

例5-13輸入一行字符,統(tǒng)計(jì)其中的單詞總數(shù),單詞之間用空格分隔開(kāi)

解題思路要統(tǒng)計(jì)輸入行中的單詞總數(shù),可以定義單詞為連續(xù)的非空格字符序列,并將連續(xù)的空格看作單詞的分隔符。程序中,首先讀取整行字符串,然后遍歷每個(gè)字符。為了區(qū)分新單詞的開(kāi)始,可使用兩個(gè)變量num和word。num(初始化為0)用來(lái)統(tǒng)計(jì)單詞的個(gè)數(shù),word(也初始化為0)作為標(biāo)志位,指示當(dāng)前是否在單詞內(nèi)。

遍歷字符串時(shí),若遇到空格,則將word置0,表示目前不在單詞中。若當(dāng)前字符不是空格并且word為0(表示上一個(gè)字符是空格或者是字符串的開(kāi)始),則將word置1,并將num增加1,因?yàn)檫@意味著遇到一個(gè)新單詞。如果當(dāng)前字符不是空格且word已經(jīng)為1,則繼續(xù)遍歷,因?yàn)檫@仍然是當(dāng)前單詞的一部分。遍歷到字符串的結(jié)尾則遍歷結(jié)束。最后,num變量就表示了輸入字符串中的單詞總數(shù)。

5.4數(shù)組的綜合示例

例5-14求任意兩個(gè)正整數(shù)(不超過(guò)8位)之間所有整數(shù)所包含的數(shù)字0~9出現(xiàn)的次數(shù)。解題思路因?yàn)檩斎氲膬蓚€(gè)整數(shù)均不超過(guò)八位數(shù),所以可以定義兩個(gè)長(zhǎng)整型變量來(lái)存儲(chǔ)。通過(guò)循環(huán)將每次得到的整型數(shù)用sprintf()函數(shù)將其轉(zhuǎn)換成8個(gè)字符的字符串并存放到字符數(shù)組str中,字符串不足8位時(shí)高位部分補(bǔ)空格字符,再對(duì)str中每個(gè)字符進(jìn)行統(tǒng)計(jì)。數(shù)字出現(xiàn)的次數(shù)可以定義一個(gè)長(zhǎng)整型數(shù)組count來(lái)表示,其大小為10,count[0]存放0出現(xiàn)的次數(shù),count[1]存放1出現(xiàn)的次數(shù),…,count[9]存放9出現(xiàn)的次數(shù)。

例5-15輸入一行字符,統(tǒng)計(jì)其中各個(gè)大寫(xiě)字母出現(xiàn)的次數(shù)。

解題思路定義一個(gè)擁有26個(gè)int類(lèi)型數(shù)組元素組成的一維數(shù)組num,用于存放26個(gè)大寫(xiě)字母出現(xiàn)的次數(shù),num[0]存放字母?'A'?的次數(shù),num[1]存放字母?'B'?的次數(shù),…,num[25]存放字母?'Z'?的次數(shù)。調(diào)用庫(kù)函數(shù)memset()將數(shù)組num清0。通過(guò)getchar()函數(shù)讀入當(dāng)前字符到ch變量中,如果是回車(chē)換行符?'\n',則循環(huán)結(jié)束,否則,判斷ch是否為大寫(xiě)字母,是則數(shù)組num中相應(yīng)數(shù)組元素num[ch-'A']加1。最后輸出統(tǒng)計(jì)結(jié)果。

例5-16幻方是一種古老的數(shù)字游戲,n階幻方就是把整數(shù)1?-?n2排成n?×?n的方陣,使得每行中的各元素之和,每列中各元素之和,以及兩條對(duì)角線(xiàn)上的元素之和都是同一個(gè)數(shù)S,S稱(chēng)為幻方的幻和。奇數(shù)階幻方的構(gòu)造方法很簡(jiǎn)單,圖5-13所示為一個(gè)三階幻方。圖5-13三階幻方

解題思路各數(shù)在方陣中的位置可以這樣確定。首先把1放在最上一行正中間的方格中。然后把下一個(gè)整數(shù)放置到右上方,如果到達(dá)最上一行,下一個(gè)整數(shù)放在最后一行,就好像它在第一行的上面。如果到達(dá)最右端,則下一個(gè)整數(shù)放在最左端,就好像它在最右一列的右側(cè)。當(dāng)?shù)竭_(dá)的方格中填上數(shù)值時(shí),下一個(gè)整數(shù)就放在剛填寫(xiě)上數(shù)碼的方格的正下方,照著三階幻方,從1至9走一下即可。

例5-17最“牛”的一條微信。如果26個(gè)英文字母A~Z或a~z(不區(qū)分大小寫(xiě))分別等于1~26,那么可以得到下面的計(jì)算結(jié)果。

例5-18用數(shù)字1,2,3,4,…,n?×?n這n2個(gè)數(shù)蛇形填充規(guī)模為n?×?n的方陣。蛇形填充方法為:對(duì)于每一條左下-右上的斜線(xiàn),從左上到右下依次編號(hào)0,1,…,2n?-?2;按編號(hào)從小到大的順序,將數(shù)字從小到大填入各條斜線(xiàn),其中編號(hào)為奇數(shù)的從左下向右上填寫(xiě),編號(hào)為偶數(shù)的從右上到左下填寫(xiě)。

輸入n,最后輸出n?×?n的蛇形矩陣。比如n?=?4時(shí),方陣填充為如下形式:

解題思路通過(guò)遍歷方陣的斜線(xiàn),可以用一個(gè)統(tǒng)一的方法填充整個(gè)方陣。方陣被分為上半部和下半部。在上半部,從左上角開(kāi)始,依次處理每一條從左下到右上的斜線(xiàn)。對(duì)于編號(hào)為偶數(shù)的斜線(xiàn)(從0開(kāi)始編號(hào)),從右上向左下填充數(shù)字;而對(duì)于編號(hào)為奇數(shù)的斜線(xiàn),從左下向右上填充。這一過(guò)程持續(xù)到達(dá)中線(xiàn)。當(dāng)在處理下半部時(shí),繼續(xù)遵循相同的規(guī)則,但起始點(diǎn)變?yōu)槊織l斜線(xiàn)的最左側(cè)或最下側(cè),直到填滿(mǎn)整個(gè)方陣。通過(guò)這種方式,能保證每個(gè)數(shù)字正確地按照蛇形規(guī)則填入相應(yīng)的位置。

本章小結(jié)

本章主要介紹了一維數(shù)組、二維數(shù)組與多維數(shù)組以及字符數(shù)組的概念和用法。一維數(shù)組是相同數(shù)據(jù)類(lèi)型元素的有序集合,二維數(shù)組是一維數(shù)組的數(shù)組,而多維數(shù)組則是二維數(shù)組的數(shù)組,以此類(lèi)推。字符數(shù)組是一種特殊的一維數(shù)組,用于存儲(chǔ)字符串。這些數(shù)組類(lèi)型在C語(yǔ)言中廣泛應(yīng)用于數(shù)據(jù)存儲(chǔ)和處理。通過(guò)學(xué)習(xí)數(shù)組,學(xué)習(xí)者可以理解如何使用數(shù)組來(lái)有效地組織和操作數(shù)據(jù),從而實(shí)現(xiàn)各種算法和數(shù)據(jù)結(jié)構(gòu)。第6章函數(shù)6.1函數(shù)定義和聲明6.2函數(shù)調(diào)用過(guò)程6.3函數(shù)的遞歸與嵌套調(diào)用6.4作用域與存儲(chǔ)類(lèi)型6.5函數(shù)與數(shù)組6.6函數(shù)的綜合示例本章小結(jié)

6.1函數(shù)定義和聲明

6.1.1函數(shù)定義的一般形式

函數(shù)定義的一般形式為函數(shù)類(lèi)型說(shuō)明函數(shù)名(形參說(shuō)明表){說(shuō)明部分;執(zhí)行部分;}

6.1.2函數(shù)定義的要點(diǎn)

1.函數(shù)類(lèi)型的說(shuō)明

如上所述,函數(shù)類(lèi)型指函數(shù)返回值的數(shù)據(jù)類(lèi)型。函數(shù)返回時(shí)可能得到0個(gè)數(shù)據(jù)、1個(gè)數(shù)據(jù)或多個(gè)數(shù)據(jù)。

1)函數(shù)無(wú)返回值

如果函數(shù)沒(méi)有返回值,則一般在定義函數(shù)時(shí)把函數(shù)類(lèi)型寫(xiě)為void。例如:

voidPRINT()

{

printf("Test\n");

}

2)函數(shù)有1個(gè)返回值

如果函數(shù)有1個(gè)返回值,則在被調(diào)用函數(shù)的函數(shù)體中有return語(yǔ)句。此時(shí)函數(shù)類(lèi)型的定義應(yīng)根據(jù)return語(yǔ)句后的表達(dá)式的數(shù)據(jù)類(lèi)型來(lái)定義。例如:

intmax(inta,intb)

{

returna>b?a:b;

}

3)函數(shù)有多個(gè)返回值

如果函數(shù)有多個(gè)返回值,則在被調(diào)函數(shù)的函數(shù)體中一般無(wú)return語(yǔ)句。多個(gè)值的返回是通過(guò)全局變量、數(shù)組或指針來(lái)實(shí)現(xiàn)的,這將在后面的章節(jié)中進(jìn)行介紹。

2.函數(shù)的命名

函數(shù)名是函數(shù)的標(biāo)識(shí),函數(shù)的命名規(guī)則與變量命名規(guī)則相同。通過(guò)引用函數(shù)名,可調(diào)用該函數(shù)。

3.形參表及形參的說(shuō)明

1)形式參數(shù)

在函數(shù)定義中寫(xiě)在圓括號(hào)中的參數(shù)稱(chēng)為形式參數(shù)(簡(jiǎn)稱(chēng)形參)。不帶形參的函數(shù)其形參表有兩種表現(xiàn)形式:一是形參表空著,二是在形參表中寫(xiě)上“void”以確定沒(méi)有形參。例如:

voidPRINT(void)

{

printf("Thisisaexample\n");

}

兩種表現(xiàn)形式的區(qū)別:若形參表空著,則在函數(shù)調(diào)用時(shí),給一個(gè)或多個(gè)實(shí)在參數(shù)(簡(jiǎn)稱(chēng)實(shí)參),編譯器不會(huì)提示有錯(cuò)誤或警告;若形參表中寫(xiě)“void”,在函數(shù)調(diào)用時(shí),給一個(gè)或多個(gè)實(shí)參,則編譯器會(huì)給出警告“warningC4087:'PRINT':declaredwith'void'parameterlist”。

有形參函數(shù)的形參表由一個(gè)或多個(gè)形參組成,各參數(shù)間用逗號(hào)分隔,且必須給出每個(gè)參數(shù)的數(shù)據(jù)類(lèi)型。

2)函數(shù)間利用參數(shù)傳遞數(shù)據(jù)

函數(shù)間通過(guò)參數(shù)傳遞數(shù)據(jù),是指將調(diào)用函數(shù)中的實(shí)參向被調(diào)用函數(shù)中的形參按從右向左順序依次傳遞。

實(shí)參向形參傳遞數(shù)據(jù)是指實(shí)參將值單向傳遞給形參,形參值的變化不傳遞給實(shí)參。其原因在于每次調(diào)用函數(shù),都必須給形參分配新的空間,而不是復(fù)用原來(lái)實(shí)參空間,

因此修改形參不會(huì)影響實(shí)參。

例如:

即實(shí)參a、b兩個(gè)變量的值沒(méi)有得到交換。這里用圖6-1來(lái)表示swap()函數(shù)調(diào)用開(kāi)始時(shí)和結(jié)束后各參數(shù)的值。

圖6-1swap函數(shù)調(diào)用過(guò)程中各參數(shù)的變化

5.主函數(shù)的定義

本書(shū)采用VisualC++2010Express作為集成開(kāi)發(fā)環(huán)境。對(duì)于main()函數(shù)的定義特進(jìn)行如下說(shuō)明:

(1)同樣的main()函數(shù)定義和源碼,源文件的擴(kuò)展名為“.c”時(shí)的編譯結(jié)果與擴(kuò)展名為“.cpp”時(shí)的編譯結(jié)果可能不同,建議擴(kuò)展名用“.c”,以確定采用C語(yǔ)言(而不是C++語(yǔ)言)的語(yǔ)法規(guī)則編譯程序。

(2)對(duì)于C語(yǔ)言主函數(shù)的定義,在C99中規(guī)定了如下兩種標(biāo)準(zhǔn)格式。

①?intmain(void)

②?intmain(intargc,char*argv[])

(3)?VisualC++2010Express主要是用于C++程序開(kāi)發(fā)的,對(duì)于C語(yǔ)言,兼容C89標(biāo)準(zhǔn),因此,本書(shū)有些C程序中的main()函數(shù)仍然定義成main(){……}這種簡(jiǎn)單的形式。

(4)雖然VisualC++2010Express允許voidmain()的定義,但也要少用。因?yàn)檫@種用法不符合C99標(biāo)準(zhǔn),很多編譯器不支持。

(5)?main()函數(shù)的返回值用于說(shuō)明程序的退出狀態(tài)。

綜上所述,我們可以得出如下結(jié)論:

(1)如果C程序單純只考慮能在VisualC++2010Express中編譯通過(guò),則主函數(shù)的定義形式幾乎不受限制,可以定義成main(){……}這種簡(jiǎn)單的形式,也可以定義成voidmain(){……}。

(2)如果C程序要考慮可移植性,則要遵循主流標(biāo)準(zhǔn)。調(diào)試C/C++程序,符合C99標(biāo)準(zhǔn)及C++98標(biāo)準(zhǔn)的主函數(shù)定義形式為

6.1.3函數(shù)的聲明

定義好的函數(shù)需要調(diào)用時(shí),一般應(yīng)在主調(diào)函數(shù)中對(duì)被調(diào)函數(shù)進(jìn)行聲明,即向編譯系統(tǒng)聲明將要調(diào)用此函數(shù),并將有關(guān)信息(如被調(diào)用函數(shù)名、函數(shù)類(lèi)型、形參的個(gè)數(shù)及類(lèi)型等)通知編譯系統(tǒng)。

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

函數(shù)類(lèi)型說(shuō)明函數(shù)名(形參及其類(lèi)型);

函數(shù)聲明又稱(chēng)為函數(shù)接口(Interface)或接口說(shuō)明,這種格式很像函數(shù)的定義,初學(xué)者很容易混淆。其實(shí),它們的區(qū)別是很明顯的:函數(shù)定義具有函數(shù)體,且在源程序中只能定義一次;函數(shù)聲明沒(méi)有函數(shù)體,且在不同的主調(diào)函數(shù)中可多次出現(xiàn)。

函數(shù)從來(lái)源上分,有系統(tǒng)庫(kù)函數(shù)和用戶(hù)自定義函數(shù)兩種。

對(duì)于庫(kù)函數(shù)的接口說(shuō)明,系統(tǒng)按功能不同組成相應(yīng)的頭文件,如所有數(shù)學(xué)函數(shù)接口說(shuō)明頭文件為“math.h”,標(biāo)準(zhǔn)輸入/輸出庫(kù)函數(shù)接口說(shuō)明頭文件為“stdio.h”。如果調(diào)用系統(tǒng)庫(kù)函數(shù),必須用預(yù)編譯命令“#include”把相應(yīng)的頭文件包含在源程序的首部,之后就不必再進(jìn)行接口說(shuō)明了。例如,在某函數(shù)中調(diào)用數(shù)學(xué)函數(shù)sqrt(),則在源程序的開(kāi)頭加命令:

#include<math.h>

對(duì)于用戶(hù)自定義函數(shù),若被調(diào)函數(shù)定義在主調(diào)函數(shù)之前,可缺省函數(shù)接口聲明;若被調(diào)函數(shù)定義在主調(diào)函數(shù)之后,則一定要進(jìn)行函數(shù)接口聲明。

6.2函數(shù)調(diào)用過(guò)程6.2.1函數(shù)調(diào)用的一般形式一個(gè)C程序是由一個(gè)或多個(gè)獨(dú)立的函數(shù)組成的,在一個(gè)函數(shù)中引用另一個(gè)函數(shù),稱(chēng)為函數(shù)的調(diào)用。其中引用另一個(gè)函數(shù)的函數(shù),稱(chēng)為主調(diào)函數(shù),被引用的函數(shù),稱(chēng)為被調(diào)用函數(shù)。主調(diào)函數(shù)中的參數(shù),稱(chēng)為實(shí)在參數(shù),而被調(diào)用函數(shù)中的參數(shù)稱(chēng)為形式參數(shù)。一般地,主函數(shù)main()只能被操作系統(tǒng)調(diào)用,不能被其他函數(shù)調(diào)用;主函數(shù)main()可以調(diào)用庫(kù)函數(shù)或其他函數(shù);除主函數(shù)main()外,其他函數(shù)之間可以互相調(diào)用。

在一個(gè)程序中,通過(guò)函數(shù)調(diào)用將各函數(shù)聯(lián)系在一起,程序總是從main()函數(shù)開(kāi)始執(zhí)行并調(diào)用所需要的函數(shù),完成所調(diào)用函數(shù)的功能后,返回到main()函數(shù)繼續(xù)執(zhí)行,最后當(dāng)main()函數(shù)執(zhí)行完畢,整個(gè)程序運(yùn)行結(jié)束。假設(shè)有main()函數(shù)和fun()函數(shù),它們的調(diào)用過(guò)程如圖6-2所示。圖6-2函數(shù)調(diào)用執(zhí)行過(guò)程示意圖

一般函數(shù)的調(diào)用執(zhí)行過(guò)程歸納如下:

(1)為被調(diào)用函數(shù)的所有形式參數(shù)分配內(nèi)存,并將實(shí)在參數(shù)的值,按從右向左的方式一一對(duì)應(yīng)地賦給相應(yīng)的形式參數(shù)(對(duì)于無(wú)參函數(shù),不做此工作)。

(2)程序控制由主調(diào)函數(shù)進(jìn)入被調(diào)函數(shù)的函數(shù)體,之后依次執(zhí)行被調(diào)用函數(shù)中變量定義部分,為局部變量分配存儲(chǔ)空間,執(zhí)行函數(shù)體中的可執(zhí)行語(yǔ)句。

(3)當(dāng)執(zhí)行到“return”語(yǔ)句時(shí),計(jì)算返回值(如果是無(wú)返回值的函數(shù),不做這項(xiàng)工作),之后釋放本函數(shù)中定義的局部變量和形式參數(shù)所占用的存儲(chǔ)空間(對(duì)于static類(lèi)型變量,其空間不釋放),最后返回主調(diào)函數(shù)繼續(xù)執(zhí)行其他語(yǔ)句。

例6-4從鍵盤(pán)輸入兩個(gè)整數(shù),求較大的整數(shù)。

程序執(zhí)行的簡(jiǎn)單過(guò)程如下:①程序從main()函數(shù)開(kāi)始執(zhí)行,當(dāng)執(zhí)行到main()函數(shù)體第三行“c=max(a,b);”時(shí),調(diào)用max()函數(shù),把實(shí)在參數(shù)b、a的值傳遞給函數(shù)max()的形式參數(shù)y、x,并在主函數(shù)的該處設(shè)置函數(shù)斷點(diǎn),然后系統(tǒng)轉(zhuǎn)去執(zhí)行函數(shù)max()的函數(shù)體;②max()函數(shù)比較由主函數(shù)傳遞來(lái)的兩個(gè)整數(shù),然后執(zhí)行return語(yǔ)句返回到主調(diào)函數(shù)的斷點(diǎn)處,并將函數(shù)的返回值也傳送給主調(diào)函數(shù);③main()函數(shù)將max()函數(shù)的返回值賦給主調(diào)函數(shù)的內(nèi)部變量c,程序繼續(xù)往下執(zhí)行,輸出較大數(shù),此時(shí)主函數(shù)執(zhí)行完畢,整個(gè)程序運(yùn)行結(jié)束。

6.2.2函數(shù)調(diào)用的參數(shù)傳遞

對(duì)帶有參數(shù)的函數(shù)進(jìn)行調(diào)用時(shí),存在著如何將實(shí)參傳遞給形參的問(wèn)題。根據(jù)實(shí)參傳遞給形參值的不同,參數(shù)傳遞通常有值傳遞方式和地址傳遞方式兩種。

1.值傳遞方式

所謂值傳遞方式是指函數(shù)調(diào)用時(shí),為形參分配內(nèi)存單元,并將實(shí)參的值復(fù)制到形參中,當(dāng)調(diào)用結(jié)束后,形參所占內(nèi)存單元被釋放,實(shí)參的內(nèi)存單元仍保留并維持原值。

例6-5函數(shù)參數(shù)的值傳遞方式示例。

該程序首先在main()函數(shù)中定義了兩個(gè)整型變量x和y,其初始值分別為7和11,然后調(diào)用swap()自定義函數(shù)試圖交換x、y的值,可結(jié)果是,調(diào)用函數(shù)swap()以后,x和y的值并沒(méi)有交換,x仍然是7,y仍然是11。為什么會(huì)出現(xiàn)這種情況呢?

這是因?yàn)閷?shí)參x和y對(duì)應(yīng)的內(nèi)存單元與形參a和b所對(duì)應(yīng)的內(nèi)存單元是各不相同的,在函數(shù)調(diào)用時(shí),只是將x的值7傳遞給形參a,y的值11傳遞給形參b,在swap()函數(shù)體內(nèi)只是將a和b的值交換了,即a的值變?yōu)?1,b的值變?yōu)?,當(dāng)函數(shù)返回時(shí),a和b的內(nèi)存單元就釋放了,x和y所對(duì)應(yīng)的內(nèi)存單元并沒(méi)有進(jìn)行任何的改變。這就好像是我復(fù)印一份文件給你,在你的文件上修改都不會(huì)改變我的文件一樣。該程序函數(shù)參數(shù)調(diào)用的過(guò)程如圖6-3所示。圖6-3函數(shù)參數(shù)值傳遞方式示意圖

2.地址傳遞方式

所謂地址傳遞方式是指,函數(shù)調(diào)用時(shí)將實(shí)參數(shù)據(jù)的存儲(chǔ)地址作為參數(shù)傳遞給形參。其特點(diǎn)是形參與實(shí)參占用同樣的內(nèi)存單元,函數(shù)中對(duì)形參值的改變也會(huì)改變實(shí)參的值。因此函數(shù)參數(shù)的地址傳遞方式可實(shí)現(xiàn)調(diào)用函數(shù)與被調(diào)函數(shù)之間的雙向數(shù)據(jù)傳遞。注意,實(shí)參和形參必須是地址常量或變量。

6.3函數(shù)的遞歸與嵌套調(diào)用

6.3.1函數(shù)的遞歸調(diào)用C語(yǔ)言中除允許一個(gè)函數(shù)調(diào)用其他函數(shù)外,還允許函數(shù)自己調(diào)用自己,這種函數(shù)稱(chēng)為遞歸函數(shù)。

1.遞歸概念

函數(shù)的遞歸調(diào)用是指一個(gè)函數(shù)在它的函數(shù)體內(nèi)直接或間接地調(diào)用它自身。因此,遞歸調(diào)用有兩種方式:直接遞歸和間接遞歸。直接遞歸指的是函數(shù)直接調(diào)用自身的過(guò)程,如圖6-4(a)所示;間接遞歸指的是一個(gè)函數(shù)通過(guò)其他函數(shù)調(diào)用自身的過(guò)程,如圖6-4(b)所示,函數(shù)1調(diào)用函數(shù)2,函數(shù)2又調(diào)用函數(shù)1。

圖6-4兩種遞歸調(diào)用示意圖

例如:

fact(intn) /*fact函數(shù)定義*/

{

t=n*fact(n-1);

}

上述函數(shù)fact()中,函數(shù)fact()又要調(diào)用函數(shù)本身,它是直接遞歸。而遞歸函數(shù)怎么定義呢?以fact(n)=n!為例。因?yàn)?/p>

由①、②兩式可得fact(n)?=?n?×?fact(n?-?1)。假設(shè)想求fact(5)的值,則必須先求得fact(4)的值,同理想求fact(4)的值,則必須求fact(3)……,因而會(huì)無(wú)限地往下遞歸,程序無(wú)法得到終止。在調(diào)用過(guò)程中假設(shè)fact(1)=1,將值回代,則可得fact(2)的值,同理可得fact(3)、fact(4)的值,最后將其值回代得到fact(5)的值。因此,函數(shù)遞歸調(diào)用一定要有遞歸終止的條件,即當(dāng)傳遞過(guò)去某個(gè)值時(shí),函數(shù)值不再調(diào)用函數(shù)本身,而是一個(gè)確定值或過(guò)程。這也說(shuō)明,遞歸函數(shù)的定義應(yīng)包括兩部分:函數(shù)的遞歸關(guān)系和函數(shù)遞歸終止條件。

2.遞歸舉例

例6-6用遞歸法求fact(n)?=?n!。

計(jì)算階乘可用如下形式描述:

它的遞歸調(diào)用和值的回代過(guò)程(設(shè)n?=?5)如圖6-5所示。主函數(shù)對(duì)fact(5)進(jìn)行0級(jí)調(diào)用時(shí),n=5,不滿(mǎn)足n==1的條件,此時(shí)必須進(jìn)行1級(jí)調(diào)用,得到fact(4)的值后,才能得出“fact(5)=5*fact(4)”。同樣,計(jì)算fact(4)時(shí)需進(jìn)行2級(jí)調(diào)用,即調(diào)用fact(3)。計(jì)算fact(3)要進(jìn)行3級(jí)調(diào)用,即調(diào)用fact(2)。計(jì)算fact(2)需進(jìn)行4級(jí)調(diào)用,即調(diào)用fact(1),此時(shí)n=1,滿(mǎn)足條件n==1,得到p=1。返回p=1,即fact(1)返回至上層調(diào)用函數(shù)fact(2)處,得到“p=2*1=2”。

返回p=2,即fact(2)返回至上層調(diào)用函數(shù)fact(3)處,得到“p=3*2=6”。返回p=6,即fact(3)返回至上層調(diào)用函數(shù)fact(4)處,得到“p=4*6=24”。返回p=24,即fact(4)返回至上層調(diào)用函數(shù)fact(5)處,得到“p=5*24=120”。返回p=120,即fact(5)返回至上層調(diào)用函數(shù)main()處,輸出運(yùn)算結(jié)果。

圖6-5遞歸調(diào)用和值的回代

例6-8漢諾塔問(wèn)題。

有3個(gè)塔,每個(gè)都可以堆放若干個(gè)盤(pán)子。開(kāi)始時(shí),所有盤(pán)子均在塔A上,并且,盤(pán)從上到下,按直徑增大的次序放置(如圖6-6所示)。設(shè)計(jì)一個(gè)移動(dòng)盤(pán)子的程序,使得塔A上的所有盤(pán)子借助于塔B移到塔C上。這里有兩個(gè)限制條件:一是一次只能搬動(dòng)一個(gè)盤(pán)子,二是任何時(shí)候不能把大盤(pán)子放在比它小的盤(pán)子的上面。圖6-6漢諾塔問(wèn)題示意圖

解題思路要移動(dòng)這n個(gè)盤(pán)子,可以定義一個(gè)函數(shù):

move(n,a,b,c)

其中,字符型變量a、b、c分別表示A、B、C3個(gè)塔,函數(shù)move(n,a,b,c)表示將n個(gè)盤(pán)子從塔A(借助于塔B)移到塔C上。這個(gè)問(wèn)題可以使用遞歸調(diào)用方法解決,在n?>?0的前提下,函數(shù)move(n,a,b,c)通過(guò)下列3步實(shí)現(xiàn)移動(dòng)。

(1)調(diào)用move(n-1,a,c,b),即將n-1個(gè)盤(pán)子從塔A(借助于塔C)移到塔B上。目的是讓塔A上的第n個(gè)盤(pán)子(最下面的盤(pán)子)上無(wú)其他盤(pán)子。

(2)將底下的第n個(gè)盤(pán)子從A塔移到C塔。

(3)調(diào)用move(n-1,b,a,c),即將n?-?1個(gè)疊放在塔B上的盤(pán)子(借助于塔A)移到C塔。

6.3.2函數(shù)的嵌套調(diào)用

將孤立的函數(shù)堆砌在一起并不能建立關(guān)系,實(shí)現(xiàn)程序的功能。程序中的函數(shù)需要通過(guò)相互調(diào)用建立關(guān)系。C語(yǔ)言規(guī)定,在一個(gè)函數(shù)內(nèi)部不允許再定義函數(shù),即函數(shù)不可嵌套定義,但是允許一個(gè)函數(shù)調(diào)用另外一個(gè)函數(shù),這個(gè)被調(diào)用的函數(shù)還可以調(diào)用其他的函數(shù),以形成任意深度的調(diào)用層次。這就是函數(shù)的嵌套調(diào)用。圖6-7給出了函數(shù)嵌套調(diào)用的示意圖。

圖6-7函數(shù)嵌套調(diào)用的示意圖

例6-9計(jì)算s?=?22!?+?32!。

解題思路本題可編寫(xiě)兩個(gè)函數(shù),一個(gè)是用來(lái)計(jì)算平方值的函數(shù)f1,另一個(gè)是用來(lái)計(jì)算階乘值的函數(shù)f2。主函數(shù)先調(diào)f1計(jì)算出平方值,再在f1中以平方值為實(shí)參,調(diào)用f2計(jì)算其階乘值,之后返回f1,最后返回主函數(shù),在循環(huán)程序中計(jì)算累加和。

6.4作用域與存儲(chǔ)類(lèi)型

6.4.1作用域與生存期1.作用域所謂變量的作用域,就是指某個(gè)變量在其生存期內(nèi)可被使用的范圍。C語(yǔ)言中有兩種變量:一種變量只能在所定義的模塊內(nèi)部有效,稱(chēng)為局部變量或內(nèi)部變量;另一種變量從定義點(diǎn)開(kāi)始至整個(gè)源程序結(jié)束都有效,稱(chēng)為全局變量或外部變量。

1)局部變量

局部變量指在函數(shù)或復(fù)合語(yǔ)句中定義的變量,只在本函數(shù)或復(fù)合語(yǔ)句范圍內(nèi)有效(從定義點(diǎn)開(kāi)始到函數(shù)或復(fù)合語(yǔ)句結(jié)束),即只有在本函數(shù)或復(fù)合語(yǔ)句內(nèi)才能使用它們,在此函數(shù)或復(fù)合語(yǔ)句以外是不能使用它們。

注意:

(1)主函數(shù)中定義的變量也只在主函數(shù)中有效,而不因?yàn)槭窃谥骱瘮?shù)中定義的而在整個(gè)文件或程序中有效。主函數(shù)也不能使用其他函數(shù)中定義的變量。

(2)不同函數(shù)中可以使用相同名稱(chēng)的變量,它們代表不同的對(duì)象,互不干擾。例如,在f1函數(shù)中定義了變量b和c,倘若在f2函數(shù)中也定義變量b和c,它們?cè)趦?nèi)存中占不同的單元。

(3)形式參數(shù)也是局部變量。在函數(shù)中可以使用本函數(shù)聲明的形參,在函數(shù)外則不能引用。

(4)在一個(gè)函數(shù)內(nèi)部,可以在復(fù)合語(yǔ)句中定義變量,這些變量只在本復(fù)合語(yǔ)句中有效。

2)全局變量

局變量指在函數(shù)之外定義的變量。全局變量的有效范圍為從定義點(diǎn)開(kāi)始到本源程序結(jié)束。在此范圍內(nèi)它可以被本程序中所有函數(shù)所使用。在一個(gè)函數(shù)中既可以使用本函數(shù)中的局部變量,又可以使用有效的全局變量。

2.生存期

所謂變量的生存期,就是變量存活的周期。程序中的變量都要占用一定的內(nèi)存空間,但并不是所有的變量在程序開(kāi)始執(zhí)行時(shí)就占用內(nèi)存。為了節(jié)省內(nèi)存,避免變量互相干擾,不可能讓所有的變量始終存在,因此只有在必要時(shí)才為變量分配內(nèi)存。當(dāng)變量占用內(nèi)存時(shí),變量就生成了。當(dāng)變量不再有用時(shí),程序?qū)⑨尫抛兞克加玫膬?nèi)存,變量就撤銷(xiāo)了。變量從被生成到被撤銷(xiāo)的這段時(shí)間稱(chēng)為變量的生存期。它實(shí)際上就是變量占用內(nèi)存的時(shí)間。

6.4.2變量的存儲(chǔ)類(lèi)型

由變量的生存期可知,有的變量在程序運(yùn)行的整個(gè)過(guò)程都是存在的,而有的變量則是在調(diào)用其所在的函數(shù)時(shí)才臨時(shí)分配內(nèi)存單元,而在函數(shù)調(diào)用結(jié)束后就馬上釋放了,變量也不再存在了。因此變量的存儲(chǔ)有兩種情況:一是變量從定義點(diǎn)開(kāi)始就被分配內(nèi)存單元(即產(chǎn)生),直到程序運(yùn)行結(jié)束才釋放內(nèi)存,這種方式稱(chēng)為靜態(tài)存儲(chǔ)方式;二是變量帶有臨時(shí)性,隨調(diào)用的模塊(如文件、函數(shù)或復(fù)合語(yǔ)句)分配內(nèi)存單元,模塊調(diào)用結(jié)束,釋放內(nèi)存,這種方式稱(chēng)為動(dòng)態(tài)存儲(chǔ)方式。

全局變量采用靜態(tài)存儲(chǔ)方式,程序開(kāi)始執(zhí)行時(shí)給全局變量分配內(nèi)存空間,程序執(zhí)行完畢釋放。在程序執(zhí)行過(guò)程中它們占據(jù)固定的存儲(chǔ)單元,而不是動(dòng)態(tài)地進(jìn)行內(nèi)存分配和釋放。在函數(shù)中定義的變量,在函數(shù)調(diào)用開(kāi)始時(shí)分配動(dòng)態(tài)存儲(chǔ)空間,函數(shù)結(jié)束時(shí)釋放這些空間。在程序執(zhí)行過(guò)程中,這種分配和釋放是動(dòng)態(tài)的。

C語(yǔ)言中變量的定義有兩個(gè)屬性:一是定義變量的數(shù)據(jù)類(lèi)型;另一個(gè)是定義變量的存儲(chǔ)類(lèi)型。變量的數(shù)據(jù)類(lèi)型規(guī)定了變量的存儲(chǔ)空間大小和取值范圍,變量的存儲(chǔ)類(lèi)型規(guī)定了變量的生存期和作用域。因此,定義一個(gè)變量的一般形式為

[存儲(chǔ)類(lèi)型]數(shù)據(jù)類(lèi)型變量標(biāo)識(shí)符表;

其中[]內(nèi)為可選項(xiàng)。

不同存儲(chǔ)類(lèi)型的變量在計(jì)算機(jī)內(nèi)部的存放位置是不同的。不同的存放位置決定了變量的存儲(chǔ)類(lèi)型,這也就決定了變量的生存期和作用域。變量可以存放在內(nèi)存中的動(dòng)態(tài)數(shù)據(jù)存儲(chǔ)區(qū)或靜態(tài)數(shù)據(jù)存儲(chǔ)區(qū)中,也可以存儲(chǔ)在CPU的寄存器中。

變量的存儲(chǔ)類(lèi)型有4種,分別是自動(dòng)型、寄存器型、外部型和靜態(tài)型,其說(shuō)明符分別是auto、register、extern和static。下面結(jié)合程序示例,分別說(shuō)明它們各自的生存期和作用域。

1.自動(dòng)型(auto)

在各個(gè)函數(shù)或復(fù)合語(yǔ)句內(nèi)定義的變量,也稱(chēng)為自動(dòng)變量。自動(dòng)變量用關(guān)鍵字“auto”進(jìn)行標(biāo)識(shí),可缺省。

例如,在例6-4中的程序中,主函數(shù)main()的函數(shù)體中定義了3個(gè)自動(dòng)變量a、b、c;在max()函中定義了1個(gè)自動(dòng)變量z(形參也為自動(dòng)變量)。當(dāng)程序運(yùn)行main()函數(shù)時(shí),系統(tǒng)為a、b、c變量分別分配內(nèi)存單元;在調(diào)用max()函數(shù)時(shí),系統(tǒng)為max()函數(shù)的形參x、y和自動(dòng)變量z分配內(nèi)存單元,即生命開(kāi)始,調(diào)用結(jié)束釋放x、y、z的空間,即生命結(jié)束,其壽命為函數(shù)調(diào)用開(kāi)始到結(jié)束期間,稱(chēng)為局部壽命。x、y、z的使用也只能在max()函數(shù)內(nèi)部,這稱(chēng)為局部可用。

2.寄存器型(register)

如果有一些變量使用頻繁(例如,在一個(gè)函數(shù)中執(zhí)行1000000次循環(huán),每次循環(huán)中都要引用某局部變量),則要為存取該變量的值花不少時(shí)間。為提高執(zhí)行效率,C語(yǔ)言允許將局部變量的值放在CPU中的寄存器中,需要用時(shí)直接對(duì)寄存器讀寫(xiě)數(shù)據(jù)。存儲(chǔ)類(lèi)型為寄存器型的變量稱(chēng)為寄存器變量。由于CPU的通用寄存器數(shù)量有限,在程序中允許定義的寄存器變量一般以少于8個(gè)為宜。如果定義為寄存器變量的數(shù)目超過(guò)系統(tǒng)所提供的寄存器數(shù)目,編譯系統(tǒng)自動(dòng)將超出的變量設(shè)為自動(dòng)型存儲(chǔ)類(lèi)型。由于在計(jì)算機(jī)中對(duì)寄存器的讀寫(xiě)速度遠(yuǎn)遠(yuǎn)高于對(duì)內(nèi)存的讀寫(xiě)速度,因此這樣可以提高執(zhí)行效率。寄存器變量用關(guān)鍵字register聲明。

3.外部型(extern)

定義在所有函數(shù)(包括主函數(shù))外部的變量稱(chēng)為外部變量。外部變量是一種全局變量。

1)外部變量的特性

對(duì)于外部變量,系統(tǒng)在編譯時(shí)是將外部變量的內(nèi)存單元分配在數(shù)據(jù)存儲(chǔ)區(qū),在整個(gè)程序文件運(yùn)行結(jié)束后系統(tǒng)才收回其存儲(chǔ)單元。因此外部變量的作用域是從外部變量定義點(diǎn)開(kāi)始到源程序運(yùn)行結(jié)束,即外部變量的壽命是全局的。在定義點(diǎn)之后的所有函數(shù),都可以使用外部變量,也就是說(shuō)其作用域也是全局的。

例6-12求ax2?+?bx?+?c?=?0(a?≠?0)的根。

解題思路在a≠0的情況下。根據(jù)b2?-?4ac的不同值,方程分別有兩個(gè)不等的實(shí)根、兩個(gè)相等的實(shí)根和兩個(gè)共軛的虛根。如果傳遞方程的3個(gè)系數(shù)a、b、c給函數(shù),分別求出方程的根,則上述3種情況都需要返回兩個(gè)數(shù)據(jù),由于這里通過(guò)return語(yǔ)句無(wú)法實(shí)現(xiàn),因此可借用外部變量實(shí)現(xiàn)。

程序開(kāi)頭的語(yǔ)句“floatx1,x2;”定義的是兩個(gè)外部變量x1、x2,編譯時(shí)分配x1、x2的存儲(chǔ)空間,程序運(yùn)行期間其空間一直存在。在其后定義的f1()函數(shù)、f2()函數(shù)、f3()函數(shù)和main()函數(shù)都可以引用變量x1、x2,也就是說(shuō)在f1()函數(shù)、f2()函數(shù)、f3()函數(shù)中改寫(xiě)x1、x2值,就可以在main()函數(shù)中輸出對(duì)應(yīng)x1、x2值。這實(shí)現(xiàn)了不同函數(shù)之間的數(shù)據(jù)共享或通信。

2)外部變量的引用

外部變量的作用域是定義點(diǎn)開(kāi)始到源程序的結(jié)束。若在定義點(diǎn)之前或別的源程序中要引用外部變量,則在引用該變量之前,需進(jìn)行外部變量的引用說(shuō)明。

外部變量的引用說(shuō)明的一般形式為

extern外部變量數(shù)據(jù)類(lèi)型外部變量名表;

一個(gè)C程序可以由很多個(gè)程序文件組成,每個(gè)文件稱(chēng)為一個(gè)編譯單位。外部變量主要用于在多個(gè)編譯單位間傳遞數(shù)據(jù)。若兩個(gè)編譯單位A和B需要交換信息,可在編譯單位A中定義一個(gè)外部變量A,并把信息存放在其中,編譯單位B要引用該變量需把該變量說(shuō)明為外部型,告訴系統(tǒng)該變量在其他編譯單位中已經(jīng)定義了。

4.靜態(tài)型(static)

靜態(tài)變量是分配在內(nèi)存中的。它們?cè)诔绦蜷_(kāi)始運(yùn)行時(shí)就分配了固定的存儲(chǔ)單元,在程序運(yùn)行過(guò)程中不釋放,直到程序運(yùn)行結(jié)束才釋放它所占的存儲(chǔ)空間。如果用static說(shuō)明外部變量為靜態(tài)型,則該外部變量只能在本程序中使用。

1)靜態(tài)局部變量

靜態(tài)局部變量是定義在函數(shù)體的復(fù)合語(yǔ)句中,用關(guān)鍵字“static”進(jìn)行標(biāo)識(shí)的變量。靜態(tài)局部變量定義的一般形式為

static變量數(shù)據(jù)類(lèi)型變量名表;

對(duì)于靜態(tài)局部變量,系統(tǒng)在編譯時(shí)將其內(nèi)存單元分配在靜態(tài)數(shù)據(jù)存儲(chǔ)區(qū),直到程序運(yùn)行結(jié)束,對(duì)應(yīng)的內(nèi)存單元才釋放。靜態(tài)局部變量只有在編譯時(shí)可以賦初值,以后每次調(diào)用時(shí)不再分配內(nèi)存單元和初始化,只是引用上一次函數(shù)調(diào)用結(jié)束時(shí)的值。其作用域只限于其所定義的函數(shù)或復(fù)合語(yǔ)句中。因此靜態(tài)局部變量是一種具有全局壽命、局部可用的變量。

2)靜態(tài)全局變量

定義在所有函數(shù)(包括主函數(shù))之外,用關(guān)鍵字“static”標(biāo)識(shí)的變量,稱(chēng)為靜態(tài)全局變量。靜態(tài)全局變量和外部變量有共同點(diǎn):都具有全局壽命,即在整個(gè)程序運(yùn)行期間都存在。但二者在使用上有區(qū)別:靜態(tài)全局變量只能在所定義的文件中使用,具有對(duì)文件的局部可見(jiàn)性;而一般的外部變量可以在所有文件中使用。

6.5函數(shù)與數(shù)組

6.5.1函數(shù)和一維數(shù)組1.一維數(shù)組元素作為函數(shù)的實(shí)參由于數(shù)組元素與相同類(lèi)型的簡(jiǎn)單變量地位完全一樣,因此,數(shù)組元素作為函數(shù)參數(shù)也和簡(jiǎn)單變量一樣,采用值的單向傳遞方式。

例6-17

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 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ì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論