版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
1、第8章 結(jié)構(gòu)和聯(lián)合8.1 結(jié)構(gòu)的定義以及結(jié)構(gòu)變量的定義和使用8.2 結(jié)構(gòu)數(shù)組與結(jié)構(gòu)指針8.3 結(jié)構(gòu)在函數(shù)間的傳遞8.8 綜合舉例8.1 結(jié)構(gòu)的定義以及結(jié)構(gòu)變量的定義和使用 8.1.1 結(jié)構(gòu)的定義 結(jié)構(gòu)是由不同數(shù)據(jù)類型的數(shù)據(jù)組成的。組成結(jié)構(gòu)的每個(gè)數(shù)據(jù)稱為該結(jié)構(gòu)的成員項(xiàng),簡稱成員。在程序中使用結(jié)構(gòu)時(shí),首先要對結(jié)構(gòu)的組成進(jìn)行描述,這稱為結(jié)構(gòu)的定義。結(jié)構(gòu)定義的一般形式如下: struct 結(jié)構(gòu)名 數(shù)據(jù)類型 成員名1; 數(shù)據(jù)類型 成員名2; . 數(shù)據(jù)類型 成員名n; ;例如,為了處理雇員的數(shù)據(jù),在程序中可以定義如下的結(jié)構(gòu):struct Employee char name20; char sex; in
2、t old; int wage;該結(jié)構(gòu)名字是Employee,它由四個(gè)成員項(xiàng)組成。第一個(gè)成員項(xiàng)是字符型數(shù)據(jù)name ,它用于保存姓名字符串;第二個(gè)成員項(xiàng)是字符型數(shù)據(jù)sex,它用于保存性別字符;第三個(gè)成員項(xiàng)是int型整數(shù)old,它用于保存年齡數(shù)據(jù);最后一個(gè)成員項(xiàng)是int型整數(shù)wage,它用于工資數(shù)據(jù)。(1) 結(jié)構(gòu)的定義以關(guān)鍵字struct作為標(biāo)識(shí)符,其后是定義的結(jié)構(gòu)名,它們兩者形成了特定結(jié)構(gòu)的類型標(biāo)識(shí)符。結(jié)構(gòu)名由用戶命名,命名原則與變量名等相同。結(jié)構(gòu)名是這一組數(shù)據(jù)集合體的名字,可以像基本數(shù)據(jù)類型名一樣,用來說明具體的結(jié)構(gòu)變量。(2) 在結(jié)構(gòu)名下面的一對大括號(hào)中包圍的是組成該結(jié)構(gòu)的各個(gè)成員項(xiàng)。每個(gè)
3、成員項(xiàng)由其數(shù)據(jù)類型和成員名組成。每個(gè)成員項(xiàng)后用分號(hào)“;”作為結(jié)束符。整個(gè)結(jié)構(gòu)的定義也用分號(hào)作為結(jié)束符,注意不要忘記這個(gè)分號(hào)。(3)結(jié)構(gòu)的定義明確地描述了該結(jié)構(gòu)的組織形式。在程序執(zhí)行時(shí),結(jié)構(gòu)的定義并不引起系統(tǒng)為該結(jié)構(gòu)分配內(nèi)存空間。結(jié)構(gòu)的定義僅僅是定義了一種特定的數(shù)據(jù)構(gòu)造類型,它指定了這種構(gòu)造使用內(nèi)存的模式。在定義時(shí)沒有指明使用這種構(gòu)造具體對象(在結(jié)構(gòu)的說明時(shí)將指明這點(diǎn))。如上述結(jié)構(gòu)Employee的定義,僅僅指定了在使用這種結(jié)構(gòu)時(shí)應(yīng)該按下圖所示的配置情況占用內(nèi)存,但這時(shí)并沒有實(shí)際占用內(nèi)存空間。圖 結(jié)構(gòu)變量的定義 程序一旦定義了一個(gè)結(jié)構(gòu)體,就相當(dāng)于定義了一個(gè)新的結(jié)構(gòu)類型,那么就可
4、以把結(jié)構(gòu)名當(dāng)作像int、double等關(guān)鍵字一樣使用,用說明語句定義該形式結(jié)構(gòu)體的具體結(jié)構(gòu)變量,其格式為: struct 結(jié)構(gòu)名 結(jié)構(gòu)變量名; 結(jié)構(gòu)變量的定義在程序的數(shù)據(jù)說明部分給出。例如,下列說明: struct Employee wang;這個(gè)說明指出了結(jié)構(gòu)變量wang使用Employee結(jié)構(gòu),也就是說,結(jié)構(gòu)變量wang是由前述的Employee的四個(gè)成員項(xiàng)組成,每個(gè)成員項(xiàng)的類型和名字都與Employee結(jié)構(gòu)定義中給出的相同。(1) 結(jié)構(gòu)變量的定義將引起系統(tǒng)按照結(jié)構(gòu)定義時(shí)制定的內(nèi)存模式,為被定義的結(jié)構(gòu)變量分配一定的內(nèi)存空間。例如,上述結(jié)構(gòu)變量wang在內(nèi)存中將占據(jù)與圖8.1所示配置相同的內(nèi)
5、存空間。 當(dāng)多個(gè)結(jié)構(gòu)變量使用結(jié)構(gòu)時(shí),它們可以在一起定義。例如:struct Employee wang, li,zhang;被定義的三個(gè)結(jié)構(gòu)變量wang、li和zhang都具有Employee定義的結(jié)構(gòu)。 (2)結(jié)構(gòu)變量使用內(nèi)存空間,所以它們也具有一定的存儲(chǔ)類型。結(jié)構(gòu)變量的存儲(chǔ)類型概念、它的壽命、可見性及使用范圍與普通變量、數(shù)組完全一致。(3) 在程序中,結(jié)構(gòu)變量的定義在該結(jié)構(gòu)的定義之后,對于尚未定義的結(jié)構(gòu),不能用它對任何結(jié)構(gòu)進(jìn)行說明。(4)在一些簡單的程序設(shè)計(jì)中,結(jié)構(gòu)的定義和結(jié)構(gòu)變量的定義也可以同時(shí)進(jìn)行,在這種情況下,有時(shí)省略結(jié)構(gòu)名。這時(shí),被定義的結(jié)構(gòu)變量直接在結(jié)構(gòu)定義的大括號(hào)后給出,例如:
6、struct Employee char name20; char sex; int old; int wage;wang ,song ,zhou;這種形式與前面給出的結(jié)構(gòu)定義和結(jié)構(gòu)說明分開進(jìn)行時(shí)功能相同。 (5)一個(gè)結(jié)構(gòu)變量占用內(nèi)存的實(shí)際大小,可以利用sizeof運(yùn)算求出。sizeof運(yùn)算的功能是計(jì)算出給定的運(yùn)算量占用內(nèi)存空間的字節(jié)數(shù),它的運(yùn)算表達(dá)式一般形式如下: sizeof(運(yùn)算量)其中運(yùn)算量可以是變量、數(shù)組或結(jié)構(gòu)變量,也可以是數(shù)據(jù)類型的名稱,如int、double、struct Employee 等。8.1.3 結(jié)構(gòu)變量的使用形式和初始化 C提供了兩種類型的聚合數(shù)據(jù)類型:數(shù)組和結(jié)構(gòu)。數(shù)
7、組是相同類型的元素的集合,它的每個(gè)元素是通過下標(biāo)引用或指針間接訪問選擇的。但在結(jié)構(gòu)中情況并非如此,由于結(jié)構(gòu)的成員可能長度不同,所以不能使用下標(biāo)來訪問它們。相反,每個(gè)結(jié)構(gòu)成員都有自己的名字,它們是通過名字來訪問的。此外,在結(jié)構(gòu)說明的同時(shí)可以給各個(gè)成員項(xiàng)賦初值,即結(jié)構(gòu)的初始化。1、結(jié)構(gòu)的使用形式 結(jié)構(gòu)是不同數(shù)據(jù)類型的若干數(shù)據(jù)的集合體。在程序中使用結(jié)構(gòu)時(shí),一般情況下不能把結(jié)構(gòu)作為一整體參加數(shù)據(jù)處理,而參加各種運(yùn)算和操作的是結(jié)構(gòu)的各個(gè)成員項(xiàng)數(shù)據(jù)。結(jié)構(gòu)的成員項(xiàng)用以下一般形式表示: 結(jié)構(gòu)變量名.成員名 例如,上節(jié)給出的結(jié)構(gòu)變量wang具有下列四個(gè)成員項(xiàng): ,wang.sex,wang.o
8、ld, wang.wage 它們分別表示結(jié)構(gòu)變量wang的四個(gè)組成數(shù)據(jù)。 在指明結(jié)構(gòu)成員項(xiàng)時(shí)使用的“.”符號(hào)是C語言的一個(gè)運(yùn)算符,它規(guī)定的運(yùn)算是訪問結(jié)構(gòu)的成員。例如,wang.old實(shí)質(zhì)上是一個(gè)運(yùn)算表達(dá)式,它的運(yùn)算是訪問結(jié)構(gòu)wang的成員old。因此,它代表了結(jié)構(gòu)變量wang中名字為old的成員項(xiàng)。訪問成員運(yùn)算“.”是第一運(yùn)算優(yōu)先級(jí)中的一種運(yùn)算,它的結(jié)合規(guī)律是從左向右。明確這一點(diǎn),對于分析包括有訪問成員運(yùn)算的復(fù)雜運(yùn)算表達(dá)式中各種運(yùn)算的先后順序有很大幫助。 當(dāng)結(jié)構(gòu)的成員項(xiàng)是指針變量時(shí),要注意它的使用形式上的特點(diǎn)。例如:struct Employee1 char *name; char sex;
9、int old; int wage; zhou; 定義的Employee1結(jié)構(gòu)中的成員項(xiàng)name是一個(gè)char型指針。如果結(jié)構(gòu)變量zhou被說明為Employee1結(jié)構(gòu),則zhou的成員項(xiàng) 是一個(gè)char型指針。那么下面的使用形式 * 表示是該指針指向的目標(biāo)變量,它的意義可以從運(yùn)算表達(dá)式的角度進(jìn)分析。上述表達(dá)式中有兩種運(yùn)算:*(訪問目標(biāo))和(訪問成員)。運(yùn)算優(yōu)先于*運(yùn)算。所以,訪問成員運(yùn)算在先,而訪問目標(biāo)運(yùn)算在后。上面的表達(dá)式等價(jià)于: *()例8.1 結(jié)構(gòu)在程序中的使用形式#include struct Employee /結(jié)構(gòu)的定義 ch
10、ar *name; char sex; int old; char *tel; char *adr;void main() struct Employee wang,gao; /結(jié)構(gòu)變量的定 / 義 =“wang hai”; /結(jié)構(gòu)變量的成 /員賦值 wang.sex=M; wang.old=34; wang.tel= ; wang.adr=beijing; =gao yang; gao.sex=F; gao.old=42; gao.tel= ; gao.adr=shanghai; /顯示結(jié)構(gòu)變量的成員內(nèi)容 printf( name sex old tel a
11、ddressn ); printf( n); printf(%-14s%-4c%-4d%-10s%- 20sn,,wang.sex,wang.old, wang.tel,wang.adr); printf(%-14s%-4c%-4d%-10s%- 20sn,,gao.sex,gao.old, gao.tel,gao.adr); 運(yùn)行結(jié)果如下: name sex old tel adrwang hai m 34 beijinggao yang f 42 shanghai 在文件的開始部分定義結(jié)構(gòu)Employee,在函數(shù)main的說明部分說明了使用該結(jié)構(gòu)的兩個(gè)結(jié)構(gòu)
12、變量wang和gao。程序的執(zhí)行部分由數(shù)據(jù)賦值和輸出兩大部分組成。在賦值部分中可以清楚地看到每個(gè)成員項(xiàng)的使用形式和使用特性。例如,其中的賦值語句: =wang jun; 由于是一個(gè)char型指針變量,所以可以用一個(gè)字符串常量直接向它賦值。再者,從數(shù)據(jù)輸出中看出,輸出項(xiàng)對應(yīng)輸出轉(zhuǎn)換說明符是%s,所以輸出結(jié)果是指針?biāo)赶虻淖址?。由此可知,結(jié)構(gòu)的成員項(xiàng)無論其表示形式多么復(fù)雜,它的類型和使用特性最終落實(shí)到成員名上。例如,成員名name在Employee結(jié)構(gòu)定義時(shí)定義為char指針型,那么無論是、還是gao.na
13、me都是char指針型。它們在程序中使用時(shí),與使用一個(gè)普通的字符指針完全相同,視作一個(gè)整體。2、結(jié)構(gòu)的初始化 在結(jié)構(gòu)說明的同時(shí),可以給這個(gè)結(jié)構(gòu)的每個(gè)成員賦初值,這稱為結(jié)構(gòu)的初始化。結(jié)構(gòu)初始化的一般形式如下: struct 結(jié)構(gòu)名 結(jié)構(gòu)變量=初始數(shù)據(jù);其中大括號(hào)中包圍的初始數(shù)據(jù)之間用逗號(hào)分隔,初始數(shù)據(jù)的個(gè)數(shù)與結(jié)構(gòu)成員項(xiàng)的個(gè)數(shù)應(yīng)該相同,它們是按先后順序一一對應(yīng)賦值。此外,每個(gè)初始數(shù)據(jù)必須符合與其對應(yīng)的成員項(xiàng)的數(shù)據(jù)類型。例如,前述Employee結(jié)構(gòu)的結(jié)構(gòu)變量wang在說明時(shí)可以初始化如下:struct Employee wang=wang hai,M,34,123-1111,beijing;它所實(shí)
14、現(xiàn)的功能,與程序中下列賦值相同:=wang hai;wang.sex=M;wang.old=34;wang.tel= ;wang.adr=beijing;8.2 結(jié)構(gòu)數(shù)組與結(jié)構(gòu)指針8.2.1 結(jié)構(gòu)數(shù)組 在C語言中,具有相同數(shù)據(jù)類型的數(shù)據(jù)可以組成數(shù)組,指向相同類型的指針可以組成指針數(shù)組。根據(jù)同樣的原則,具有相同結(jié)構(gòu)的結(jié)構(gòu)也可以組成數(shù)組,稱它們?yōu)榻Y(jié)構(gòu)數(shù)組。結(jié)構(gòu)數(shù)組的每一個(gè)元素都是結(jié)構(gòu)變量。 結(jié)構(gòu)數(shù)組的說明形式如下: struct 結(jié)構(gòu)名 結(jié)構(gòu)數(shù)組名元素個(gè)數(shù) = 初值表 ;例如,struct Employee man3; 說明了結(jié)構(gòu)數(shù)組man ,它有三個(gè)元素man0、man1和ma
15、n2,它們都是具有Employee結(jié)構(gòu)的結(jié)構(gòu)變量。 結(jié)構(gòu)數(shù)組適合于處理由若干具有相同關(guān)系的數(shù)據(jù)組成的數(shù)據(jù)集合體。與數(shù)組一樣,在定義結(jié)構(gòu)數(shù)組的同時(shí)可以用初始化列表給它的每個(gè)元素賦初值。 在對結(jié)構(gòu)數(shù)組進(jìn)行初始化時(shí),方括號(hào) 中的元素個(gè)數(shù)可以缺省。 結(jié)構(gòu)數(shù)組也具有數(shù)組的屬性,結(jié)構(gòu)數(shù)組名是結(jié)構(gòu)數(shù)組存儲(chǔ)首地址,如例中的man表示該結(jié)構(gòu)數(shù)組存儲(chǔ)首地址。例8.2 結(jié)構(gòu)數(shù)組的使用#include #define STUDENT 3 /*用符號(hào)常量STUDENT表示學(xué)生人數(shù) struct Data /定義一個(gè)結(jié)構(gòu) char name20; / 姓名 short age; / 年齡 char adr30; / 地址
16、 long tel; / 電話號(hào)碼 ;void main( ) struct Data manSTUDENT = /*定義一個(gè)結(jié)構(gòu)數(shù)組并初始化 王偉, 20, 東八舍416室, 87543641, 李玲, 21, 南三舍219室, 87543945, 張利, 19, 東八舍419室, 87543645; int i; / 輸出顯示表頭提示信息 printf(“編號(hào)t姓名t年齡t地 址t電 話nn); /輸出結(jié)構(gòu)數(shù)組的數(shù)據(jù) for(i = 0; i STUDENT; i+) printf(% -dt%-st%-dt%-st%Ldn, i + 1, , mani.age, man
17、i.adr, mani.tel); / 每個(gè)輸出項(xiàng)都左對齊,編號(hào)從1開始 printf(n結(jié)構(gòu)類型Data的數(shù)據(jù)長度 : %d 字節(jié)。n, sizeof(struct Data);該程序的輸出結(jié)果為:編號(hào) 姓名 年齡 地 址 電 話1 王偉 20 東八舍416室 875436412 李玲 21 南三舍219室 875439453 張利 19 東八舍419室 87543645結(jié)構(gòu)類型Data的數(shù)據(jù)長度 : 56字節(jié)。例8.3:選舉,對候選人得票進(jìn)行統(tǒng)計(jì),設(shè)有4個(gè)候選人,N個(gè)人參加選舉,每次輸入一個(gè)得票的候選人的名字,要求最后輸出個(gè)人的得票結(jié)果。程序如下:#include #include #de
18、fine N 10 /宏定義,定義參加選舉人的個(gè)數(shù)struct person /結(jié)構(gòu)定義 char name20; int count;void main() /結(jié)構(gòu)數(shù)組定義及初始化 struct person leader4=wang,0,zhang,0,zhou,0, gao,0; char name20,i,j; /模擬選舉過程,循環(huán)一次代表一次選舉 for(i=0;iN;i+) gets(name); /從鍵盤輸入候選人的名字 for(j=0;j4;j+) /在候選人中查找匹配的人 if(strcmp(name,)=0) leaderj.count+; /被投票
19、的候選人的票數(shù)加1 break; printf(n); for(j=0;j4;j+) /輸出選舉結(jié)果 printf(%s:%dn,,leaderj.count); 該程序的運(yùn)行結(jié)果為:wangwangzhangzhangzhangzhangzhouzhougaogao /輸入wang:2zhang:4zhou:2gao:2 /輸出8.2.2 結(jié)構(gòu)指針 在C語言中對于結(jié)構(gòu)的數(shù)據(jù)可以使用指針進(jìn)行處理。我們把指向結(jié)構(gòu)的指針稱為結(jié)構(gòu)指針。 指向結(jié)構(gòu)的指針變量稱為結(jié)構(gòu)指針,它與其他各類指針在特性和使用方法上完全相同。結(jié)構(gòu)指針的運(yùn)算仍按地址計(jì)算規(guī)則進(jìn)行,其定義格式為: struct
20、 結(jié)構(gòu)名 * 結(jié)構(gòu)指針名 = 初始地址值 ; 其中結(jié)構(gòu)名必須是已經(jīng)定義過的結(jié)構(gòu)類型。例如: struct Employee * pman; struct Employee * pd; 存儲(chǔ)類型是結(jié)構(gòu)指針變量本身的存儲(chǔ)類型。編譯系統(tǒng)按指定的存儲(chǔ)類型為結(jié)構(gòu)指針pman和pd分配內(nèi)存空間。 由于結(jié)構(gòu)指針是指向整個(gè)結(jié)構(gòu)體而不是某個(gè)成員,因此結(jié)構(gòu)指針的增(減)量運(yùn)算,例如: “pman+;”將跳過一個(gè)結(jié)構(gòu)變量的整體,指向內(nèi)存中下一個(gè)結(jié)構(gòu)變量或結(jié)構(gòu)數(shù)組中下一個(gè)元素,結(jié)構(gòu)指針本身的(物理)地址增量值取決于它所指的結(jié)構(gòu)變量(或結(jié)構(gòu)類型)的數(shù)據(jù)長度。 結(jié)構(gòu)體可以嵌套,即結(jié)構(gòu)體成員又是一個(gè)結(jié)構(gòu)變量或結(jié)構(gòu)指針。例如
21、:struct student char name20; short age; char adr30; struct Date BirthDay; struct Date StudyDate; studt300;其中成員項(xiàng)BirthDay、StudyDate是具有Date結(jié)構(gòu)類型的結(jié)構(gòu)變量,稱student為外層結(jié)構(gòu)體,Date為內(nèi)層結(jié)構(gòu)體。 在結(jié)構(gòu)嵌套中,當(dāng)結(jié)構(gòu)體的成員項(xiàng)具有與該結(jié)構(gòu)體相同結(jié)構(gòu)類型的結(jié)構(gòu)變量或結(jié)構(gòu)指針時(shí),就形成了結(jié)構(gòu)體的自我嵌套。這種結(jié)構(gòu)體稱為遞歸結(jié)構(gòu)體。例如:struct Node int num; / 數(shù)據(jù)場,節(jié)點(diǎn)序號(hào) struct Node * next; / 指針場,
22、指向下一個(gè)節(jié)點(diǎn)的結(jié)構(gòu)指針 ;該結(jié)構(gòu)體中的成員項(xiàng)next是指向自身結(jié)構(gòu)類型Node的結(jié)構(gòu)指針,構(gòu)成了遞歸結(jié)構(gòu)體,鏈表、樹和有向圖等數(shù)據(jù)結(jié)構(gòu)中廣泛采用遞歸結(jié)構(gòu)體。 使用結(jié)構(gòu)指針對結(jié)構(gòu)成員進(jìn)行引用時(shí),有兩種形式:(1)使用運(yùn)算符“.”,這時(shí)指針指向結(jié)構(gòu)的成員項(xiàng)一般表示形式是: (*結(jié)構(gòu)指針名).成員名 由于成員選擇運(yùn)算符.的優(yōu)先級(jí)比取內(nèi)容運(yùn)算符*“高,所以需要使用圓括號(hào)。 在C語言程序中結(jié)構(gòu)指針使用相當(dāng)頻繁,所以C中提供了一種直觀的特殊運(yùn)算符:結(jié)構(gòu)指針運(yùn)算符“-”(橫線加大于號(hào))。在C語言程序中經(jīng)常采用下面的形式。(2)使用運(yùn)算符-“ 結(jié)構(gòu)指針名-成員名 它與前一種表示方法在意義上是完全等價(jià)的。例如
23、,前面給出的pman指向的結(jié)構(gòu)中的成員項(xiàng)old可以表示如下: pman-old在這種表示方法中,-(減號(hào)和大于號(hào))也是一種運(yùn)算符,它在第一運(yùn)算優(yōu)先級(jí)中。它表示的運(yùn)算意義是,訪問指針指向的結(jié)構(gòu)中的成員項(xiàng)。例8.4:結(jié)構(gòu)指針的使用#include struct Date /定義一個(gè)結(jié)構(gòu) int month; int day; int year;void main() struct Date today,*date_p; /定義一個(gè)結(jié)構(gòu)變量和結(jié)構(gòu)指針變量 date_p =&today; /將結(jié)構(gòu)指針指向一個(gè)結(jié)構(gòu)變量 date_p-month =4; /采用結(jié)構(gòu)指針給目標(biāo)變量賦值 date_p-day
24、 =15; date_p-year =1990; /采用結(jié)構(gòu)指針輸出目標(biāo)變量的數(shù)據(jù) printf(Today is %d/%d/%dn, date_p-month,date_p-day , date_p-year );程序運(yùn)行結(jié)果:Today is 4/15/1990例8.5:結(jié)構(gòu)指針運(yùn)算#include struct Key /定義一個(gè)結(jié)構(gòu)char *keyword;int keyno;void main() /定義一個(gè)結(jié)構(gòu)數(shù)組 struct Key kd=are,123,my,456,you,789; struct Key *p; /定義一個(gè)結(jié)構(gòu)指針變量 int a; char chr;
25、p=kd; /將結(jié)構(gòu)數(shù)組的首地址賦給結(jié)構(gòu)指針p a=p-keyno; printf(p=%d,a=%dn,p,a); a=+p-keyno; / 相當(dāng)于chr=+(p-keyno), /結(jié)構(gòu)指針無變化 printf(p=%d,a=%dn,p,a); /結(jié)構(gòu)指針指向結(jié)構(gòu)數(shù)組的下一個(gè)元素,結(jié)構(gòu)指針發(fā)生變 /化;給a賦值是指針變化后所指向目標(biāo)的成員數(shù)據(jù) a=(+p)-keyno; printf(p=%d,a=%dn,p,a); /給a賦值是指針變化前所指向目標(biāo)的成員數(shù)據(jù);結(jié)構(gòu)指 /針值發(fā)生變化,結(jié)構(gòu)指針指向結(jié)構(gòu)數(shù)組的下一個(gè)元素 a=(p+)-keyno; printf(p=%d,a=%dn,p,a)
26、; p=kd; /重新將結(jié)構(gòu)數(shù)組的首地址賦給結(jié)構(gòu)指針p chr=*p-keyword;/相當(dāng)于chr=*(p-keyword) printf(p=%d,chr=%c(adr=%d)n,p,chr,p-keyword); /相當(dāng)于chr=*(p-keyword)+,賦值之后,keyword指針發(fā) /生變化 chr=*p-keyword+; printf(p=%d,chr=%c(adr=%d)n,p,chr,p-keyword); /相當(dāng)于chr=(*(p-keyword))+,給chr賦值的是 /*(p-keyword),所以/r(前面keyword指針指向r); /賦值之后*(p-keywor
27、d)進(jìn)行加1變?yōu)閟 chr=(*p-keyword)+; printf(p=%d,chr=%c(adr=%d)n,p,chr,p-keyword); /給chr賦值是指針變化前所指向目標(biāo)的成員數(shù)據(jù),chr=s; /結(jié)構(gòu)指針值發(fā)生變化,結(jié)構(gòu)指針指向結(jié)構(gòu)數(shù)組的下一個(gè) /元素, chr=*p+-keyword; printf(p=%d,chr=%c(adr=%d)n,p,chr,p-keyword); /相當(dāng)于chr=*(+(p-keyword),結(jié)構(gòu)指針值無變化,將 /my中的y賦給chr chr=*+p-keyword; printf(p=%d,chr=%c(adr=%d)n,p,chr,p-k
28、eyword);程序運(yùn)行結(jié)果:p=158,a=123p=158,a=124p=162,a=456p=166,a=456p=158,chr=a(adr=170)p=158,chr=a(adr=171)p=158,chr=r(adr=171)p=162,chr=s(adr=174)p=162,chr=y(adr=175)注意輸出結(jié)果值中地址值每次運(yùn)行時(shí)可能有所不同,但地址的相對值不變。例8.6:指向結(jié)構(gòu)數(shù)組的指針的應(yīng)用#include struct student /定義一個(gè)結(jié)構(gòu) int No; char name20; char sex; int age;void main() /定義一個(gè)結(jié)構(gòu)數(shù)
29、組并初始化 struct student stu3= 10101,Li Lin,M,18, 10102,Zhang fan,M,19, 10104,Wang Min,F,20; /定義一個(gè)結(jié)構(gòu)指針變量 struct student *p; printf(No. Name Sex Agen); for( p=stu ; pNo,p-name,p-sex,p-age);程序運(yùn)行結(jié)果:No. Name Sex Age10101 Li Lin M 1810102 Zhang fan M 1910104 Wang Min F 208.3 結(jié)構(gòu)在函數(shù)間的傳遞 將一個(gè)結(jié)構(gòu)體變量的值傳遞給另一個(gè)函數(shù),有3種方
30、法:(1)用結(jié)構(gòu)體變量的成員作參數(shù),用法和用普通變量作實(shí)參是一樣的,屬于“值傳遞”方式。應(yīng)當(dāng)注意實(shí)參和形參的類型保持一致。由于結(jié)構(gòu)是不同數(shù)據(jù)類型的數(shù)據(jù)的集合體,采用這種方法,無實(shí)用價(jià)值,實(shí)際應(yīng)用時(shí),較少采用。(2)用結(jié)構(gòu)體變量作實(shí)參。ANSI C支持在調(diào)用函數(shù)時(shí),把結(jié)構(gòu)作為參數(shù)傳遞給函數(shù),采取的是“值傳遞”的方式,將結(jié)構(gòu)體變量所占的內(nèi)存單元的內(nèi)容全部順序傳遞給形參。形參也必須是同類型的結(jié)構(gòu)體變量。在函數(shù)調(diào)用期間,形參也要占用內(nèi)存單元。(3)用結(jié)構(gòu)變量的地址或結(jié)構(gòu)數(shù)組的首地址作為實(shí)參,用指向相同結(jié)構(gòu)類型的結(jié)構(gòu)指針作為函數(shù)的形參來接受該地址值。用結(jié)構(gòu)指針作為函數(shù)的形參與用指針變量作為形參在函數(shù)間傳
31、遞一樣,即采用地址傳遞方式,把結(jié)構(gòu)變量的存儲(chǔ)首地址或結(jié)構(gòu)數(shù)組名作為實(shí)參向函數(shù)傳遞,函數(shù)的形參是指向相同結(jié)構(gòu)類型的指針接收該地址值。例8.7, 采用值傳遞在函數(shù)間傳遞結(jié)構(gòu)變量,計(jì)算雇傭天數(shù)和工資。#include struct Date int day; int month; int year; int yearday; char mon_name4;int day_of_year(struct Date pd);void main( ) struct Date HireDate; float laborage; / 存放每天的雇傭工資 printf(請輸入每天的工資 : ); scanf(%f
32、, & laborage); printf(請輸入年份 : ); scanf(%d, & HireDate.year); printf(請輸入月份 : ); scanf(%d, & HireDate.month); printf(請輸入日 : ); scanf(%d, & HireDate.day); HireDate.yearday = day_of_year( HireDate); printf(從%d年元月1日到%d年%d月%d日的雇傭期限 : %d天,n應(yīng)付給你的工錢: %-.2f元。n, HireDate.year, HireDate.year,HireDate.month, Hir
33、eDate.day, HireDate.yearday, laborage * HireDate.yearday);/ 計(jì)算某年某月某日是這一年的第幾天int day_of_year(struct Date pd) int day_tab213 = 0,31,28,31,30,31,30,31,31,30,31,30,31, / 非閏年的每月 /天數(shù) 0,31,29,31,30,31,30,31,31,30,31,30,31; / 閏年的每月 天數(shù)/* 為了與月份一致,列號(hào)不使用為零的下標(biāo)號(hào)。行號(hào)為0是非閏年的每月天數(shù),為1是閏年的每月天數(shù) */ int i, day, leap; / lea
34、p為0是非閏年,為1是閏年 day = pd.day; / 將當(dāng)月的天數(shù)加入 leap = pd. year % 4 = 0 & / 能被4整除的年份基本上是閏年 pd. year % 100 != 0 | / 能被100整除的年份不是閏年 pd. year % 400 = 0; / 能被400整除的年份又是閏年 / 求從元月1日算起到這一天的累加天數(shù) for(i = 1 ; i pd .month ; i+) day += day_tableapi; return day;該程序的運(yùn)行結(jié)果為:請輸入每天的工資 : 38.5(CR)請輸入年份 : 2000(CR)請輸入月份 : 10(CR)請
35、輸入日 : 1(CR)從2000年元月1日到2000年10月1日的雇傭期限 : 275天,應(yīng)付給你的工錢 : 10587.50元。例8.8 通信錄的建立和顯示程序(采用地址方式傳遞結(jié)構(gòu)變量)#include #define MAX 3 /用符號(hào)常量MAX表示建立通信錄人數(shù)最 /大記錄數(shù)struct Address /定義一個(gè)通信錄的結(jié)構(gòu),包括姓名、地址 /和電話 char name20; char addr50; char tel15;int input(struct Address *pt); /通信錄錄入函數(shù)原型void display(struct Address *pt,int n);
36、 /通信錄顯示函數(shù)原型void main() struct Address manMAX; /定義一個(gè)結(jié)構(gòu)數(shù)組, /存放學(xué)生通信錄數(shù)據(jù) int i; for(i=0;iname); if(pt-name0=0)return 0; /輸入空字符串,停止錄 /入,返回0 printf(Address?); gets(pt-addr); printf(Telephone?); gets(pt-tel); return 1; /正常返回1 /*通信錄顯示函數(shù),顯示整個(gè)通信錄的數(shù)據(jù),*/void display(struct Address *pt,int n) int i; printf( name
37、address teln); printf(- -n); for(i=0 ; iname,pt-addr,pt-tel);該程序運(yùn)行結(jié)果為:Name?王偉Address?東八舍416室Telephone? 87543641Name?李玲Address?南三舍219室Telephone? 87543945Name?張利Address?東八舍419室Telephone?87543645 /輸入/以下為輸出name address tel-王偉 東八舍416室 87543641李玲 南三舍219室 87543945張利 東八舍419室 87543645說明: (1)該程序由三個(gè)函數(shù)組成,其中inpu
38、t( )函數(shù)用于以人機(jī)對話方式輸入數(shù)據(jù),它的形式參數(shù)pt是結(jié)構(gòu)指針,用來接收結(jié)構(gòu)地址。在main( )函數(shù)中調(diào)用input( )函數(shù)時(shí),實(shí)參數(shù)是&mani,它是結(jié)構(gòu)數(shù)組man 中的第i個(gè)結(jié)構(gòu)的地址。程序中看出,main( )的for循環(huán)中,通過i的遞增依次把man 中的各個(gè)結(jié)構(gòu)地址傳送到input( ),在input( )中給該結(jié)構(gòu)的各個(gè)成員項(xiàng)輸入數(shù)據(jù)。在輸入過程中,對name輸入零時(shí),整個(gè)輸入過程結(jié)束。(2)輸入數(shù)據(jù)后,調(diào)用display( )函數(shù)顯示輸入結(jié)果。在調(diào)用display( )時(shí),實(shí)參數(shù)是結(jié)構(gòu)數(shù)組man 的首地址,從而把整個(gè)結(jié)構(gòu)數(shù)組傳遞到函數(shù)中。display( )函數(shù)用結(jié)構(gòu)指針p
39、t接收傳送來的地址。然后通過pt的加一運(yùn)算,依次處理各個(gè)結(jié)構(gòu)的數(shù)據(jù)。例8.9 返回結(jié)構(gòu)變量的函數(shù)/*該例題中調(diào)用了一個(gè)名為str_add_int的函數(shù),該函數(shù)返回的是一個(gè)結(jié)構(gòu)類型變量,在這個(gè)例題中,同時(shí)介紹了數(shù)字串與浮點(diǎn)數(shù)轉(zhuǎn)換的方法*/#include #include #include struct Record /定義一個(gè)結(jié)構(gòu) char str20; int num;struct Record str_add_int(struct Record x); /函數(shù)原型聲明void main() struct Record p,s=“31.45”,20; /*定義結(jié)構(gòu) 變量p,s,并對s初始化*
40、/*以傳遞值的方式,將結(jié)構(gòu)變量s傳遞給函數(shù)str_add_int,經(jīng)過該函數(shù)對s的復(fù)制值加工處理后,再將結(jié)果通過return語句返回給main中的另一結(jié)構(gòu)變量p*/ p=str_add_int(s); printf(%s %dn,s.str,s.num); printf(%s %dn,p.str,p.num);struct Record str_add_int(struct Record x) /形參x和實(shí)參s的類型一致 float e; e=atof(x.str); /將字符串x.str轉(zhuǎn)換為浮 /點(diǎn)數(shù)并賦給e e=e+x.num; /浮點(diǎn)數(shù)與整數(shù)相加 gcvt(e,5,x.str); /將
41、浮點(diǎn)數(shù)e再轉(zhuǎn)換為字 /符串,并賦給x.str return x; /將處理后的結(jié)果(結(jié)構(gòu) /變量)返回給調(diào)用函數(shù)程序運(yùn)行結(jié)果:31.45 2051.45 20例8.10:返回結(jié)構(gòu)變量的地址即結(jié)構(gòu)指針型函數(shù)C語言中,結(jié)構(gòu)的存儲(chǔ)首地址可以作為函數(shù)的返值傳遞給調(diào)用它的函數(shù)。返值為結(jié)構(gòu)地址的函數(shù)就是結(jié)構(gòu)指針型函數(shù)。/*本題中調(diào)用了一個(gè)名為find的函數(shù),根據(jù)小汽車的代號(hào)(不為0)在一個(gè)結(jié)構(gòu)數(shù)組中來查找該種汽車數(shù)據(jù)的位置,該函數(shù)返回的是一個(gè)結(jié)構(gòu)類型指針,該指針指向所找到的結(jié)構(gòu)變量,如未找到,返回NULL*/#include #define NULL 0struct Sample /定義一個(gè)結(jié)構(gòu),包括小汽
42、車代號(hào)、顏色和 /類型等成員 int num; char color; char type;struct Sample *find(struct Sample *pd,int n); /查找函數(shù)原型void main() int num; struct Sample *result; /定義一個(gè)結(jié)構(gòu)指針變量,接收被調(diào) /用函數(shù)的返回值 /定義一個(gè)結(jié)構(gòu)數(shù)組并初始化,存放了所有樣品汽車數(shù)據(jù) struct Sample car=101,G,c,210,Y,m,105,R,l, 222,B,s,308,P,b,0,0,0; printf(Enter the number:); scanf(%d,&nu
43、m); /輸入要查找樣品的代號(hào) /*以傳遞地址的方式,將結(jié)構(gòu)數(shù)組名car和查找代號(hào)num傳遞給函數(shù)find,該函數(shù)返回查找的結(jié)果,找到,返回代號(hào)所對應(yīng)的樣品汽車數(shù)據(jù)的地址,否則,返回NULL*/ result=find(car,num); if(result-num!=NULL) /找到,顯示相關(guān)汽車數(shù)據(jù) printf(number :%dn,result-num); printf(color :%cn,result-color); printf(type :%cn,result-type); else printf(not found); /未找到,給出提示信息struct Sample *
44、find(struct Sample *pd,int n) int i; for(i=0 ; pdi.num!=0 ;i+) if(pdi.num=n)break; /找到,退出循環(huán) if(pdi.num!=NULL) return pd+i; /返回查找結(jié)果 else return NULL;該程序的運(yùn)行結(jié)果為:Enter the number:101 /輸入number:101 /輸出color:Gtype:c 該程序是查找結(jié)構(gòu)數(shù)組car 中的有關(guān)數(shù)據(jù)。鍵盤輸入一個(gè)整數(shù)后,調(diào)用find( )函數(shù)進(jìn)行查找。然后把查到的結(jié)構(gòu)地址作為返值返回。因此,find( )函數(shù)定義為struct samp
45、le *型。在main( )中用指向相同結(jié)構(gòu)的指針result接收函數(shù)返值。在car 結(jié)構(gòu)數(shù)組中,用一個(gè)全零結(jié)構(gòu)作為結(jié)構(gòu)數(shù)組的結(jié)束標(biāo)志(汽車代號(hào)不為0)。采用這種方法便于程序處理??梢钥闯?,結(jié)構(gòu)數(shù)組中的結(jié)構(gòu)數(shù)目無論如何變化,函數(shù)都不需要做任何修改。 結(jié)構(gòu)指針型函數(shù)是以地址傳遞方式向調(diào)用它的函數(shù)返回結(jié)構(gòu)的數(shù)據(jù)。采用這種方式,不僅可以返回某個(gè)結(jié)構(gòu)的地址,也可以返回結(jié)構(gòu)數(shù)組的地址,從而把函數(shù)中處理的若干結(jié)構(gòu)的數(shù)據(jù)返回給調(diào)用它的函數(shù)中。8.8 綜合舉例例8.14 編程處理某班N個(gè)學(xué)生4門課的成績,它們是數(shù)學(xué)、物理、英語和計(jì)算機(jī),按編號(hào)從小到大的順序依次輸入學(xué)生的姓名、性別和四門課的成績。計(jì)算每個(gè)學(xué)生的
46、平均分,并以清晰的打印格式從高分到低分的順序打印平均分高于全班總平均成績的男生的成績單。分析:從題目的要求來看,該問題可以分成三個(gè)功能塊:輸入數(shù)據(jù)、排序,求總平均成績和輸出,我們把它規(guī)劃成四個(gè)函數(shù)。再來看主要的數(shù)據(jù)類型或數(shù)據(jù)結(jié)構(gòu)的選擇,由于學(xué)生的姓名、性別、各門功課的成績及平均成績具有一定的關(guān)聯(lián)性,作為集合數(shù)據(jù),將其規(guī)劃為一個(gè)結(jié)構(gòu)體:struct studentchar name20; /姓名char sex; /性別,m代表男,f代表女float score4; /學(xué)生的各科成績float aver; /平均成績; 這樣學(xué)生的數(shù)據(jù)就可以存放在一個(gè)結(jié)構(gòu)數(shù)組中。有了上面的分析結(jié)果,我們就可以規(guī)劃出三個(gè)函數(shù)的原型:(1)輸入數(shù)據(jù):void input(struct student *p,int n);第一個(gè)參數(shù)用來接收存儲(chǔ)學(xué)生數(shù)據(jù)的結(jié)構(gòu)數(shù)組的首地址,第二個(gè)參數(shù)接收學(xué)生的個(gè)數(shù),(2)排序:void sort(struct student *p,int n);第一個(gè)參數(shù)用來接收存儲(chǔ)學(xué)生數(shù)據(jù)的結(jié)構(gòu)數(shù)組的首地址,第二個(gè)參數(shù)接收學(xué)生的個(gè)數(shù),(3)輸出:void output(struct student *p,int n,float aver);第一個(gè)參數(shù)用來接收存儲(chǔ)學(xué)生數(shù)據(jù)的結(jié)構(gòu)數(shù)組的首地址,第二個(gè)參數(shù)接收學(xué)生的個(gè)數(shù),第三個(gè)參數(shù)接收總平均成績(4)求總平均成績:float a
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 普通述職報(bào)告
- 新應(yīng)急預(yù)案編制
- 保護(hù)家庭網(wǎng)絡(luò)安全的方法
- 股票實(shí)戰(zhàn)課件教學(xué)課件
- 交通安全人人有責(zé)
- DB1304T 492-2024農(nóng)村消防設(shè)施管理指南
- 傳媒經(jīng)營管理
- 校園艾滋病健康
- 初中引體向上教案
- 菱形的性質(zhì)說課稿
- RoHS物料及產(chǎn)品管理規(guī)定
- 教師專業(yè)發(fā)展的文化自覺
- 2023年大西北游考察報(bào)告
- 幼兒行為觀察與指導(dǎo):日記描述法
- 路燈工程施工勞務(wù)清包合同
- 人行道透水磚施工解決方案2445
- 2023年高考浙江卷英語試題(2023年1月考試-含聽力音頻、聽力原文和答案)
- 五年級(jí)上冊數(shù)學(xué)蘇教版課件第1課時(shí) 用列舉法解決問題-教案
- 中國歷史文選第四單元 典志體政書、詔令奏議
- YC/T 11.4-2006煙草機(jī)械產(chǎn)品圖樣及設(shè)計(jì)文件第4部分:編號(hào)原則
- RB/T 047-2020檢驗(yàn)檢測機(jī)構(gòu)管理和技術(shù)能力評(píng)價(jià)設(shè)施和環(huán)境通用要求
評(píng)論
0/150
提交評(píng)論