版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第9章
用戶可建立的數(shù)據(jù)類型——復(fù)雜數(shù)據(jù)
的表示與處理9.1結(jié)構(gòu)體9.2共用體9.3枚舉類型9.4用戶自定義數(shù)據(jù)類型名稱9.5用結(jié)構(gòu)體和指針處理鏈表實(shí)訓(xùn)任務(wù)十七
熟悉結(jié)構(gòu)體、共用體數(shù)據(jù)類型的表示與使用實(shí)訓(xùn)任務(wù)十八
學(xué)習(xí)復(fù)雜數(shù)據(jù)表示處理的編程方法 9.1結(jié)
構(gòu)
體
9.1.1結(jié)構(gòu)體類型與結(jié)構(gòu)體變量的定義
1.先定義結(jié)構(gòu)體類型,再定義結(jié)構(gòu)體變量
定義結(jié)構(gòu)體類型的一般形式為
其中,“struct”為結(jié)構(gòu)體類型定義關(guān)鍵字,是結(jié)構(gòu)體類型的標(biāo)識(shí)符?!敖Y(jié)構(gòu)體類型名”是所定義結(jié)構(gòu)體的類型名稱,這個(gè)名字由用戶命名,其命名同變量名、數(shù)組名一樣,要符合C語(yǔ)言的標(biāo)識(shí)符命名規(guī)則。用戶可以用該類型名來(lái)定義結(jié)構(gòu)體變量?;ɡㄌ?hào)中定義該結(jié)構(gòu)體類型所包含的成員,即成員的類型、名稱及其順序關(guān)系。成員名的命名規(guī)則與標(biāo)識(shí)符命名規(guī)則相同。成員類型可以是基本類型或者任何在該結(jié)構(gòu)體類型之前已經(jīng)定義過(guò)的自定義類型。結(jié)構(gòu)體類型的定義僅是聲明了一種數(shù)據(jù)對(duì)象的結(jié)構(gòu)類型,僅表示一種抽象結(jié)構(gòu),并不代表具體的數(shù)據(jù)對(duì)象,編譯系統(tǒng)也不分配存儲(chǔ)空間,不能在程序中引用。要使所定義的結(jié)構(gòu)體類型代表一個(gè)數(shù)據(jù)對(duì)象,需定義結(jié)構(gòu)體類型變量。定義結(jié)構(gòu)體類型變量的一般方式為
struct結(jié)構(gòu)體類型名變量名;
其中,“struct結(jié)構(gòu)體類型名”代表一種結(jié)構(gòu)體類型,其后的變量名就被定義為可表示該結(jié)構(gòu)體類型的變量,變量表示具有該結(jié)構(gòu)體的實(shí)體對(duì)象,編譯系統(tǒng)給結(jié)構(gòu)體變量按結(jié)構(gòu)體成員順序與類型分配存儲(chǔ)空間。
“date”是結(jié)構(gòu)體類型的名稱,year、month和day分別是整型數(shù)據(jù)成員的名稱,表示日期中的年、月、日。
定義了結(jié)構(gòu)體類型之后,就可以用該類型來(lái)定義結(jié)構(gòu)體變量。如:
structdatedate1;
“date1”是被定義為表示日期類型的結(jié)構(gòu)體變量。其存儲(chǔ)結(jié)構(gòu)是連續(xù)分配3個(gè)整型數(shù)據(jù)的單元,一個(gè)整型數(shù)據(jù)占4個(gè)字節(jié),共占12個(gè)字節(jié)的存儲(chǔ)空間。
結(jié)構(gòu)體類型定義中,成員類型可以是已經(jīng)定義過(guò)的任何一種數(shù)據(jù)對(duì)象的類型。例如,在定義了日期結(jié)構(gòu)體類型的基礎(chǔ)上,可定義一個(gè)學(xué)生信息的結(jié)構(gòu)體類型:學(xué)生結(jié)構(gòu)體類型定義中包含日期結(jié)構(gòu)體成員birthday,即結(jié)構(gòu)體類型可以嵌套定義。但是,結(jié)構(gòu)體不允許遞歸定義,即結(jié)構(gòu)體的成員不能為該結(jié)構(gòu)體的變量。如,下面的定義是非法的:
在定義了“student”結(jié)構(gòu)體類型的基礎(chǔ)上,可以定義該結(jié)構(gòu)體類型的變量:
structstudentstudent1,student2;
從上述可以看出,由一個(gè)結(jié)構(gòu)體類型可以定義多個(gè)結(jié)構(gòu)體變量。
2.在定義結(jié)構(gòu)體類型的同時(shí)定義結(jié)構(gòu)體變量
該方式定義的一般形式為
從上述可知,定義結(jié)構(gòu)體類型的目的是定義結(jié)構(gòu)體變量,只有結(jié)構(gòu)體變量才能存儲(chǔ)和處理結(jié)構(gòu)體數(shù)據(jù),前兩種方式定義了結(jié)構(gòu)體類型名稱,可以使用這種結(jié)構(gòu)體類型名稱來(lái)定義新的結(jié)構(gòu)體變量。第3種定義方式,沒(méi)用結(jié)構(gòu)體類型名,無(wú)法利用結(jié)構(gòu)體類型名來(lái)定義新的結(jié)構(gòu)體變量。
結(jié)構(gòu)體成員可以與程序中的其他變量同名,兩者代表不同對(duì)象,互不影響。結(jié)構(gòu)體的定義可以放在函數(shù)內(nèi),也可以放在函數(shù)外。在函數(shù)內(nèi)定義的結(jié)構(gòu)體只能在函數(shù)內(nèi)使用(即局部數(shù)據(jù)對(duì)象)。在函數(shù)外定義的結(jié)構(gòu)體可以在定義點(diǎn)之后的所有函數(shù)內(nèi)使用(全局?jǐn)?shù)據(jù)對(duì)象)。
9.1.2結(jié)構(gòu)體變量的初始化
如何給結(jié)構(gòu)體變量提供初始數(shù)據(jù)?
定義了結(jié)構(gòu)體變量后,系統(tǒng)按成員的順序和類型給其分配存儲(chǔ)空間,但成員沒(méi)有指定的數(shù)據(jù)。對(duì)結(jié)構(gòu)體提供數(shù)據(jù)是針對(duì)成員來(lái)進(jìn)行的,也就是說(shuō),不能對(duì)結(jié)構(gòu)體整體進(jìn)行,這與數(shù)組類似。對(duì)結(jié)構(gòu)體成員提供數(shù)據(jù)有兩種方式,一種是在定義結(jié)構(gòu)體變量時(shí)提供初始值,稱為初始化;還有一種是在程序運(yùn)行中,通過(guò)賦值操作給成員提供值。一般在定義結(jié)構(gòu)體變量時(shí),需進(jìn)行初始化。結(jié)構(gòu)體變量初始化的方式是:按結(jié)構(gòu)體成員的順序和類型分別提供初始數(shù)據(jù)。例如,對(duì)前面定義的學(xué)生結(jié)構(gòu)體變量初始化如下:
structstudentstudent1={0103208,"liuxiqiao",'w',{1983,9,17}};
給結(jié)構(gòu)體變量賦初值要用花括號(hào)將所有成員數(shù)據(jù)括起來(lái)。在花括號(hào)中要按成員順序提供初始數(shù)據(jù),數(shù)據(jù)類型要與定義的成員類型一致。例如“姓名”成員是字符數(shù)組,可以通過(guò)字符串提供初值,也可以按字符數(shù)組元素的方式提供初值?!俺錾掌凇背蓡T是一個(gè)結(jié)構(gòu)體類型,要按定義的日期結(jié)構(gòu)體來(lái)提供初值,其年、月、日數(shù)據(jù)用花括號(hào)括起來(lái)。
9.1.3結(jié)構(gòu)體成員的引用
如何引用結(jié)構(gòu)體變量中的數(shù)據(jù)?
系統(tǒng)把結(jié)構(gòu)體變量看作一個(gè)數(shù)據(jù)對(duì)象,給其分配數(shù)據(jù)空間,按成員的順序和類型連續(xù)存儲(chǔ)數(shù)據(jù),但對(duì)結(jié)構(gòu)體變量的數(shù)據(jù)不能整體引用,只能按成員來(lái)引用。結(jié)構(gòu)體數(shù)據(jù)的引用方式與數(shù)組數(shù)據(jù)的引用方式類似。
結(jié)構(gòu)體成員引用的形式為
結(jié)構(gòu)體變量名.成員名
其中,“.”是C語(yǔ)言的一種運(yùn)算符,稱為“取成員運(yùn)算符”?!?”的優(yōu)先級(jí)是C語(yǔ)言中優(yōu)先級(jí)最高的運(yùn)算符,具有左結(jié)合性(參見(jiàn)附錄C)。例如,前面定義的一個(gè)學(xué)生信息的結(jié)構(gòu)體變量,student1.num表示學(xué)號(hào)成員數(shù)據(jù)項(xiàng)。
如果成員又是一個(gè)結(jié)構(gòu)體類型,則要分層用成員運(yùn)算符,一級(jí)一級(jí)地找到最基本的成員。例如,要引用一個(gè)學(xué)生信息的結(jié)構(gòu)體變量中的出生日期數(shù)據(jù),要分別采用如下的引用
形式:
student1.birthday.year
student1.birthday.month
student1.birthday.day
不能用student1.birthday來(lái)引用出生日期數(shù)據(jù)。可以對(duì)結(jié)構(gòu)體變量中的成員進(jìn)行輸入、輸出、賦值、運(yùn)算等操作。
對(duì)結(jié)構(gòu)體成員輸入數(shù)據(jù),要取成員地址。例如:
scanf("%ld",&student1.num);
一個(gè)成員變量可以像基本類型變量一樣進(jìn)行相應(yīng)的運(yùn)算。例如:
sum=student1.age+student2.age;
age++;
例9.1
定義一個(gè)學(xué)生成績(jī)表的數(shù)據(jù)結(jié)構(gòu),學(xué)生信息包含學(xué)號(hào)、姓名、出生日期,有5門(mén)課成績(jī),從鍵盤(pán)輸入數(shù)據(jù),求出學(xué)生總分,輸出學(xué)生數(shù)據(jù)和總分。
編程思路:學(xué)生成績(jī)表包含許多學(xué)生數(shù)據(jù),每個(gè)學(xué)生具有相同的數(shù)據(jù)結(jié)構(gòu),屬于典型的結(jié)構(gòu)體類型數(shù)據(jù)。先定義學(xué)生數(shù)據(jù)結(jié)構(gòu),再定義學(xué)生數(shù)據(jù)結(jié)構(gòu)的變量。學(xué)生信息的輸入和處理要針對(duì)成員數(shù)據(jù)來(lái)進(jìn)行。
運(yùn)行結(jié)果:
分析:在程序中定義兩個(gè)結(jié)構(gòu)體類型,學(xué)生結(jié)構(gòu)中嵌套了日期結(jié)構(gòu),形成了嵌套結(jié)構(gòu)。定義了結(jié)構(gòu)體變量s來(lái)表示具體學(xué)生的結(jié)構(gòu)數(shù)據(jù)。從程序及其運(yùn)行結(jié)果可以看出,結(jié)構(gòu)體成員的輸入/輸出只能按基本類型數(shù)據(jù)元素來(lái)進(jìn)行。例如,輸入成員數(shù)組元素采用語(yǔ)句“scanf("%f",&s.score[i]);”,輸出成員數(shù)組元素采用語(yǔ)句“printf("Score%d:%-6.1f",i,s.score[i]);”。
9.1.4結(jié)構(gòu)體數(shù)組
批量結(jié)構(gòu)體類型數(shù)據(jù)如何表示與處理?
在實(shí)際應(yīng)用中,經(jīng)常遇到結(jié)構(gòu)體類型的批量數(shù)據(jù),如一個(gè)班級(jí)的學(xué)生信息。一個(gè)學(xué)生的基本信息是一個(gè)結(jié)構(gòu)體類型數(shù)據(jù),一個(gè)班級(jí)的學(xué)生基本信息就是一個(gè)結(jié)構(gòu)體數(shù)組。C語(yǔ)言允許定義結(jié)構(gòu)體數(shù)組。
構(gòu)體數(shù)組是復(fù)合型構(gòu)造數(shù)據(jù)類型,即結(jié)構(gòu)體數(shù)組中所有元素是同一類型的結(jié)構(gòu)體數(shù)據(jù)對(duì)象,一個(gè)元素是一個(gè)結(jié)構(gòu)體數(shù)據(jù)對(duì)象。所以,結(jié)構(gòu)體數(shù)組的定義、初始化和元素引用方法都是數(shù)組和結(jié)構(gòu)體中方法的類推。因?yàn)榻Y(jié)構(gòu)體數(shù)組元素是用戶自定義的結(jié)構(gòu)體類型,所以定義結(jié)構(gòu)體數(shù)組應(yīng)先定義元素的結(jié)構(gòu)體類型,然后再按已定義的結(jié)構(gòu)體類型定義數(shù)組。其定義方式與結(jié)構(gòu)體變量的定義方式相仿。只要在結(jié)構(gòu)體變量定義中的變量名位置寫(xiě)上數(shù)組定義符號(hào)即可。結(jié)構(gòu)體數(shù)組定義也有與結(jié)構(gòu)體變量定義對(duì)應(yīng)的3種方式。若已定義了結(jié)構(gòu)體類型(具有結(jié)構(gòu)體類型名),則一維結(jié)構(gòu)體數(shù)組定義的一般形式為
struct結(jié)構(gòu)體類型名
數(shù)組名[數(shù)組長(zhǎng)度];
其中,“struct結(jié)構(gòu)體類型名”是已經(jīng)定義過(guò)的結(jié)構(gòu)體類型,其他和數(shù)組定義一樣。另外兩種定義方式,在后面的例子中說(shuō)明。同樣也可定義二維結(jié)構(gòu)體數(shù)組。二維結(jié)構(gòu)體數(shù)組不太常用,不再細(xì)述。結(jié)構(gòu)體數(shù)組的初始化是先按元素順序,再按元素的結(jié)構(gòu)體成員順序與類型來(lái)提供初始數(shù)據(jù)。所以就形成了按元素順序,依次對(duì)結(jié)構(gòu)體成員初始化的過(guò)程。
對(duì)結(jié)構(gòu)體數(shù)組元素的引用也是先引用數(shù)組元素(結(jié)構(gòu)體對(duì)象),再引用該元素中的結(jié)構(gòu)體成員。
下面通過(guò)一個(gè)實(shí)例來(lái)說(shuō)明結(jié)構(gòu)體數(shù)組的定義、初始化和引用的方法。
例9.2
構(gòu)造一個(gè)班一門(mén)課程成績(jī)表的數(shù)據(jù)結(jié)構(gòu),初始化成績(jī)表信息,查找出不及格學(xué)生,并輸出該學(xué)生的全部信息。成績(jī)表信息包括學(xué)號(hào)、姓名、課程、成績(jī)。
編程思路:學(xué)生基本信息包含不同類型數(shù)據(jù),應(yīng)是一個(gè)結(jié)構(gòu)體類型。一個(gè)班成績(jī)表應(yīng)是結(jié)構(gòu)體數(shù)組。所以,采用結(jié)構(gòu)體數(shù)組進(jìn)行處理。為簡(jiǎn)化數(shù)據(jù),說(shuō)明處理方法,程序中只對(duì)5個(gè)學(xué)生信息進(jìn)行處理。
運(yùn)行結(jié)果:
分析:
(1)在程序開(kāi)頭定義了一個(gè)結(jié)構(gòu)體類型,同時(shí)定義了結(jié)構(gòu)體數(shù)組st[5],又對(duì)數(shù)組進(jìn)行了初始化。內(nèi)層一個(gè)花括號(hào)對(duì)應(yīng)一個(gè)數(shù)組元素,花括號(hào)內(nèi)的數(shù)據(jù)對(duì)應(yīng)一個(gè)結(jié)構(gòu)體成員的數(shù)據(jù)??梢钥闯?,數(shù)據(jù)類型與所定義的成員類型一一對(duì)應(yīng)。如果去掉結(jié)構(gòu)體類型名“student”,或者把結(jié)構(gòu)體數(shù)組定義放在主函數(shù)中,用“structstudentst[5];”定義,程序都能正確運(yùn)行。請(qǐng)讀者自行驗(yàn)證。
(2)在程序中求總分和輸出不及格學(xué)生的信息中都采用了“數(shù)組名[i].成員名”的引用形式,表示引用數(shù)組第i個(gè)元素中指定的成員數(shù)據(jù)。如“st[2].score”是引用結(jié)構(gòu)體數(shù)組第2個(gè)元素的結(jié)構(gòu)體成員score的值(即對(duì)應(yīng)數(shù)組中的第2個(gè)學(xué)生的成績(jī))。
從上例可以看出,只要掌握結(jié)構(gòu)體數(shù)組復(fù)合層次關(guān)系,類推數(shù)組元素的引用到結(jié)構(gòu)體成員的引用方法,對(duì)結(jié)構(gòu)體數(shù)組的引用就不難理解。最終都類推到對(duì)基本變量的引用上。
9.1.5結(jié)構(gòu)體指針
何謂結(jié)構(gòu)體指針?如何通過(guò)結(jié)構(gòu)體指針引用其數(shù)據(jù)?
定義了結(jié)構(gòu)體類型與結(jié)構(gòu)體變量后,系統(tǒng)給結(jié)構(gòu)體數(shù)據(jù)分配一個(gè)存儲(chǔ)空間,按照成員順序連續(xù)存儲(chǔ),按成員類型分別占據(jù)不同字節(jié)的存儲(chǔ)長(zhǎng)度,每個(gè)成員都有確定的存儲(chǔ)地址,結(jié)構(gòu)體數(shù)據(jù)對(duì)象的首地址就是結(jié)構(gòu)體的指針。對(duì)結(jié)構(gòu)體數(shù)據(jù)也有兩種訪問(wèn)方式:直接訪問(wèn)和間接訪問(wèn)。前面講的“結(jié)構(gòu)體變量名·成員名”訪問(wèn)方式就是直接訪問(wèn),也可以通過(guò)指向結(jié)構(gòu)類型的指針變量,來(lái)間接訪問(wèn)結(jié)構(gòu)體數(shù)據(jù)。結(jié)構(gòu)體數(shù)組存儲(chǔ)結(jié)構(gòu)也同樣保持結(jié)構(gòu)的復(fù)合關(guān)系,先按元素順序連續(xù)存儲(chǔ),再按成員順序和類型分配存儲(chǔ)空間。每一個(gè)結(jié)構(gòu)體元素及其成員都有確定的存儲(chǔ)地址。對(duì)結(jié)構(gòu)體數(shù)組數(shù)據(jù)也有兩種訪問(wèn)方式?!皵?shù)組名[下標(biāo)]·成員名”是直接訪問(wèn)。同樣,也可以通過(guò)指向結(jié)構(gòu)體數(shù)組的指針變量來(lái)間接訪問(wèn)。
掌握了指針及指針變量的實(shí)質(zhì)意義,通過(guò)指針變量來(lái)訪問(wèn)結(jié)構(gòu)體及結(jié)構(gòu)體數(shù)組就不難理解了。指向結(jié)構(gòu)體對(duì)象的指針變量可指向結(jié)構(gòu)體數(shù)據(jù),也可指向結(jié)構(gòu)體數(shù)組中的元素。指向結(jié)構(gòu)體的指針變量定義、賦初值及通過(guò)指針變量引用數(shù)據(jù)的方法同普通指針變量相仿。只是要用自定義的結(jié)構(gòu)體類型來(lái)定義指針變量,取結(jié)構(gòu)體類型變量地址賦給指針變量,即可建立指向。例如:
structstudentst; //定義結(jié)構(gòu)體變量
structstudent*p; //定義指向結(jié)構(gòu)體指針變量
p=&st; //使p指向結(jié)構(gòu)體變量st通過(guò)指針變量對(duì)結(jié)構(gòu)體數(shù)據(jù)的引用有兩種方式:
方式一:
(*指針變量名)·成員名
例如:
(*p)?name;
方式二:
指針變量名->成員名
例如:
p->name;
這兩種方式是等價(jià)的,可以相互取代。注意:指針變量名兩側(cè)的括號(hào)是不能缺省的。
1.通過(guò)結(jié)構(gòu)體指針變量來(lái)引用結(jié)構(gòu)體成員值或結(jié)構(gòu)體數(shù)組中的成員值
下面通過(guò)兩個(gè)例子來(lái)說(shuō)明通過(guò)指針變量來(lái)引用結(jié)構(gòu)體數(shù)據(jù)和結(jié)構(gòu)體數(shù)組元素。
例9.3
通過(guò)指向結(jié)構(gòu)體變量的指針變量輸出結(jié)構(gòu)體變量中成員的信息。
編程思路:為了便于對(duì)比,仍以學(xué)生信息表數(shù)據(jù)為例。
運(yùn)行結(jié)果:
分析:在主函數(shù)中定義學(xué)生信息結(jié)構(gòu)體類型的同時(shí)定義了結(jié)構(gòu)體變量st,并進(jìn)行了初始化。接著定義了指向結(jié)構(gòu)體類型的指針變量p,&st賦給p,使其指向結(jié)構(gòu)體變量st。兩個(gè)printf函數(shù)調(diào)用中,分別采用結(jié)構(gòu)體變量名引用法和指針變量引用法,輸出結(jié)果完全一樣,但意義有所不同,結(jié)構(gòu)體變量名表示結(jié)構(gòu)體數(shù)據(jù)的地址是固定的,指針變量的指向是可以變化的。
分析:程序中定義了指向結(jié)構(gòu)體類型的指針變量ps,把數(shù)組名表示的數(shù)組首地址賦給ps。在for循環(huán)中,“ps=st”使ps指向數(shù)組首元素,“ps++”是數(shù)組邏輯指針的調(diào)整,即使ps指向下一個(gè)元素(結(jié)構(gòu)體成員),“ps<st+5”中的st+5仍是一個(gè)邏輯指針,表示ps指向最末一個(gè)元素后結(jié)束,最末一個(gè)元素的指針是st+4。
2.用結(jié)構(gòu)體變量和結(jié)構(gòu)體變量的指針作函數(shù)參數(shù)
從前述已經(jīng)知道,變量作函數(shù)參數(shù),實(shí)參向形參單向傳遞變量的值;指針作函數(shù)參數(shù),實(shí)參向形參傳遞地址,使實(shí)參和形參共同指向一個(gè)存儲(chǔ)單元或存儲(chǔ)區(qū),使主調(diào)函數(shù)和被調(diào)函數(shù)共享存儲(chǔ)單元或存儲(chǔ)區(qū)中的數(shù)據(jù)。同樣,結(jié)構(gòu)體變量作函數(shù)參數(shù),實(shí)參向形參傳遞結(jié)構(gòu)體變量中的成員值,即傳遞的是不同類型的多個(gè)數(shù)據(jù);結(jié)構(gòu)體變量的指針作函數(shù)的參數(shù),實(shí)參向形參傳遞結(jié)構(gòu)體數(shù)據(jù)對(duì)象的地址,使主調(diào)函數(shù)和被調(diào)函數(shù)能共享結(jié)構(gòu)體存儲(chǔ)空間的成員數(shù)據(jù),即能實(shí)現(xiàn)結(jié)構(gòu)體成員數(shù)據(jù)的雙向傳遞。下面通過(guò)實(shí)例來(lái)說(shuō)明,請(qǐng)認(rèn)真理解。
例9.5
設(shè)一個(gè)班有3門(mén)課程的成績(jī)表,學(xué)生學(xué)號(hào)、姓名已存入系統(tǒng),從鍵盤(pán)上錄入學(xué)生3門(mén)課成績(jī),求每個(gè)學(xué)生的平均成績(jī),并將平均成績(jī)最高的學(xué)生信息輸出。
編程思路:學(xué)生成績(jī)表屬于結(jié)構(gòu)體數(shù)組結(jié)構(gòu)。從功能上可由3個(gè)函數(shù)來(lái)實(shí)現(xiàn),顯示學(xué)生學(xué)號(hào)、姓名,錄入3門(mén)課成績(jī),同時(shí)求平均成績(jī);找出最高平均成績(jī);輸出平均成績(jī)最高的學(xué)生信息。
運(yùn)行結(jié)果:分析:
(1)定義學(xué)生成績(jī)結(jié)構(gòu)體類型,同時(shí)定義結(jié)構(gòu)體數(shù)組,只給學(xué)號(hào)、姓名成員賦初值;
(2)定義成績(jī)錄入并求平均分函數(shù)input,結(jié)構(gòu)體數(shù)組名作參數(shù),系統(tǒng)把數(shù)組名看作指針變量,接收實(shí)參傳遞的指針。屏幕上顯示學(xué)號(hào)、姓名,只輸入3門(mén)課成績(jī)。外循環(huán)控制錄入第i個(gè)學(xué)生成績(jī),內(nèi)循環(huán)控制錄入第j門(mén)課成績(jī)。使用了結(jié)構(gòu)體數(shù)組元素中的成員元素的引用“st[i].score[j]”。
(3)定義找最高平均分函數(shù),結(jié)構(gòu)體數(shù)組名作形參。在循環(huán)中只比較數(shù)組元素的平均分成員項(xiàng)“st[i].aver>st[m].aver”。
(4)定義輸出學(xué)生信息函數(shù),結(jié)構(gòu)體變量作形參,接收實(shí)參傳遞的結(jié)構(gòu)體變量值(全部成員數(shù)據(jù))。
(5)函數(shù)調(diào)用,“input(p);”把指針變量p的值(結(jié)構(gòu)體數(shù)組首地址)傳遞給形參st,使p和st都指向結(jié)構(gòu)體數(shù)組,函數(shù)中錄入的成績(jī)就存入結(jié)構(gòu)體數(shù)組的成績(jī)數(shù)組中,所求平均分存入平均分成員項(xiàng)中。因?yàn)榻Y(jié)構(gòu)體數(shù)組屬于全局?jǐn)?shù)據(jù)對(duì)象,所在函數(shù)中的操作結(jié)果,可供其他函數(shù)使用。
(6)函數(shù)調(diào)用,“print(max(p));”先調(diào)用“max(p)”,把結(jié)構(gòu)體數(shù)組首地址傳遞給形參,在函數(shù)中使用結(jié)構(gòu)體數(shù)組中平均分成員數(shù)據(jù)進(jìn)行比較,返回最高平均分結(jié)構(gòu)體元素st[m],再產(chǎn)生“print(st[m]);”調(diào)用,在函數(shù)中輸出最高平均分學(xué)生的全部信息。
9.2共
用
體
9.2.1共用體類型與共用體變量的定義
共用體是用戶自定義的一種數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)類型。必須先定義類型,再定義變量,通過(guò)變量來(lái)引用共用體中的成員。
共用體定義的一般形式為
其中,union是共用體類型定義關(guān)鍵字;共用體類型名是用戶自定義的類型名稱;花括號(hào)中可以是任一類型的數(shù)據(jù)對(duì)象,包括自定義類型;共用體變量名表是用戶自定義的共用體類型變量,如果定義多個(gè)變量,變量之間要用逗號(hào)分隔。
共用體定義同結(jié)構(gòu)體相仿,也有3種定義方式。在上述定義中可以不要“共用體類型名”,也可以在定義共用體類型之后,利用已定義的共用體類型來(lái)定義變量。其一般形式為
union共用體類型名共用體變量名表;
定義了共用體類型與變量后,編譯系統(tǒng)按成員中占據(jù)存儲(chǔ)字節(jié)數(shù)最多的成員分配一個(gè)存儲(chǔ)單元或空間。
系統(tǒng)給i、ch、f按實(shí)型數(shù)據(jù)分配一個(gè)存儲(chǔ)單元,通過(guò)變量a可引用3種數(shù)據(jù)之一。其存儲(chǔ)結(jié)構(gòu)如圖9.1所示。為說(shuō)明問(wèn)題,假定整型數(shù)占2個(gè)字節(jié),實(shí)型數(shù)占4個(gè)字節(jié)。
圖9.1共用體存儲(chǔ)結(jié)構(gòu)示意圖9.2.2共用體變量引用
同結(jié)構(gòu)體數(shù)據(jù)引用相仿,共用體變量只能引用其中的成員,也有兩種引用形式。
形式一:
共用體變量名·成員名
形式二:
共用體指針變量名->成員名
因?yàn)楣灿皿w成員通過(guò)覆蓋方式共享一個(gè)存儲(chǔ)單元或空間,一個(gè)變量的瞬時(shí)值只能是一個(gè)類型的成員值,所以對(duì)共用體賦值及引用,一個(gè)時(shí)刻只能對(duì)一個(gè)成員進(jìn)行操作。這與結(jié)構(gòu)體變量是截然不同的。關(guān)于共用體變量引用的幾點(diǎn)說(shuō)明:
(1)共用體變量初始化與賦值??梢詫?duì)共用體變量初始化,在初始化表中只能有任一成員類型的常量,不能期望同時(shí)給各個(gè)成員提供初始數(shù)據(jù)。例如:
實(shí)際上是向共用體變量存入一個(gè)整型數(shù)。如初始化表為{230,'a',3.6}則是錯(cuò)誤的。
可以在程序中給共用體變量的成員賦值,但不能給共用體變量賦值。例如:
a.f=3.6;
a.ch='a';
a.i=230;
都是正確的。但如果有a=3.6則是不正確的。
如果有多次賦值,共用體變量中只是最后一次所賦的值,即后面的賦值覆蓋前面的賦值。如上面的賦值語(yǔ)句被執(zhí)行,則引用3個(gè)成員的值都是230。
(2)共用體變量的地址和成員的地址是同一地址,即有&a==&a.i==&a.ch==&a.f,因?yàn)?個(gè)成員共享一個(gè)存儲(chǔ)單元。
下面通過(guò)一個(gè)例子來(lái)說(shuō)明共用體數(shù)據(jù)的使用。
例9.6
錄入表9.1中的數(shù)據(jù),并輸出。表9.1數(shù)據(jù)信息編程思路:從表中可以看出,教師和學(xué)生信息前四項(xiàng)都是相同的,只有最后一項(xiàng)不同。如果在一個(gè)實(shí)際應(yīng)用系統(tǒng)中把學(xué)生和教師信息以單獨(dú)表的結(jié)構(gòu)來(lái)存儲(chǔ)、處理,不但會(huì)重復(fù)占據(jù)存儲(chǔ)空間,也給程序設(shè)計(jì)帶來(lái)一定的麻煩。如果把最后一項(xiàng)作共用體數(shù)據(jù)對(duì)象,將會(huì)避免上述問(wèn)題。為說(shuō)明方法,只編寫(xiě)一位教師和學(xué)生的信息處理程序。運(yùn)行結(jié)果:
分析:程序中定義了全局結(jié)構(gòu)體數(shù)組person[2],存儲(chǔ)兩個(gè)人的信息。在結(jié)構(gòu)體類型定義中嵌套定義了一個(gè)共用體變量category,其中有兩個(gè)成員,company和charposition[10],身份是學(xué)生,則存班級(jí)信息(整型數(shù)據(jù));身份是教師,則存職稱信息(字符數(shù)組)。使用共用體變量,使兩種人員信息統(tǒng)一在一個(gè)數(shù)據(jù)結(jié)構(gòu)中。人員信息輸出中,相同信息項(xiàng)作相同處理,只是對(duì)不同信息項(xiàng)作選擇處理,簡(jiǎn)化了程序設(shè)計(jì),也提高了程序效率。
9.3枚舉類型
一些事物屬性只能列舉,不具有數(shù)值關(guān)系,這些數(shù)據(jù)對(duì)象怎樣表示與處理?
現(xiàn)實(shí)中存在一些可列舉的數(shù)據(jù)對(duì)象,如一周有星期一到星期日,顏色有紅、橙、黃、綠、青、藍(lán)、紫,等等。這種數(shù)據(jù)對(duì)象只可列舉,不具有數(shù)值關(guān)系,似乎難以在計(jì)算機(jī)中處理。C語(yǔ)言允許將這類數(shù)據(jù)定義為枚舉類型,能方便地進(jìn)行處理。
枚舉類型與枚舉變量的定義也同結(jié)構(gòu)體相仿。定義的一般形式為
enum枚舉類型名
{
枚舉元素列表
}枚舉變量列表;
其中,enum為定義枚舉類型的關(guān)鍵字;枚舉類型名是用戶自定義的表示所定義枚舉類型的名稱;“枚舉元素列表”是用逗號(hào)分隔的列舉的元素名稱序列;枚舉變量列表是定義枚舉類型的同時(shí)定義的變量名。一個(gè)枚舉類型可定義多個(gè)變量,變量間用逗號(hào)分隔,就是枚舉變量列表。枚舉類型與枚舉變量定義也可有3種形式。在上面的定義中可以省略“枚舉類型名”而直接定義枚舉變量。也可以先定義枚舉類型,然后用所定義的枚舉類型來(lái)定義枚舉變量。其定義的一般形式為
enum枚舉類型名
枚舉變量列表關(guān)于枚舉數(shù)據(jù)的幾點(diǎn)說(shuō)明:
(1)枚舉元素雖以標(biāo)號(hào)列出,但C編譯系統(tǒng)按常量處理,故稱枚舉常量。在程序中不能給枚舉元素賦值,即枚舉元素相當(dāng)于一個(gè)符號(hào)常量。
(2)?C編譯系統(tǒng)對(duì)枚舉元素按定義的順序依次賦值0,1,2,3,4,5,…。在上面的定義中,Sunday的值為0,Monday的值為1,…,Saturday的值為6。也可在定義時(shí),給枚舉元素指定常量序列值。
(3)枚舉變量的取值范圍是列舉元素值的范圍。如Sunday只可能取0~7之間的一個(gè)整數(shù)。
(4)由于枚舉型變量的值是整數(shù),因此C99標(biāo)準(zhǔn)中也把枚舉型作為整型數(shù)據(jù),用整型變量來(lái)表示枚舉型元素值。
下面通過(guò)一個(gè)例子來(lái)說(shuō)明枚舉數(shù)據(jù)的應(yīng)用。
例9.7
一個(gè)盒子中有紅、黃、藍(lán)3種顏色的球若干,每次從盒子中先后取出3個(gè)球,編程求解取不同顏色球的排列數(shù),并輸出每種顏色排列。
編程思路:定義3種顏色的枚舉類型,再定義3個(gè)枚舉類型或整型變量i、j、k,分別表示3個(gè)球的顏色值,然后用枚舉算法求取出3個(gè)球的顏色排列數(shù)。
枚舉算法:當(dāng)取出的兩個(gè)球顏色不同(i≠j)時(shí),取第3個(gè)球。如果第3個(gè)球與前兩個(gè)球顏色都不同(k≠i且k≠j),則是一次有效排列取法,計(jì)數(shù)一次。如此,i、j、k依次取3種顏色值之一,進(jìn)行判斷,可得到求解結(jié)果。顯然應(yīng)該用三重循環(huán)來(lái)實(shí)現(xiàn)。
運(yùn)行結(jié)果:
分析:
(1)定義了3種顏色的枚舉類型后,編譯時(shí),3種顏色標(biāo)號(hào)依次具有值0、1、2。
(2)定義i、j、k、pri表示顏色取值變量,等價(jià)于枚舉變量。
(3)三重循環(huán)實(shí)現(xiàn)3次取球的顏色排列。第3層內(nèi)循環(huán)的if語(yǔ)句要執(zhí)行27次,實(shí)現(xiàn)3次取球的顏色排列判斷。當(dāng)判斷出3個(gè)球的顏色不同時(shí),則計(jì)數(shù)變量n+1,將顏色值轉(zhuǎn)換成顏色字符輸出。
(4)將顏色值轉(zhuǎn)換成顏色字符輸出,由if語(yǔ)句中嵌套的for循環(huán)來(lái)實(shí)現(xiàn)。當(dāng)判斷3個(gè)球顏色不同時(shí),由switch(loop)分別將i、j、k當(dāng)前值賦給pri,再由switch(pri)輸出顏色值對(duì)應(yīng)的顏色字符。
(5)使用枚舉類型,使枚舉元素標(biāo)號(hào)具有整型值,可以很方便地進(jìn)行比較判斷和相應(yīng)的運(yùn)算。
(6)只要在枚舉類型中添加顏色元素,再于循環(huán)中更改最后一個(gè)顏色的取值,即可實(shí)現(xiàn)更多種顏色的取球模型求解。取球模型代表了隨機(jī)抽樣一類應(yīng)用問(wèn)題。
9.4用戶自定義數(shù)據(jù)類型名稱
1.用新類型名代替原有類型名
其使用的一般形式為
typedef已有類型標(biāo)識(shí)符
新類型名;
其作用是用“新類型名”代替原有類型標(biāo)識(shí)符,即為原有的一個(gè)數(shù)據(jù)類型重新命名,而不是定義一種新的數(shù)據(jù)類型。
2.用一個(gè)簡(jiǎn)單類型名代替復(fù)雜的類型
諸如數(shù)組類型、結(jié)構(gòu)體類型、共用體類型、枚舉類型等,看起來(lái)比較復(fù)雜,可用typedef定義一個(gè)簡(jiǎn)單的類型名代替復(fù)雜的類型。
9.5用結(jié)構(gòu)體和指針處理鏈表
9.5.1鏈表簡(jiǎn)介
鏈表是動(dòng)態(tài)地進(jìn)行存儲(chǔ)分配的一種數(shù)據(jù)結(jié)構(gòu),特別適合規(guī)模不確定的復(fù)雜數(shù)據(jù)結(jié)構(gòu)的批量數(shù)據(jù)表示與處理問(wèn)題。例如,在一個(gè)學(xué)生成績(jī)管理系統(tǒng)中,需要處理多個(gè)班級(jí)的學(xué)生數(shù)據(jù),每個(gè)班學(xué)生數(shù)是不固定的。采用數(shù)組可以表示成績(jī)表數(shù)據(jù),但在定義數(shù)組長(zhǎng)度時(shí)就會(huì)產(chǎn)生困惑。按人數(shù)少的班級(jí)定義數(shù)組長(zhǎng)度,人數(shù)多的班級(jí)數(shù)據(jù)不夠用,按人數(shù)多的班級(jí)定義數(shù)組長(zhǎng)度,則必然造成存儲(chǔ)空間的浪費(fèi)。采用鏈表來(lái)表示學(xué)生成績(jī)表數(shù)據(jù),可完全解除這種困惑。鏈表是把一個(gè)學(xué)生的信息看作一個(gè)數(shù)據(jù)節(jié)點(diǎn),成績(jī)表數(shù)據(jù)在存儲(chǔ)器中不連續(xù)存儲(chǔ),通過(guò)一個(gè)指針把一個(gè)班學(xué)生數(shù)據(jù)連接起來(lái),動(dòng)態(tài)地分配內(nèi)存,即可根據(jù)學(xué)生數(shù)來(lái)開(kāi)辟內(nèi)存空間。鏈表也有多種結(jié)構(gòu),一種簡(jiǎn)單的單向鏈表結(jié)構(gòu)如圖9.2所示。圖9.2一種簡(jiǎn)單的單向鏈表結(jié)構(gòu)鏈表中,與一個(gè)節(jié)點(diǎn)之前連接的節(jié)點(diǎn)稱為該節(jié)點(diǎn)的前驅(qū)節(jié)點(diǎn),與一個(gè)節(jié)點(diǎn)之后連接的節(jié)點(diǎn)稱為該節(jié)點(diǎn)的后繼節(jié)點(diǎn)。鏈表的中間節(jié)點(diǎn)包含兩個(gè)域:一是數(shù)據(jù)域,存放學(xué)生實(shí)際數(shù)據(jù);二是地址域,存放后繼節(jié)點(diǎn)的地址。每一個(gè)鏈表都有一個(gè)頭節(jié)點(diǎn),只有地址域,存放指向鏈表首節(jié)點(diǎn)的地址。每一個(gè)鏈表也有一個(gè)尾節(jié)點(diǎn),包含數(shù)據(jù)域,但地址域?yàn)榭?NULL),沒(méi)有后繼節(jié)點(diǎn)。每一個(gè)節(jié)點(diǎn)的地址都是由系統(tǒng)動(dòng)態(tài)分配的。
可以看到,表中的元素節(jié)點(diǎn)由地址連接起來(lái)。訪問(wèn)表中節(jié)點(diǎn)數(shù)據(jù),首先要提供頭指針,由頭節(jié)點(diǎn)指針連接表首元素節(jié)點(diǎn),再由此節(jié)點(diǎn)連接下一元素節(jié)點(diǎn),直到表尾節(jié)點(diǎn)。這樣的鏈接方式,如同一個(gè)鏈條,一環(huán)扣一環(huán),中間是不能斷開(kāi)的,所以稱為鏈表。
鏈表中節(jié)點(diǎn)數(shù)據(jù)對(duì)象是一個(gè)結(jié)構(gòu)體類型。學(xué)生成績(jī)表鏈表節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)可定義如下:
9.5.2建立靜態(tài)鏈表
例9.8
建立由4個(gè)學(xué)生信息節(jié)點(diǎn)組成的鏈表,并輸出各節(jié)點(diǎn)中的數(shù)據(jù)。
編程思路:定義節(jié)點(diǎn)數(shù)據(jù)對(duì)象為結(jié)構(gòu)體類型,依照連接關(guān)系設(shè)置每個(gè)節(jié)點(diǎn)的指針成員,就可形成鏈表。
運(yùn)行結(jié)果:
分析:建立鏈表要經(jīng)歷3個(gè)步驟:①根據(jù)節(jié)點(diǎn)數(shù)據(jù)定義節(jié)點(diǎn)結(jié)構(gòu)體,指針成員是不可缺少的;②設(shè)置節(jié)點(diǎn)數(shù)據(jù),只需將數(shù)據(jù)賦給結(jié)構(gòu)體對(duì)應(yīng)成員;③建立連接關(guān)系,只需按節(jié)點(diǎn)順序關(guān)系,取結(jié)構(gòu)體變量地址賦值即可。鏈表節(jié)點(diǎn)數(shù)據(jù)輸出,先使指針變量p指向頭節(jié)點(diǎn),輸出頭節(jié)點(diǎn)指針?biāo)赶蚴坠?jié)點(diǎn)數(shù)據(jù),將本節(jié)點(diǎn)指針成員的值賦給p,即指向下一節(jié)點(diǎn),一直到p為NULL。9.5.3建立動(dòng)態(tài)鏈表
建立動(dòng)態(tài)鏈表需經(jīng)過(guò)以下步驟:
(1)使用動(dòng)態(tài)分配函數(shù)malloc或calloc申請(qǐng)節(jié)點(diǎn)空間,得到節(jié)點(diǎn)地址,第一次申請(qǐng)節(jié)點(diǎn)為head節(jié)點(diǎn),地址賦給head。
(2)從第1節(jié)點(diǎn)開(kāi)始,申請(qǐng)節(jié)點(diǎn)得到地
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 游樂(lè)設(shè)備產(chǎn)業(yè)鏈協(xié)同發(fā)展研究-洞察分析
- 芭蕾舞蹈培訓(xùn)班招生宣傳
- 2024年新型城鎮(zhèn)化建設(shè)項(xiàng)目招商引資合作協(xié)議范本3篇
- 2024年02月江蘇2024年中信銀行南京分行社會(huì)招考(222)筆試歷年參考題庫(kù)附帶答案詳解
- 采購(gòu)合同跟蹤的案例分享與解讀3篇
- 采購(gòu)框架合同共進(jìn)步3篇
- 2024年度房地產(chǎn)中介買(mǎi)賣(mài)合同范本:含房屋買(mǎi)賣(mài)合同生效條件3篇
- 采購(gòu)合同補(bǔ)充協(xié)議模板范例3篇
- 采購(gòu)合同預(yù)付款的稅務(wù)籌劃3篇
- 采購(gòu)商品電子合同3篇
- 公司董事長(zhǎng)在集團(tuán)年度務(wù)虛會(huì)上的講話發(fā)言稿
- 多元化經(jīng)營(yíng)的陷阱——巨人集團(tuán)失敗的財(cái)務(wù)分析
- 市政道路工程_混凝土路面檢驗(yàn)批_樣板
- 《語(yǔ)言習(xí)得與外語(yǔ)教學(xué)》-課程教學(xué)大綱
- COMMERCIAL INVOICE 商業(yè)發(fā)票
- 旅行社踩線邀請(qǐng)函
- 12噸汽車(chē)起重機(jī)基本技術(shù)規(guī)格資料
- 年產(chǎn)2億袋板藍(lán)根顆粒劑車(chē)間工藝設(shè)計(jì)
- 基數(shù)詞-與序數(shù)詞PPT優(yōu)秀課件
- 雙壁波紋管出廠合格證(共4頁(yè))
- 學(xué)校校醫(yī)室常用藥物配備目錄及急救小常識(shí)
評(píng)論
0/150
提交評(píng)論