《結(jié)構(gòu)和鏈表》PPT課件.ppt
《《結(jié)構(gòu)和鏈表》PPT課件.ppt》由會員分享,可在線閱讀,更多相關(guān)《《結(jié)構(gòu)和鏈表》PPT課件.ppt(114頁珍藏版)》請?jiān)谘b配圖網(wǎng)上搜索。
1、1,第7章 結(jié)構(gòu)和鏈表,7.1 結(jié)構(gòu)類型和結(jié)構(gòu)變量 7.2 結(jié)構(gòu)數(shù)組 7.3 結(jié)構(gòu)與函數(shù) 7.4 鏈表 *7.5 聯(lián)合,*7.6 位域 *7.7 枚舉 *7.8 類型定義 *7.9 變量定義,2,基本類型:如整型、實(shí)型、字符型等。 構(gòu)造類型:數(shù)組,每個(gè)元素都是屬于同一個(gè)類型。 結(jié)構(gòu)類型:不同的數(shù)據(jù)類型組成一個(gè)整體方便引用。 例如:一個(gè)學(xué)生數(shù)據(jù)實(shí)體可能有以下多項(xiàng)信息 學(xué)號、 姓名、 性別、 年齡、 成績、 家庭地址 int char char int float char 說明:這類實(shí)體的數(shù)據(jù)因所包含的成員類型不同,不能用單個(gè)數(shù)組來表示,也不便將它們的成員分拆成多個(gè)獨(dú)立的簡單變量
2、,因?yàn)檫@樣會失去實(shí)體的整體性。,,,,,,,7.1 結(jié)構(gòu)類型和結(jié)構(gòu)變量,3,結(jié)構(gòu)類型形式: struct 結(jié)構(gòu)類型名 成員說明表 ; 其中 關(guān)鍵字“struct”:引出結(jié)構(gòu)類型的定義。 結(jié)構(gòu)類型名:結(jié)構(gòu)類型的標(biāo)記,用來定義引用該結(jié)構(gòu)的結(jié)構(gòu)變量。 成員說明表:指明該結(jié)構(gòu)類型的各成員的數(shù)據(jù)類型和名稱。 每個(gè)成員的說明形式為: 類型 成員名;,1. 結(jié)構(gòu)類型,4,【例】學(xué)生基本信息的結(jié)構(gòu)類型: struct student int number; /* 學(xué)號 */ char name20; /* 姓名,設(shè)姓名少于20個(gè)字符 */ char sex; /* 性別 */ c
3、har address40; /* 家庭地址 */ ; 說明:在C++中,如果不會引起混淆(例如,結(jié)構(gòu)類型與結(jié)構(gòu)變量同名),引用結(jié)構(gòu)類型可以不用struct引導(dǎo)。,結(jié)構(gòu)類型例,5,當(dāng)結(jié)構(gòu)類型中的某個(gè)成員又是另一個(gè)結(jié)構(gòu)類型時(shí),這種結(jié)構(gòu)類型是一種嵌套的結(jié)構(gòu)類型。 例如,給上述學(xué)生信息增加出生日期,并將出生日期定義為一種包含日、月、年3項(xiàng)信息的結(jié)構(gòu)類型,則更完整的學(xué)生信息類型就被定義成嵌套的結(jié)構(gòu)類型。,嵌套的結(jié)構(gòu)類型,6,struct Date int day; /* 日 */ int month; /* 月 */ int year; /* 年 */ ; struct student in
4、t number; /* 學(xué)號 */ char name20; /* 姓名 */ char sex; /* 性別 */ struct Date birthday; /*嵌套 Date結(jié)構(gòu) */ char address40; /* 家庭地址 */ ;,嵌套的結(jié)構(gòu)類型例,7,在結(jié)構(gòu)類型定義中,詳細(xì)列出了結(jié)構(gòu)類型所包含的每個(gè)成員的名稱及其類型。實(shí)際上,結(jié)構(gòu)類型定義只是表明一類實(shí)體其數(shù)據(jù)屬性的“模式”,并不定義一個(gè)特定的數(shù)據(jù)實(shí)體,因此不要求分配存儲單元。 程序如果要實(shí)際使用結(jié)構(gòu)類型所描述的數(shù)據(jù)信息,就必須定義結(jié)構(gòu)變量。 結(jié)構(gòu)變量要占用存儲單元,能存放如結(jié)構(gòu)類型所描述的具體數(shù)據(jù)。 對
5、結(jié)構(gòu)類型和結(jié)構(gòu)變量,我們可以簡單地理解為,結(jié)構(gòu)類型是表示數(shù)據(jù)框架的描述文本,結(jié)構(gòu)變量才能存放實(shí)際數(shù)據(jù)。,2. 結(jié)構(gòu)變量,8,一、先定義結(jié)構(gòu)類型,再聲明結(jié)構(gòu)變量 形式:struct 結(jié)構(gòu)類型名 結(jié)構(gòu)變量名表; 例如:利用前面已定義的結(jié)構(gòu)類型 student聲明結(jié)構(gòu)變量 代碼: struct student st1, st2; 其中: student為結(jié)構(gòu)類型名,st1和st2為結(jié)構(gòu)變量。 說明:結(jié)構(gòu)變量聲明后,每個(gè)結(jié)構(gòu)變量的成員名稱、成員個(gè)數(shù)和各成員的數(shù)據(jù)類型與結(jié)構(gòu)類型定義中的成員名稱、成員個(gè)數(shù)和各成員的數(shù)據(jù)類型相一致。,結(jié)構(gòu)變量的定義,9,結(jié)構(gòu)變量內(nèi)存分配單元,10,二、在定義結(jié)構(gòu)類型的同時(shí)聲
6、明結(jié)構(gòu)變量,一般形式: struct 結(jié)構(gòu)類型名 成員說明表 結(jié)構(gòu)變量表;,結(jié)構(gòu)變量的定義,例如: struct stuSType int number;/* 學(xué)號 */ char name20;/* 姓名 */ int score;/* 成績 */ stuS;,結(jié)構(gòu)變量,11,在定義結(jié)構(gòu)變量的同時(shí)給它賦初值,稱為結(jié)構(gòu)變量的初始化。結(jié)構(gòu)變量初始化時(shí),要按結(jié)構(gòu)類型定義中成員的順序逐一給出各成員的初值。 例如:struct point /* 說明繪圖程序的坐標(biāo)類型 */ int x; int y; p1 = 20, 50, p2; /* p1的x值為20,p1的y值為50 *
7、/ 說明:也可以在定義結(jié)構(gòu)類型與聲明結(jié)構(gòu)變量分開的情況下,在聲明結(jié)構(gòu)變量時(shí)進(jìn)行初始化。 例如: struct point p3 = 10, 40, p4 = 20, 50;,結(jié)構(gòu)變量初始化,12,要注意結(jié)構(gòu)類型名和結(jié)構(gòu)變量名的區(qū)別。不能對結(jié)構(gòu)類型名進(jìn)行賦值、存取或運(yùn)算,因?yàn)轭愋筒徽加么鎯臻g;而結(jié)構(gòu)變量會占用存儲空間,定義時(shí)可以賦初值,定義后可引用。 結(jié)構(gòu)變量初始化的時(shí)間。靜態(tài)的和全局的結(jié)構(gòu)變量初始化在程序執(zhí)行之前完成,靜態(tài)的結(jié)構(gòu)變量未指定初值時(shí),值自動置0。局部結(jié)構(gòu)變量初始化是程序控制每次進(jìn)入它所屬轄域時(shí)創(chuàng)建并初始化,未指定初值的局部結(jié)構(gòu)變量其初值是不確定的。,結(jié)構(gòu)變量初始化說明,13,可以
8、定義指向結(jié)構(gòu)的指針變量(結(jié)構(gòu)指針變量簡稱結(jié)構(gòu)指針)。 例如: struct Date *pd, date3; /* 定義變量 */ pd = /* pd指向date3 */ 表示:定義結(jié)構(gòu)指針pd和結(jié)構(gòu)變量date3,并使結(jié)構(gòu)指針pd指向結(jié)構(gòu)變量date3,即結(jié)構(gòu)指針pd的內(nèi)容為結(jié)構(gòu)變量date3所占據(jù)的存儲塊的首地址。,結(jié)構(gòu)變量初始化說明,14,一、引用結(jié)構(gòu)變量 1. 用結(jié)構(gòu)變量名直接引用結(jié)構(gòu)變量 例如: struct student int number;/* 學(xué)號 */ char name20;/* 姓名 */ float score;/* 成績 */ st1 = 10001,
9、 Zhang ping, 85.0, st2; st2 = st1; /* 將結(jié)構(gòu)變量st1作為整體賦值給結(jié)構(gòu)變量st2 */ 說明:兩個(gè)結(jié)構(gòu)變量必須是同類型的。,3. 結(jié)構(gòu)變量的引用,15,2. 指向結(jié)構(gòu)變量的指針間接引用結(jié)構(gòu)變量 例如: struct student int number;/* 學(xué)號 */ char name20;/* 姓名 */ float score;/* 成績 */ st1 = 10001, Zhang ping, 85.0, st2; struct student *p1 = /* 定義結(jié)構(gòu)指針變量p1,并指向結(jié)構(gòu)變量st1的首地址 */,3. 結(jié)構(gòu)變量的引
10、用,16,二、引用結(jié)構(gòu)成員 1. 使用結(jié)構(gòu)變量和成員運(yùn)算符 引用方法:結(jié)構(gòu)變量名.成員名 其中:點(diǎn)符號“.”是結(jié)構(gòu)的成員運(yùn)算符,是優(yōu)先級最高運(yùn)算符之一。 假設(shè)有前面定義的類型為stuSType的結(jié)構(gòu)變量stuS 例如: stuS.name /* 直接引用stuS結(jié)構(gòu)變量的name成員*/,3. 結(jié)構(gòu)變量的引用,17,引用結(jié)構(gòu)變量的成員無非是對該成員進(jìn)行輸入輸出、賦值、運(yùn)算等操作。 例如: printf(學(xué)號:%d 姓名:%s 成績:%dn, stuS.number, stuS.name, stuS.score);/* 輸出學(xué)生stuS的信息 */ 代碼: stuS.score += 5; /
11、* 更新學(xué)生stuS的成績 */ strcpy(stuS.name, Li ming); /*更正學(xué)生stuS的姓名 */,3. 結(jié)構(gòu)變量的引用,18,2. 使用結(jié)構(gòu)指針和指針運(yùn)算符 引用方法:指針變量名-成員名 其中:“-”是指針運(yùn)算符,它是由減號“-”和大于號“”兩個(gè)字符組成(請注意中間不能有空格符),其優(yōu)先級與成員運(yùn)算符“.”一樣,也是優(yōu)先級最高的運(yùn)算符之一。 繼續(xù)使用前面定義的結(jié)構(gòu)變量stuS,可以使用結(jié)構(gòu)指針間接引用stuS結(jié)構(gòu)變量的成員。 struct stuSType *sp = /* 修改成績 */,二、引用結(jié)構(gòu)成員,19,3. 使用結(jié)構(gòu)指針和成員運(yùn)算符 引用方法:(* 指針
12、變量名).成員名 其中:圓括號是必要的。若省略,由于成員運(yùn)算符“.”優(yōu)先級高于“*”,將會導(dǎo)致編譯錯(cuò)誤。 例如: struct stuSType *sp = */,二、引用結(jié)構(gòu)成員,20,(1) 不能直接對結(jié)構(gòu)變量進(jìn)行輸入或輸出,只允許對結(jié)構(gòu)變量的成員變量進(jìn)行輸入和輸出。 例如,對于前面定義的類型為student的結(jié)構(gòu)變量st1,以下分別是錯(cuò)誤和正確的代碼: printf(%s, st1); /*錯(cuò)誤,st1是結(jié)構(gòu)變量不能直接輸出*/ printf(%s, st1.name); /*正確,僅輸出st1的name成員 */,引用結(jié)構(gòu)變量或成員注意,21,(2) 如果結(jié)構(gòu)中的成員本身也是一個(gè)結(jié)構(gòu)類
13、型,在引用該成員的成員時(shí)需使用多個(gè)成員運(yùn)算符“.”,將嵌套的結(jié)構(gòu)成員一級一級地連續(xù)指定。 例如,想引用前面定義的類型為student的結(jié)構(gòu)變量st1中成員birthday成員year, 正確的寫法是: st1.birthday.year,引用結(jié)構(gòu)變量或成員注意,22,#include struct stuScore /* 定義結(jié)構(gòu) */ char name20; int chinese; int math; ; void main() float aver1,aver2,aver3; struct stuScore st1,st2,st3; /* 定義3個(gè)結(jié)構(gòu)變量 */ printf(請
14、輸入3位學(xué)生的姓名、語文成績、數(shù)學(xué)成績n); scanf(%s%d%d, st1.name, ,【例7.1】利用結(jié)構(gòu)變量,輸入3個(gè)學(xué)生的姓名、語文成績和數(shù)學(xué)成績,然后計(jì)算每個(gè)學(xué)生的平均成績并輸出。,23,aver1=(st1.chinese+st1.math)/2.0; /* 計(jì)算平均成績 */ aver2=(st2.chinese+st2.math)/2.0; aver3=(st3.chinese+st3.math)/2.0; printf(姓名t語文t數(shù)學(xué)t平均成績n); printf(%st%4dt%4dt%6.2fn, st1.name, st1.chinese, st1.mat
15、h, aver1); printf(%st%4dt%4dt%6.2fn, st2.name, st2.chinese,st2.math, aver2); printf(%st%4dt%4dt%6.1fn, st3.name, st3.chinese,st3.math, aver3); ,【例7.1】程序續(xù),24,從例7.1中可以看出,一個(gè)結(jié)構(gòu)變量只能存放一個(gè)學(xué)生的基本信息。如果要描述兩個(gè)學(xué)生的信息需要有兩個(gè)結(jié)構(gòu)變量,依此類推, 當(dāng)要描述一個(gè)班級的學(xué)生時(shí),獨(dú)立定義同樣類型的許許多多結(jié)構(gòu)變量的方法顯然是不可取的。在C程序設(shè)計(jì)中,一般用結(jié)構(gòu)類型描述個(gè)體的信息結(jié)構(gòu),用數(shù)組表示個(gè)體的集合。
16、當(dāng)數(shù)組的元素是結(jié)構(gòu)時(shí),這種數(shù)組就稱為結(jié)構(gòu)數(shù)組。 例如,用結(jié)構(gòu)數(shù)組表示一個(gè)班級學(xué)生,數(shù)組的元素存儲一個(gè)學(xué)生的有關(guān)信息。這樣,能充分反映班級的整體性,程序處理也變得更為方便。,7.2 結(jié)構(gòu)數(shù)組,25,定義結(jié)構(gòu)數(shù)組與定義結(jié)構(gòu)變量的方法類似也有兩種方法。 (1) 先定義結(jié)構(gòu)類型,再聲明結(jié)構(gòu)數(shù)組 struct stuScore char name20; int chinese; int math; ; struct stuScore st3;,1. 結(jié)構(gòu)數(shù)組的定義,結(jié)構(gòu)數(shù)組,26,與結(jié)構(gòu)變量初始化相仿,在定義結(jié)構(gòu)數(shù)組時(shí),也可給結(jié)構(gòu)數(shù)組賦初值。例如: struct stuScore char na
17、me20; int chinese; int math; st3=Zhang,80,85,Li,85,90,Wang,90,70;,結(jié)構(gòu)數(shù)組的初始化,27,結(jié)構(gòu)數(shù)組的引用實(shí)際上是對每個(gè)元素中的成員進(jìn)行引用。與引用結(jié)構(gòu)成員類似,也有以下3種方法: (1) 使用結(jié)構(gòu)數(shù)組元素和成員運(yùn)算符 方法:結(jié)構(gòu)數(shù)組名元素下標(biāo).結(jié)構(gòu)成員名 例如:printf(%s, st0.name); 說明:輸出第1個(gè)學(xué)生的姓名,即Zhang,2. 結(jié)構(gòu)數(shù)組的引用,28,2. 結(jié)構(gòu)數(shù)組的引用,(2) 使用結(jié)構(gòu)指針和指針運(yùn)算符 方法:指針變量名-成員名 例如: struct stuScore *sp = st; /*定義結(jié)
18、構(gòu)指針sp,指向結(jié)構(gòu)數(shù)組st首元素*/ printf(%sn, sp-name); /*輸出第1個(gè)學(xué)生的姓名,即Zhang */ sp++;/* 結(jié)構(gòu)指針指向下一個(gè)元素 */ printf(%sn, sp-name); /* 輸出第2個(gè)學(xué)生的姓名,即Li */,29,2. 結(jié)構(gòu)數(shù)組的引用,(3) 使用結(jié)構(gòu)指針和成員運(yùn)算符 方法:(* 指針變量名).成員名 例如: struct stuScore *sp = st; /*定義結(jié)構(gòu)指針sp,指向結(jié)構(gòu)數(shù)組st首元素*/ printf(%sn, (*sp).name); /* 輸出學(xué)生st0的姓名,即Zhang */ sp++;/* 結(jié)構(gòu)指
19、針指向下一個(gè)元素,即指向st1 */ printf(%sn, sp-name);/* 輸出學(xué)生st1的姓名,即Li */,30,#include struct stuScore char name20; int chinese; int math; ; void main() int i; float aver3;/* 定義普通數(shù)組 */ struct stuScore st3;/* 定義結(jié)構(gòu)數(shù)組 */ printf(請輸入3位學(xué)生的姓名、語文成績、數(shù)學(xué)成績n);,【例7.2】利用結(jié)構(gòu)數(shù)組,輸入3個(gè)學(xué)生的姓名、語文成績和數(shù)學(xué)成績,然后計(jì)算每個(gè)學(xué)生的平均成績并輸出。,31,for(
20、 i=0; i<3; i++) scanf(%s%d%d, sti.name, ,【例7.2】程序續(xù),32,在C語言中,函數(shù)的形參可以是變量、指針、數(shù)組,也允許是一個(gè)結(jié)構(gòu)。 將一個(gè)結(jié)構(gòu)傳遞給函數(shù)有三種方式:傳遞單個(gè)成員、傳遞整個(gè)結(jié)構(gòu)、傳遞指向結(jié)構(gòu)的指針。 傳遞單個(gè)成員或整個(gè)結(jié)構(gòu)給函數(shù)在C中認(rèn)為是值調(diào)用,即在被調(diào)用的函數(shù)中盡管修改了形參的值,但不會改變調(diào)用函數(shù)時(shí)提供的實(shí)參變量的值。,7.3 結(jié)構(gòu)與函數(shù),33,將結(jié)構(gòu)成員作為實(shí)參傳遞給一個(gè)函數(shù),實(shí)際上和其他基本數(shù)據(jù)類型的傳遞方法相同。 【例7.3】輸入年月日,輸出該年中的第幾天 #include int dayTable12=31,28
21、,31,30,31,30,31,31,30,31,30,31, 31,29,31,30,31,30,31,31,30,31,30,31; /* 平年或閏年 */ struct Date /* 定義一個(gè)Date結(jié)構(gòu)類型 */ int day; int month; int year; int yearDay; date; /* 定義一個(gè)Date結(jié)構(gòu)類型的結(jié)構(gòu)變量 */,1. 結(jié)構(gòu)成員作為函數(shù)參數(shù),34,int dayofYear(int d, int m, int y) /* 計(jì)算年中第幾天函數(shù) */ int i, leap, day = d; leap = (y%4 == 0 /* 返回
22、計(jì)算的結(jié)果 */ ,【例7.3】程序續(xù) dayofYear() 函數(shù),35,void main() int leap, days; printf( Date Conversion Programn); printf(Year = ); scanf(%d, ,【例7.3】程序續(xù)主函數(shù),36,leap = (date.year%4 == 0 ,【例7.3】程序續(xù)主函數(shù),37,程序運(yùn)行時(shí),輸入的數(shù)據(jù)與輸出的結(jié)果如下:,【例7.3】程序運(yùn)行結(jié)果,38,使用結(jié)構(gòu)作為實(shí)參傳遞給一個(gè)函數(shù),實(shí)際上將這個(gè)結(jié)構(gòu)的所有成員都傳遞給了被調(diào)用函數(shù)的形參。 以例7.3程序?yàn)槔瑢χ骱瘮?shù)中對函數(shù)dayofYear的調(diào)用
23、,原來使用表示日、月、年的3個(gè)結(jié)構(gòu)成員作為實(shí)參改為用一個(gè)結(jié)構(gòu)變量date作為實(shí)參。即將代碼 date.yearDay = dayofYear(date.day, date.month, date.year); 改寫成 date.yearDay = dayofYear(date);,2. 結(jié)構(gòu)作為函數(shù)參數(shù),39,對應(yīng)的dayofYear函數(shù)也要作如下的修改: int dayofYear(struct Date d) /* 計(jì)算年中第幾天函數(shù) */ int i, leap, day = d.day; leap=(d.year%4==0 /* 返回計(jì)算的結(jié)果 */ ,2. 結(jié)構(gòu)作為函數(shù)參數(shù),4
24、0,指向結(jié)構(gòu)的指針作為函數(shù)的形參。實(shí)參可以是結(jié)構(gòu)的地址,也可以是指向結(jié)構(gòu)的指針變量。 仍以例7.3程序?yàn)槔?,主函?shù)中對函數(shù)dayofYear的調(diào)用,原來使用結(jié)構(gòu)變量date作為實(shí)參現(xiàn)改為用結(jié)構(gòu)變量date的地址作為實(shí)參。即將代碼 date.yearDay = dayofYear(date); 改寫成 dayofYear(,2. 結(jié)構(gòu)指針作為函數(shù)參數(shù),41,對應(yīng)的dayofYear函數(shù)也要作如下的修改: /* 計(jì)算年中第幾天函數(shù),無返回值 */ void dayofYear(struct Date *dp) int i, leap, day = dp-day; leap = ( d
25、p-year%4 == 0 /* 計(jì)算結(jié)果回填到y(tǒng)earDay成員,沒有return語句 */ ,2. 結(jié)構(gòu)作為函數(shù)參數(shù),42,(1) 結(jié)構(gòu)或結(jié)構(gòu)成員作為函數(shù)參數(shù)是值傳遞方式,在被調(diào)用函數(shù)dayofYear中必須用return語句返回結(jié)果。 如果不用return語句,寫成“d.yearDay = day;”,主函數(shù)不能獲得函數(shù)結(jié)果。因?yàn)楹瘮?shù)的形參是函數(shù)的局部變量,函數(shù)調(diào)用時(shí),將結(jié)構(gòu)date的各成員值依次送給形參d的各成員中,以后函數(shù)對d作任何的改變與date無關(guān)。,對結(jié)構(gòu)、結(jié)構(gòu)成員與結(jié)構(gòu)指針作為函數(shù)參數(shù)作一個(gè)總結(jié),,,,,main函數(shù)調(diào)用語句 dayofYear函數(shù) date結(jié)構(gòu)(實(shí)參)
26、 d結(jié)構(gòu)(形參),43,(2) 使用結(jié)構(gòu)地址或結(jié)構(gòu)指針作為函數(shù)的參數(shù),函數(shù)調(diào)用時(shí),雖只傳遞結(jié)構(gòu)的地址給結(jié)構(gòu)指針形參,但通過該結(jié)構(gòu)指針形參間接引用所指向的結(jié)構(gòu)變量。因此,函數(shù)既可以引用結(jié)構(gòu)指針形參所指向結(jié)構(gòu)的成員,也可把計(jì)算結(jié)果存儲于結(jié)構(gòu)指針形參所指向結(jié)構(gòu)的成員中。,對結(jié)構(gòu)、結(jié)構(gòu)成員與結(jié)構(gòu)指針作為函數(shù)參數(shù)作一個(gè)總結(jié),,date結(jié)構(gòu),形參dp,44,將結(jié)構(gòu)date作為實(shí)參傳遞給dayofYear函數(shù)的結(jié)構(gòu)類型形參d,但計(jì)算結(jié)果是通過return day;語句返回到主函數(shù)的調(diào)用語句。 如果希望將計(jì)算的結(jié)果先保存到結(jié)構(gòu)類型形參d的成員yearDay中,然后返回結(jié)構(gòu)類型形參d的值,可以對函數(shù)dayo
27、fYear重新改寫如下: struct Date dayofYear(struct Date d) int i, leap; d.yearDay = d.day; leap = (d.year%4 == 0 /* 返回結(jié)構(gòu)類型 */ ,4. 函數(shù)返回結(jié)構(gòu)類型值,45,在主函數(shù)中,調(diào)用dayofYear函數(shù)后把返回的結(jié)構(gòu)賦值給結(jié)構(gòu)變量date,調(diào)用語句也作相應(yīng)的修改。即將 date.yearDay = dayofYear(date); 改寫成 date = dayofYear(date); 調(diào)用帶有結(jié)構(gòu)類型形參的函數(shù)時(shí),實(shí)參結(jié)構(gòu)的各成員的值需要全部拷貝給形參結(jié)構(gòu)的相應(yīng)成員,費(fèi)時(shí)間
28、又費(fèi)空間。一般情況下,以傳遞結(jié)構(gòu)地址或指針為好。,4. 函數(shù)返回結(jié)構(gòu)類型值,46,變量:通過變量定義引入。程序執(zhí)行時(shí),不能顯式地用語句隨意生成變量和消去變量。 數(shù)組:必須事先定義固定的長度(即元素個(gè)數(shù)),有時(shí)存放的數(shù)據(jù)不確定時(shí),往往把數(shù)組定得足夠大。,7.4 鏈表,按數(shù)據(jù)對象可能最多情況來設(shè)定變量或數(shù)組,稱為靜態(tài)方法。 而按需要用隨時(shí)生成和消去數(shù)據(jù)對象,數(shù)據(jù)之間的關(guān)系也能由程序隨時(shí)設(shè)定和改變,這種實(shí)現(xiàn)方法稱為動態(tài)方法,如鏈表。,47,head:鏈表的“頭指針”變量,存放的是地址,指向鏈表的第一個(gè)元素(或稱表元、結(jié)點(diǎn))。 鏈表元素:分成兩部分,存放實(shí)際的數(shù)據(jù)和后繼表元指針。,單向鏈表結(jié)構(gòu)示意
29、圖,空鏈表示意圖,1. 什么是鏈表,48,鏈表與數(shù)組相比較,主要有以下幾個(gè)方面的區(qū)別: 數(shù)組的元素個(gè)數(shù)在數(shù)組定義時(shí)指定,元素個(gè)數(shù)是固定的;鏈表表元的存儲空間是在程序執(zhí)行時(shí)由程序動態(tài)向系統(tǒng)申請的,鏈表的表元個(gè)數(shù)可按需要增減。 數(shù)組的元素順序關(guān)系由元素在數(shù)組中的下標(biāo)確定,鏈表表元順序關(guān)系由表元的指針實(shí)現(xiàn)。 在數(shù)組中插入或刪除表元,要移動部分表元的存儲位置。在鏈表中插入或刪除表元,不要移動表元,僅改變表元的指針指向即可。,鏈表與數(shù)組的區(qū)別,49,動態(tài)數(shù)據(jù)結(jié)構(gòu)中的數(shù)據(jù)對象是一種結(jié)構(gòu)變量,它除有一些成員存儲數(shù)據(jù)信息外,還有存儲指針的成員。最簡單情況是結(jié)構(gòu)包含有指向與自己同樣結(jié)構(gòu)的指針。 例如: str
30、uct intNode /* 整數(shù)鏈表表元類型 */ int value ; /* 存放整數(shù) */ intNode *next ; /* 存放后繼表元的指針 */ ; 利用指針成員next,可把一個(gè)intNode類型的結(jié)構(gòu)與另一個(gè)同類型的結(jié)構(gòu)鏈接起來,用于描述動態(tài)數(shù)據(jù)結(jié)構(gòu)中兩數(shù)據(jù)對象之間的關(guān)系。,2. 動態(tài)變量,50,動態(tài)數(shù)據(jù)結(jié)構(gòu)中的變量稱為動態(tài)變量,動態(tài)變量能由程序調(diào)用庫函數(shù),顯式地隨意生成和釋放(消去)。 在C語言中,有malloc和calloc兩個(gè)庫函數(shù)用于生成動態(tài)變量,另有一個(gè)庫函數(shù)free用于釋放動態(tài)變量。,2. 動態(tài)變量,51,格式:void *malloc(si
31、ze) 功能:向系統(tǒng)申請size個(gè)字節(jié)的連續(xù)空間。如果申請成功,函數(shù)的返回值是指向已分配的連續(xù)空間開始地址的指針;如果因動態(tài)存儲區(qū)域的內(nèi)存已分配完,而不能滿足這次申請要求,函數(shù)將返回0(NULL)值。 說明:由于malloc()函數(shù)的返回值是void類型(無類型)的指針值,程序需將該返回值強(qiáng)制轉(zhuǎn)換成某種特定的指針類型。 例如: intNode *p; p = (intNode *) malloc(sizeof(intNode));,(1) malloc() 函數(shù),52,(2) calloc() 函數(shù),格式:void *calloc(n, size) 功能:向系統(tǒng)申請n塊size個(gè)字節(jié)的連
32、續(xù)空間(即n*size個(gè)字節(jié))。如果申請成功,函數(shù)的返回值是指向已分配的連續(xù)空間的開始地址的指針;如果申請不成功,則返回NULL值。 說明:calloc()與malloc()函數(shù)一樣,返回值是一個(gè)無類型的指針值,程序需將該返回值強(qiáng)制轉(zhuǎn)換成某種特定的指針類型。函數(shù)calloc()與函數(shù)malloc()比較,除多一個(gè)參數(shù)外,在功能上,函數(shù)calloc()還給分配的空間完成清0的工作,而函數(shù)malloc()通常不另還做清0的工作,53,(2) calloc() 函數(shù),例如:申請能存儲100個(gè)整數(shù)的存儲塊。 int *p; p = (int *) calloc(100, sizeof(int)); 也
33、可以使用 malloc 函數(shù)實(shí)現(xiàn),如: p = (int *) malloc(100 * sizeof(int)); 利用上述函數(shù)返回的存儲塊的首地址,就能如同普通數(shù)組一樣訪問這存儲塊中100個(gè)元素,習(xí)慣稱這樣的數(shù)組為動態(tài)數(shù)組。 例如: 以下代碼置這個(gè)動態(tài)數(shù)組的值為1至100的整數(shù): for(int k = 0; k < 100; k++) pk = k+1;,54,(3) free() 函數(shù),格式:void free(*ptr) 功能: 釋放由ptr所指向的存儲塊。 說明: ptr的值必須是調(diào)用函數(shù)malloc()或calloc()時(shí)的返回值,即為動態(tài)申請內(nèi)存得到的一塊連續(xù)存儲空間的
34、地址。,以上三個(gè)函數(shù)中,形參n和size為unsigned類型,ptr為指針類型。函數(shù)malloc()和calloc()返回的是系統(tǒng)分配的連續(xù)存儲空間的首地址,其類型為void *,程序?qū)⑦@個(gè)返回值強(qiáng)制轉(zhuǎn)換成某種指針類型后,賦值給某個(gè)指針變量,然后用這個(gè)指針變量間接引用存儲空間的相應(yīng)成員。,55,主要包括建立空的單鏈表、創(chuàng)建一個(gè)表元、遍歷單鏈表、查找指定值的表元、插入一個(gè)表元、刪除一個(gè)表元等。 假定存儲一個(gè)學(xué)生信息的鏈表表元類型定義如下: struct stuS/* 學(xué)生鏈表表元結(jié)構(gòu)類型 */ int number;/* 學(xué)號 */ char name20;/* 姓名 */ int score
35、;/* 成績 */ stuS *next; /* 指向后繼表元的指針 */ ; stuS *head,*p,*p1,*p2; /* head是鏈表的頭指針,其余是工作指針 */,3. 單鏈表上的基本操作,56,單鏈表的建立過程是從空鏈表(沒有鏈表表元)開始,逐步插入新表元的過程。 要建立空鏈表首先應(yīng)讓“頭指針”為空,即設(shè)置變量head為NULL。 例如:head = NULL; 說明:建立以head為鏈表頭指針的空鏈表。,(1) 建立空鏈表,空鏈表示意圖,57,假設(shè)要創(chuàng)建一個(gè)新的學(xué)生,該生的學(xué)號、姓名和成績從鍵盤輸入。程序應(yīng)首先向系統(tǒng)申請對應(yīng)該生的表元的存儲空間,然后輸入該生的信息存入這個(gè)
36、表元。 例如: p=(stuS *)malloc(sizeof(stuS)); /* p指向申請到的存儲塊 */ scanf(%d%s%d, /* 后繼表元地址為空 */,(2) 創(chuàng)建一個(gè)表元,58,stuS *createStudent (int num, char *name, int s) /* 學(xué)生的學(xué)號、姓名和成績 */ stuS *p = (stuS *) malloc(sizeof(stuS)); p-number = num;/* 學(xué)號 */ strcpy(p-name, name); /* 姓名*/ p-score = s; /* 成績 */ p-next = NU
37、LL; /* 后繼表元地址為空 */ return p; ,【例7.4】編寫創(chuàng)建一個(gè)學(xué)生表元的函數(shù),59,所謂遍歷鏈表是順序訪問鏈表中的表元,對各表元作某種處理。 例如,順序輸出鏈表各表元的數(shù)據(jù)。遍歷單鏈表需從鏈表的首表元開始,沿著表元的鏈接順序逐一考察鏈表的每個(gè)表元,直至鏈表結(jié)束。 假設(shè)用工作指針p遍歷整個(gè)鏈表,p的初值應(yīng)該是鏈表的頭指針,循環(huán)條件是指針p還指向某個(gè)表元,即p不等于NULL。循環(huán)要做的工作包括輸出p所指向的表元的值,和準(zhǔn)備考察下一個(gè)表元(p = p-next實(shí)現(xiàn))。,(3) 遍歷鏈表,60,void travelStuLink(stuS *head) stuS *p
38、= head; if(head == NULL) printf (n目前在鏈表中沒有學(xué)生n); return; printf (n目前在鏈表中的學(xué)生如下n); while (p != NULL) printf(%dt%st%dn, p-number, p-name, p-score); p = p-next; /* 準(zhǔn)備訪問下一個(gè)表元 */ ,【例7.5】編寫遍歷學(xué)生單鏈表的函數(shù),61,在鏈表中查找指定值的表元可能有以下幾個(gè)目的: 獲取該表元的詳細(xì)信息; 對找到的表元進(jìn)行修改; 將查到的表元刪除; 在查到的表元之前插入一個(gè)新表元等。 查找分為兩種:
39、 無序鏈表上的查找, 有序鏈表上的查找。,(4) 在鏈表中查找表元,62,【例7.6】編寫無序?qū)W生鏈表上的查找函數(shù), 在無序鏈表上查找 從鏈表頭指針?biāo)傅牡谝粋€(gè)表元出發(fā),順序查找。若發(fā)現(xiàn)有指定值的表元,以指向該表元的指針值為查找結(jié)果;若查找至鏈表末尾,未發(fā)現(xiàn)有指定值的表元,查找結(jié)果為NULL,表示鏈表中沒有指定值的表元。 stuS *searchSLink(stuS *h, int num) /* h為頭指針,num為要查找的學(xué)號 */ stuS *v = h;/* 工作指針v的初值是鏈表的頭指針 */ while(v != NULL ,63, 在有序鏈表上查找,有序鏈表的表元是
40、按值從小到大順序鏈接的,在順序查找循環(huán)中,當(dāng)發(fā)現(xiàn)還有表元,并且該表元的值比尋找值小時(shí),應(yīng)繼續(xù)查找。 反之,若不再有表元,或當(dāng)前表元值不比尋找值小,則查找應(yīng)結(jié)束。 查找循環(huán)結(jié)束后,僅當(dāng)還有表元,并且當(dāng)前表元的值與尋找值相等情況下,才算找到,函數(shù)返回當(dāng)前表元的指針。否則,鏈表中沒有要尋找的表元,函數(shù)應(yīng)該返回NULL 。,64,【例7.7】編寫有序?qū)W生鏈表上的查找函數(shù),從鏈表的首表元開始,循環(huán)條件是還有表元,且表元的值小于尋找值。循環(huán)體要做的工作是準(zhǔn)備考察下一個(gè)學(xué)生。尋找循環(huán)結(jié)束后,在有當(dāng)前表元,且當(dāng)前表元的值是要尋找值情況下,函數(shù)才返回當(dāng)前表元的指針。否則,函數(shù)返回NULL。 stuS *se
41、archSOLink(stuS *h, int key) /* h為頭指針,key為要查找的學(xué)號 */ stuS *v = h; /* 工作指針v的初值是鏈表的頭指針 */ while (v != NULL ,65,在鏈表中插入一個(gè)表元,可以插在鏈表的最前面(作為首表元)、最后面(作為尾表元)、也可以插在指定的表元之后。 在首表元之前插入新表元 在原來的首表元之前插入一個(gè)新表元,插入的表元將成為鏈表新的首表元。這個(gè)工作包括將鏈表原來的首表元接在新插入的表元后面,并修改鏈表的頭指針,使鏈表的頭指針指向新插入的表元。設(shè)指針p指向新申請到的表元地址,實(shí)現(xiàn)這個(gè)功能的代碼如下: p-next
42、= head; /* 新表元指向原首表元地址,使原首表元成為后繼表元 */ head = p; /* 頭指針指向新表元,使新表元成為首表元 */,(5) 在鏈表中插入新表元,66,插入新表元之前的狀態(tài),插入新表元之后的狀態(tài),執(zhí)行 p-next = head;,執(zhí)行 head = p;,在首表元之前插入新表元圖示,67,假設(shè): 指針w指向指定的表元(新表元插在其后) 指針p指向新表元 插入工作包含兩個(gè)基本動作: a. 將原先w所指向表元的后繼表元成為p所指向表元的后繼表元,用代碼p-next = w-next實(shí)現(xiàn)。 b. 將p所指的表元成為w所指表元的后繼表元,用代碼w-next = p實(shí)現(xiàn)。,
43、 在指定的表元之后插入新表元,68,插入新表元之前的狀態(tài),插入新表元之后的狀態(tài),執(zhí)行 p-next = w-next;,執(zhí)行 w-next = p;,在指定的表元之后插入新表元圖示,69,【例7.8】編寫在學(xué)生鏈表中,在指定學(xué)生 之后插入一個(gè)新學(xué)生的函數(shù),void insert(stuS *head, int num) /* num為要查找的學(xué)號 */ stuS *w=head, *p; while (w != NULL /* *p作為*w的后繼表元 */ ,70,設(shè)指針p指向新表元,由以下3個(gè)操作步驟完成: a. 從頭指針開始依次找到最后的表元,由指針w指向最后的表元。 b. 將指針p所指
44、表元成為指針w所指的后繼表元,用代碼 w-next = p 實(shí)現(xiàn)。 c. 將新表元的后繼表元設(shè)置為空,用代碼 p-next = NULL 實(shí)現(xiàn)。, 在鏈表末尾添加新表元,71,添加新表元之前的狀態(tài),添加新表元之后的狀態(tài),NULL,執(zhí)行 w-next = p;,執(zhí)行 p-next = NULL;,在鏈表末尾添加新表元圖示,NULL,72,【例7.9】編寫在學(xué)生鏈表的末尾接上一個(gè)新學(xué)生的函數(shù),stuS *append(stuS *head) stuS *w = head,*p; p = (stuS *)malloc(sizeof(stuS)); /* p指向新申請的表元 */ printf (請
45、輸入學(xué)號、姓名、成績:); scanf (%d%s%d, /* 返回頭指針 */ ,73,要將一表元從鏈表中刪除,首先要在鏈表中查找該表元。若未找到,則不用做刪除工作; 在刪除時(shí)還要考慮兩種不同的情況: 如果刪除的是首表元要修改鏈表頭指針。 如果刪除的表元不是鏈表的首表元,則要更改刪除表元的前驅(qū)表元的后繼指針。 假設(shè)指針變量p的初值指向首表元,通過循環(huán),p依次指向下一個(gè)表元(使用p = p-next實(shí)現(xiàn));指針變量w總是指向p的前導(dǎo)表元(使用w = p實(shí)現(xiàn))。,(6) 從鏈表中刪除表元,74,p = head;/* 將首表元的指針保存到指針變量p */ if(p) /* 判是否為空鏈表 *
46、/ head = head-next; /* 讓鏈表的頭指針指向首表元的后繼表元*/ p-next = NULL; /* 刪除的表元脫離鏈表 */ , 刪除單鏈表的首表元,刪除首表元 之后狀態(tài),75,p = w-next;/* w是要刪除表元的前驅(qū)表元的指針*/ w-next = p-next; /* p是要刪除表元的指針 */ p-next = NULL; /* 刪除的表元脫離鏈表 */, 刪除單鏈表中的某表元,刪除表元 之前狀態(tài),刪除非首表 元之后狀態(tài),p = w-next;,w-next = p-next;,p-next = NULL;,,,,,,,NULL,76,【例7.1
47、0】編寫在學(xué)生鏈表中刪除 指定學(xué)號的表元的函數(shù),stuS *delStu (stuS *head, int num)/* num為要查找的學(xué)號 */ stuS *w, *p; if (head == NULL) return NULL; p = head; /* 讓p指向鏈表的首表元 */ while (p != NULL /* 返回頭指針 */ ,77,#include #include #include struct stuS int number;/* 學(xué)號 */ char name20; /* 姓名 */ int score;/* 成績 */ stuS *next; ;/* 其他函數(shù)應(yīng)
48、插在主函數(shù)之前 */,主函數(shù)1,78,void main() stuS *head=NULL; char *menu = 1 在鏈表末尾添加新表元, 2 在指定表元之后插入新表元”, 3 顯示鏈表中所有表元,4 刪除鏈表中指定表元,; int i, ans, number; while (1) printf(n請選擇下列菜單命令:n); for( i=0; menui0!=0; i++) printf(t%sn, menui); /*顯示在鏈表上操作的菜單 */ printf(t其他選擇(非14),結(jié)束本程序運(yùn)行!n); scanf(%d,,主函數(shù)2,79,switch(an
49、s) case 1: head= append (head); break; case 2: printf(請輸入插入學(xué)生的學(xué)號:); scanf(%d, ,主函數(shù)3,80,【例7.11】寫一個(gè)函數(shù),輸入n個(gè)整數(shù),并按整數(shù)的輸入順序建立一個(gè)整數(shù)單鏈表。 算法思想: 1. 為加快新表元添加到鏈表的末尾,引入指向鏈表的末尾表元的指針變量tail; 2. 鏈表的初始狀態(tài)為空鏈表,即頭指針head和末尾表元指針tail都為 NULL; 3. 每輸入一個(gè)大于0的整數(shù)時(shí),向系統(tǒng)申請一個(gè)表元的存儲空間并賦給指針變量p; 4. 將輸入的整數(shù)n存入新表元并將新表元接在鏈表的末尾; 5. 當(dāng)輸入
50、一個(gè)小于或等于0的整數(shù)時(shí),函數(shù)運(yùn)行結(jié)束并返回鏈表的頭指針head。,4. 單鏈表程序設(shè)計(jì)實(shí)例,81,連接前的狀態(tài),連接后的狀態(tài),【例7.11】圖示,tail = tail-next = p,82,#include #include struct intNode int value; struct intNode *next; ; /* 建立正整數(shù)鏈表的函數(shù) */ struct intNode *createList( ) struct intNode *head, *tail, *p; /* 鏈表頭尾指針 */ int n; /* 存放讀入的整數(shù) */ head = tail = NULL;
51、 /* 初始時(shí)為空鏈表 */ printf (請輸入一個(gè)整型數(shù)據(jù)(0時(shí)運(yùn)行結(jié)束):); scanf (%d, ,【例7.11】程序,83,while ( n 0) /* 有整數(shù)讀入 */ p = ( struct intNode *) malloc ( sizeof ( struct intNode)); /* 申請一個(gè)表元的存儲空間 */ p-value = n; /* 輸入的整數(shù)存入新表元 */ p-next = NULL;/* 新表元為最后一個(gè)表元 */ if (head == NULL) head = tail = p; /* 當(dāng)空鏈表時(shí),新表元作為首表元 */ el
52、se tail = tail-next = p; /* 非空鏈表時(shí),新表元接在鏈表的末尾 */ printf (請輸入一個(gè)整型數(shù)據(jù)(0時(shí)運(yùn)行結(jié)束):); scanf (%d, /* 返回鏈表的頭指針head */ ,【例7.11】程序續(xù),84,/* 主函數(shù) */ void main() struct intNode *p, *q; q = createList( );/* 當(dāng)函數(shù)返回時(shí),q為頭指針 */ while (q) printf(%dn,q-value); /* 依次顯示鏈表中的表元值 */ p = q-next; free(q); q = p; ,【例7.11】程序續(xù)
53、,85,算法思想: 為程序處理方便,引入指向當(dāng)前要考察的表元的指針變量v和指向當(dāng)前要考察的表元前一個(gè)表元的指針變量u; 鏈表的初始狀態(tài)為空鏈表,即頭指針head為 NULL; 每輸入一個(gè)大于0的整數(shù)時(shí),向系統(tǒng)申請一個(gè)表元的存儲空間并賦給指針變量p; 將輸入的整數(shù)n存入新表元; 尋找新表元插入的位置:從鏈表的首表元開始考察,與輸入的整數(shù)n比較。若n當(dāng)前表元的值,則考察下一個(gè)表元;否則新表元插在當(dāng)前表元之前。 當(dāng)輸入一個(gè)小于或等于0的整數(shù)時(shí),函數(shù)運(yùn)行結(jié)束并返回鏈表的頭指針head。,【例7.12】編寫一個(gè)函數(shù),輸入n個(gè)整數(shù),建立一個(gè)按值從小到大順序鏈接的鏈表,86,#include #includ
54、e struct intNode int value; struct intNode *next; ; /* 建立有序的正整數(shù)鏈表的函數(shù) */ struct intNode *createSortList( ) struct intNode *u, *v, *p, *head = NULL; /* u 指向上一個(gè)表元,v指向下一個(gè)表元 */ int n; printf (請輸入一個(gè)整型數(shù)據(jù)(0時(shí)運(yùn)行結(jié)束):); scanf (%d, ,【例7.12】程序,87,while ( n 0) /* 有整數(shù)讀入 */ p = (struct intNode *)malloc (sizeof(stru
55、ct intNode)); p-value = n; /* 輸入的整數(shù)存入新表元 */ v = head; /* 從首表元開始考察 */ while(v != NULL /* 返回鏈表的頭指針head */ ,【例7.12】程序續(xù),88,/* 主函數(shù) */ void main() struct intNode *p, *q; q = createSortList ( );/* 當(dāng)函數(shù)返回時(shí),q為頭指針 */ while (q) printf(%dn,q-value); /* 依次顯示鏈表中的表元值 */ p = q-next; free(q); q = p; ,【例7.12】程序
56、續(xù),89,【例7.13】實(shí)現(xiàn)將一個(gè)已知鏈表顛倒排列, 即將鏈頭當(dāng)鏈尾,鏈尾當(dāng)鏈頭。,顛倒前的狀態(tài),顛倒后的狀態(tài),90,【例7.13】鏈表顛倒圖示,顛倒前,第1次循環(huán),第2次循環(huán),,,,第3次循環(huán),head = v2-next,v1 = v2,v2 = head,v2-next = v1,91,void reverse(intNode *h) intNode *p, *v1, *v2; v1 = NULL; /* v1指向v2前一個(gè)表元,初值指向NULL */ v2 = h-next; /* v2 指向要顛倒的表元,初值指向首表元 */ while (v2 != NULL) /* 還
57、未顛倒完,循環(huán) */ p = v2-next;/* p 指向v2的后繼表元 */ v2-next = v1; /* v2所指表元的后繼表元是v1所指表元 */ v1 = v2; /* 調(diào)整v1的指向,即指向下一個(gè)表元 */ v2 = p; /* 調(diào)整v2的指向,即指向下一個(gè)表元 */ h= v1; /* 原鏈表的最后一個(gè)表元變?yōu)槭妆碓?*/ return; ,【例7.13】鏈表顛倒函數(shù),92,聯(lián)合類型和結(jié)構(gòu)類型類似,都可以定義和使用不同類型的成員數(shù)據(jù)。 但在聯(lián)合類型中,所有成員是共享同一個(gè)存儲空間,任一時(shí)刻只存儲其中一個(gè)成員。因此,聯(lián)合也被稱之為共用體。 聯(lián)合的目的是
58、表達(dá)某種數(shù)據(jù)在不同時(shí)刻取不同類型的值。,7.5 聯(lián)合,93,格式:union 聯(lián)合類型名 成員說明表 ; 例如:union Data int ival; char chval; float fval; ; 表示:定義一個(gè)名為Data的聯(lián)合類型,能存儲整型、字符型或浮點(diǎn)型的數(shù)據(jù)。,1. 聯(lián)合類型與聯(lián)合變量的定義,94,在程序中如果要使用聯(lián)合類型的數(shù)據(jù),就必須定義聯(lián)合變量。定義聯(lián)合變量也與定義結(jié)構(gòu)變量一樣,可以先定義聯(lián)合類型再定義聯(lián)合變量,也可在定義聯(lián)合類型同時(shí)定義聯(lián)合變量。 例如,以上已定義了聯(lián)合類型Data,再定義聯(lián)合變量: union Data x, y
59、; /*C語言句法*/ Data a, b; //C++句法,1. 聯(lián)合類型與聯(lián)合變量的定義,也可以聯(lián)合類型與聯(lián)合變量一起定義。例如: union Data int ival; char chval; float fval; u, v;,95,格式:聯(lián)合變量名.成員名 例如:前面定義了聯(lián)合類型Data及聯(lián)合變量x、y,下面就可以正確地引用了。 x.ival/* 引用聯(lián)合變量x的成員ival */ y.chval/* 引用聯(lián)合變量y的成員chval */ 注意:只引用聯(lián)合變量是錯(cuò)誤的。 例如:printf(%d, x);/* 錯(cuò)誤的引用 */ 說明:這是因?yàn)槁?lián)合變量中的存儲的是某個(gè)成員
60、的值,不存儲聯(lián)合的所有成員。,2. 聯(lián)合變量中成員的引用,96,(1) 一個(gè)聯(lián)合可以存放多種不同類型的數(shù)據(jù),但實(shí)際上只存儲著其中的一種數(shù)據(jù),而不是同時(shí)存放著多種數(shù)據(jù)。存于聯(lián)合中的值是最近一次存入的值。存入新值后,原有的值就全部或部分被新值所覆蓋。 例如:x.ival = 1; x.fval = 2.0; x.chval= ?; 完成以上三個(gè)賦值后,只有x.chval是有效的,而x.ival或x.fval中的值已經(jīng)變成無意義的了。,使用聯(lián)合變量注意1,97,(2) 聯(lián)合類型變量定義時(shí)可以初始化,但只能對該變量的第一個(gè)成員置初值。 例如:Data x = 1; /* 將數(shù)值1賦給x的ival
61、成員,注意花括號是必須的 */ 下面的寫法是錯(cuò)誤的。 Data x = 1, 2.0, ?;/* 不能同時(shí)給3個(gè)成員賦值 */,使用聯(lián)合變量注意2,98,(3) 聯(lián)合變量的開始地址和它的成員變量的開始地址是相同。例如, /* 給聯(lián)合變量u賦一個(gè)long型值 */ 則u.s0、u.s1、u.s2、u.s3是對long類型值按照字節(jié)的分拆。,使用聯(lián)合變量注意3,99,(4) 函數(shù)的形參類型不能是聯(lián)合類型,函數(shù)的結(jié)果類型也不能是聯(lián)合類型。但指向聯(lián)合的指針可以作為函數(shù)形參,函數(shù)也可以返回指向聯(lián)合的指針。 (5) 聯(lián)合可出現(xiàn)在結(jié)構(gòu)類型中,聯(lián)合也可包含有結(jié)構(gòu)和數(shù)組。引用結(jié)構(gòu)中的聯(lián)合,或聯(lián)合中的結(jié)構(gòu)與引用
62、嵌套結(jié)構(gòu)成員的書寫形式完全一樣 。,使用聯(lián)合變量注意4、5,100,在某些應(yīng)用中,需要標(biāo)志某些對象的狀態(tài)或特征。這可分別用一個(gè)機(jī)器字中的一位二進(jìn)制位或連續(xù)若干二進(jìn)制位代表不同屬性的狀態(tài)。例如,某臺計(jì)算機(jī)配置的磁盤機(jī)中的控制狀態(tài)寄存器的字長為16位(自右至左,第0位至第15位)。設(shè)某些位的意義如下: 第15位: 置 1 表示數(shù)據(jù)傳送發(fā)生錯(cuò)誤; 第7位 : 置 1 表示設(shè)備已準(zhǔn)備好,可傳送數(shù)據(jù); 第6位 : 置 1 允許響應(yīng)中斷; 第2位 : 置 1 表示讀; 第1位 : 置 1 表示寫。,7.6 位域,101,實(shí)現(xiàn)上述要求可以給對應(yīng)字中的某些二進(jìn)位定義一系列表示特征的代碼。如 #def
63、ine ERROR 0100000 /* 對應(yīng)第 15 位錯(cuò)誤標(biāo)志 */ #define READY 0200 /* 對應(yīng)第 7 位準(zhǔn)備好 */ #define IENABLE 0100 /* 對應(yīng)第 6 位允許中斷 */ #define READ 04 /* 對應(yīng)第 2 位讀 */ #define WRITE 02 /* 對應(yīng)第 1 位寫 */,7.6 位域,102,在編譯程序處理符號表時(shí),為了區(qū)分每個(gè)標(biāo)識符的類別屬性,如變量名,函數(shù)名,類型名,及全局的,靜態(tài)的等。描述類別屬性的最簡單方法是把表示類別屬性的字符或整數(shù)中的某些二進(jìn)位作為標(biāo)志位使用。例如: #define VA
64、RIABLE O1 /* 第 0 位表示變量名 */ #define FUNCTION 02 /* 第 1 位表示函數(shù)名 */ #define TYPE 04 /* 第 2 位表示類型名 */ #define EXTERNAL 010 /* 第 3 位表示外部的 */ #define STATICAL 020 /* 第 4 位表示靜態(tài)的 */ 通常稱這種表示法為字位標(biāo)志法,所有的數(shù)字必定是2的若干次冪。對這些位可以進(jìn)行移位、屏蔽、求補(bǔ)等運(yùn)算,就能實(shí)現(xiàn)對屬性值的測試,存儲等。,7.6 位域,103,例1: flg = VARIABLE | EXTERNAL | STATICAL; 表
65、示:將flg置成變量,全局,靜態(tài)的。 例2: flg 表示:將flg置成非變量,非全局,非靜態(tài)的。 說明:利用提供的位域機(jī)制,能直接定義和存取字中的字段。字段是機(jī)器字存儲單元中的一串連續(xù)的二進(jìn)位。字段的定義和存取的方法建立在結(jié)構(gòu)基礎(chǔ)上。,7.6 位域,104,struct id_atr unsigned variable :1; unsigned function :1; unsigned type :1; unsigned external :1; unsigned statical :1; ; struct id_atr flg; 說明:flg 包含五個(gè)字段,其中每個(gè)字段的
66、長度均為1。為特別強(qiáng)調(diào)它們是無正負(fù)號的量,定義它們是 unsigned 型的。,7.6 位域,字段名,字段長度,105,struct ins_type unsigned op :6; /* 操作碼占前 6 位 */ unsigned flg :2; /* 特征碼占 2 位 */ unsigned operand1 :4; /* 第一操作數(shù)占 4 位 */ unsigned operand2 :4; /* 第二操作數(shù)占 4 位 */ instruction ; 引用字段的方法(類似于引用結(jié)構(gòu)的成員): 如:instruction.op表示引用instruction的op字段。另外,字段可以認(rèn)為是一個(gè)無符號整數(shù),像別的整數(shù)一樣可出現(xiàn)在算術(shù)表達(dá)式中。 如:flg.variable = flg.external = flg.statical = 1;,7.6 位域,106,條件:if (flg.extermal==0 表示:測試flg的相應(yīng)位是否都為0。 說明: 1. 一個(gè)字段只能在同一個(gè)整數(shù)字中,即限制字段不能跨越整數(shù)字的邊界。如果剩余的位太少不夠下一個(gè)字段時(shí),下一個(gè)字段將占用下一個(gè)整
- 溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 導(dǎo)游服務(wù)技能
- 德國BASLER_品牌發(fā)布會方案
- 第1章聲現(xiàn)象(共27張PPT)分解
- 華為公司戰(zhàn)略規(guī)劃(PPT35頁)
- 文明交往禮為先課件
- 《小獅子愛爾莎》課件3(教育精品)
- 高三化學(xué)上學(xué)期燃料電池復(fù)習(xí)專題
- 中國移動企業(yè)文化理念體系宣講稿件
- 上海來福士廣場智能商場體驗(yàn)活動方案Final(備份
- 節(jié)點(diǎn)電壓法經(jīng)典例題85299課件
- 腳手架荷載計(jì)算課件
- 有機(jī)化學(xué)酸堿理論
- 2013外研版英語七年級下冊M4_U2
- 某汽車鑄件質(zhì)量管理措施課件
- 第1講 種群的特征和數(shù)量變化