C語言第9章結(jié)構(gòu)體_第1頁
C語言第9章結(jié)構(gòu)體_第2頁
C語言第9章結(jié)構(gòu)體_第3頁
C語言第9章結(jié)構(gòu)體_第4頁
C語言第9章結(jié)構(gòu)體_第5頁
已閱讀5頁,還剩41頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

C語言程序設(shè)計第9章結(jié)構(gòu)體與共用體引言C語言的數(shù)據(jù)類型分為基本數(shù)據(jù)類型和構(gòu)造數(shù)據(jù)類型,我們在前面章節(jié)中學(xué)過的int、float、double等數(shù)據(jù)類型都屬于“基本數(shù)據(jù)類型”,都是C語言事先規(guī)定好的數(shù)據(jù)類型,我們編程時直接使用即可。同時C語言還允許用戶自定義數(shù)據(jù)類型,這稱之為“構(gòu)造數(shù)據(jù)類型”,如前面說過的數(shù)組。本章要學(xué)習(xí)的結(jié)構(gòu)體與共用體數(shù)據(jù)類型都屬于“構(gòu)造數(shù)據(jù)類型”結(jié)構(gòu)體結(jié)構(gòu)體(structure)是不同數(shù)據(jù)類型的數(shù)據(jù)所組成的集合體,是構(gòu)造類型數(shù)據(jù)。與前面我們所講的構(gòu)造類型數(shù)據(jù)數(shù)組的區(qū)別在于其中的成員可以不是同一個數(shù)據(jù)類型的。每一個結(jié)構(gòu)體有一個名字,稱為結(jié)構(gòu)體名。所有成員都組織在該名字之下。一個結(jié)構(gòu)體由若干成員組成。它是組成結(jié)構(gòu)體的要素,每個成員的數(shù)據(jù)類型可以不同,也可以相同。每個成員有自己的名字,稱為結(jié)構(gòu)體成員名。結(jié)構(gòu)體的應(yīng)用為處理復(fù)雜的數(shù)據(jù)結(jié)構(gòu)提供了有利的手段。特別是對處理那些數(shù)據(jù)結(jié)構(gòu)比較復(fù)雜的程序提供了方便。結(jié)構(gòu)體類型的定義聲明一個結(jié)構(gòu)體類型的一般形式為:struct結(jié)構(gòu)體名{數(shù)據(jù)類型成員1的名字; 數(shù)據(jù)類型成員2的名字; 數(shù)據(jù)類型成員3的名字; ……};

表9-1某班學(xué)生成績管理表學(xué)號性別高數(shù)英語C語言程序設(shè)計1F9085782M8976903M7643694M589276…………………………例:針對表9-1中的每個學(xué)生的信息,我們可以定義如下的結(jié)構(gòu)體類型:structstudent{intsID; //學(xué)號charsSex; //性別intsMath; //高數(shù)成績intsEng; //英語成績intsC; //C語言程序設(shè)計成績};

結(jié)構(gòu)體變量的定義(1)先聲明結(jié)構(gòu)體類型再定義變量名如例9-2中,我們已經(jīng)定義了一個structstudent的結(jié)構(gòu)體數(shù)據(jù)類型,可以用該數(shù)據(jù)類型來定義變量,如: structstudentS1;結(jié)構(gòu)體變量的定義(2)在聲明結(jié)構(gòu)體類型的同時定義結(jié)構(gòu)體變量其定義形式為:struct結(jié)構(gòu)體名{ 數(shù)據(jù)類型成員1的名字; 數(shù)據(jù)類型成員2的名字; 數(shù)據(jù)類型成員3的名字; ……}結(jié)構(gòu)體變量名表;結(jié)構(gòu)體變量的定義(3)直接定義結(jié)構(gòu)體變量,不出現(xiàn)結(jié)構(gòu)體名其定義形式為:struct{數(shù)據(jù)類型成員1的名字; 數(shù)據(jù)類型成員2的名字; 數(shù)據(jù)類型成員3的名字; ……}結(jié)構(gòu)體變量名表;用typedef定義數(shù)據(jù)類型關(guān)鍵字typedef用于為系統(tǒng)固有的或自定義數(shù)據(jù)類型定義一個別名。數(shù)據(jù)類型的別名通常使用大寫字母,但這不是強制性的,只是為了與已有數(shù)據(jù)類型相區(qū)分。如:typedefintINTEGER;為int數(shù)據(jù)類型定義了一個新名字INTEGER,則若程序中出現(xiàn)INTEGERa;即表示定義了一個int型的變量。也可以利用typedef為結(jié)構(gòu)體數(shù)據(jù)類型定義一個別名。注意,typedef只是為一種已存在的類型定義一個新的名字而已,并未定義一種新的數(shù)據(jù)類型。結(jié)構(gòu)體變量的引用定義了結(jié)構(gòu)體變量后,可以引用該變量。但需注意:(1)不能將一個結(jié)構(gòu)體變量作為一個整體進(jìn)行輸入和輸出,只能對每個具體的成員進(jìn)行輸入、輸出操作。如對已定義的結(jié)構(gòu)體變量S1,不能按如下方式引用:printf(“%d%c%d%d%d”,S1);訪問結(jié)構(gòu)體變量的成員,需使用“成員運算符”(也稱“圓點運算符”)。其訪問格式如下:結(jié)構(gòu)體變量名.成員名如,可用下面的語句為結(jié)構(gòu)體變量S1的sC成員進(jìn)行賦值。S1.sC=90;S1.sC為結(jié)構(gòu)體成員,與其他類型變量的使用方法是一樣的。注意:結(jié)構(gòu)體變量不能作為整體進(jìn)行輸入和輸出,但允許對具有相同結(jié)構(gòu)體類型的變量進(jìn)行整體賦值。結(jié)構(gòu)體變量的引用(2)如果成員本身又屬一個結(jié)構(gòu)體類型,則要用若干個成員運算符,一級一級的找到最低一級的成員。例:structdate{intyear;intmonth;};structstudent{intsID; charsSex; structdatebirth; intsMath; intsEng; intsC;}s,s1,s2;則要引用結(jié)構(gòu)體變量s的birth成員的year成員,則需如此引用:s.birth.year。結(jié)構(gòu)體變量的引用(3)對結(jié)構(gòu)體成員的操作與其它變量一樣,可進(jìn)行各種運算,如:賦值運算:s.birth.year=1990;算術(shù)運算:ave=(s.sMath+s.sEng+s.sC)/3;自加減運算:s.sC++;--s.sC;關(guān)系運算:s1.sC>s2.sC;結(jié)構(gòu)體變量的初始化和其他數(shù)據(jù)類型的變量一樣,對結(jié)構(gòu)體變量可以初始化,即在定義結(jié)構(gòu)體變量的同時,對其成員指定初始值。結(jié)構(gòu)體變量初始化的格式:struct結(jié)構(gòu)體名結(jié)構(gòu)體變量名={初始數(shù)據(jù)};對結(jié)構(gòu)體變量初始化應(yīng)注意幾點:(1)初始化數(shù)據(jù)與數(shù)據(jù)之間用逗號隔開;(2)初始化數(shù)據(jù)的個數(shù)要與被賦值的結(jié)構(gòu)體成員的個數(shù)相等。(3)初始化數(shù)據(jù)的類型要與相應(yīng)的結(jié)構(gòu)體成員的數(shù)據(jù)類型一致。(4)不能直接在結(jié)構(gòu)體成員表中對成員賦初值。結(jié)構(gòu)體數(shù)組一個結(jié)構(gòu)體變量中可存放一組數(shù)據(jù)(如例9-1的學(xué)生成績管理表中的一行信息)。若該班有30個學(xué)生,則這30個學(xué)生的信息都可以用結(jié)構(gòu)體變量來表示,它們具有相同的數(shù)據(jù)類型,可以用數(shù)組來表示,這就是結(jié)構(gòu)體數(shù)組。結(jié)構(gòu)體數(shù)組中每個數(shù)組元素都是一個結(jié)構(gòu)體類型的數(shù)據(jù),它們都分別包括各個成員項。結(jié)構(gòu)體數(shù)組的定義結(jié)構(gòu)體數(shù)組必須先定義,后引用。其定義形式與定義結(jié)構(gòu)體變量的方法差不多,只需說明其為數(shù)組即可。如:structstudents[30];結(jié)構(gòu)體數(shù)組的初始化結(jié)構(gòu)體數(shù)組也可在定義的同時進(jìn)行賦值,即對其進(jìn)行初始化。如對結(jié)構(gòu)體數(shù)組s[30]的前3個元素進(jìn)行初始化,其他數(shù)組元素被系統(tǒng)自動賦值為0:structstudents[30]={{1,’F’,90,80,70},{2,’M’,78,89,98},{3,’M’,76,81,90}};結(jié)構(gòu)體數(shù)組的引用例9-4:利用結(jié)構(gòu)體數(shù)組計算上面3位同學(xué)的“英語成績”的平均分。(1)首先分析該程序要求,結(jié)構(gòu)體數(shù)組的每個元素是一位同學(xué)的信息,其中每位同學(xué)的sEng成員表示“英語成績”,要求平均成績,只要將每位同學(xué)的sEng成員的值加起來除以3即可。(2)流程圖如圖9-1所示:結(jié)構(gòu)體指針變量結(jié)構(gòu)體指針變量是指向結(jié)構(gòu)體變量的指針,該指針變量的值就是結(jié)構(gòu)體變量的起始地址,其目標(biāo)變量是一個結(jié)構(gòu)體變量。指向結(jié)構(gòu)體變量的指針定義一個指向該結(jié)構(gòu)類型的指針變量的方法為:STU*p; 這里只是定義了一個指向STU結(jié)構(gòu)體類型的指針變量p,但此時的p并沒有指向一個確定的存儲單元,其值是一個隨機值。為使p指向一個確定的存儲單元,需要對指針變量進(jìn)行初始化。例:pt=&S1;使指針pt指向結(jié)構(gòu)體變量S1所占內(nèi)存空間的首地址,即pt是指向結(jié)構(gòu)體變量S1的指針。當(dāng)然也可對定義指針變量初始化,例:STU*p=&S1;指向結(jié)構(gòu)體變量的指針C語言規(guī)定了兩種用于訪問結(jié)構(gòu)體成員的運算符,一種是成員運算符,也稱圓點運算符(前面介紹過);另一種是指向運算符,也成箭頭運算符,其訪問形式為:指向結(jié)構(gòu)體的指針變量名->成員名如要給結(jié)構(gòu)體指針變量p指向的結(jié)構(gòu)體的sEng成員賦值90,需使用語句:p->sEng=90;它與語句(*p).sEng=90;是等價的,因為()的優(yōu)先級比成員運算符的優(yōu)先級高,所以先將(*p)作為一個整體,取出p指向的結(jié)構(gòu)體的內(nèi)容,將其看成一個結(jié)構(gòu)體變量,利用成員選擇運算符訪問它的成員。指向結(jié)構(gòu)體數(shù)組的指針定義一個結(jié)構(gòu)體數(shù)組STUs[30];則定義結(jié)構(gòu)體指針變量p,并將其指向結(jié)構(gòu)體數(shù)組s有以下三種方法:(1)STU*p=s; (2)STU*p=&s[0]; (3)STU*p; p=s; 這三種方法是等價的,指針變量p中存放的是數(shù)組s的首元素s[0]的地址。結(jié)構(gòu)體變量和結(jié)構(gòu)體指針變量作為函數(shù)參數(shù)將一個結(jié)構(gòu)體變量的值傳遞給另一個函數(shù),有3種方法:

(1)用結(jié)構(gòu)體的單個成員作為函數(shù)參數(shù),向函數(shù)傳遞結(jié)構(gòu)體的單個成員。(2)用結(jié)構(gòu)體變量作函數(shù)參數(shù),向函數(shù)傳遞結(jié)構(gòu)體的完整結(jié)構(gòu)。(3)用結(jié)構(gòu)體指針或結(jié)構(gòu)體數(shù)組作函數(shù)參數(shù),向函數(shù)傳遞結(jié)構(gòu)體的地址。

鏈表鏈表是動態(tài)進(jìn)行內(nèi)存分配的一種結(jié)構(gòu),鏈表根據(jù)需要開辟內(nèi)存單元。動態(tài)內(nèi)存分配是指在程序執(zhí)行的過程中根據(jù)需要動態(tài)地分配或者回收存儲空間的內(nèi)存分配方法。動態(tài)內(nèi)存分配不像數(shù)組等靜態(tài)內(nèi)存分配方法那樣需要預(yù)先分配存儲空間,而是由系統(tǒng)根據(jù)程序的需要即時分配,且分配的大小就是程序要求的大小。鏈表數(shù)據(jù)集合中的每個數(shù)據(jù)存儲在稱為結(jié)點的結(jié)構(gòu)體中,一個結(jié)點通過該結(jié)點中存儲的另一個結(jié)點的存儲地址(指針)訪問另一個結(jié)點,如果按照這種方法把所有結(jié)點依次串接起來,就稱為鏈表。鏈表的類型及定義鏈表是用一組任意的存儲單元存儲線性表元素的一種數(shù)據(jù)結(jié)構(gòu)。鏈表又分為單鏈表、雙向鏈表和循環(huán)鏈表等。鏈表一般采用圖形方式來形象直觀地描述結(jié)點之間的連接關(guān)系。這種描述鏈表邏輯結(jié)構(gòu)的圖形稱為鏈表圖。單鏈表單鏈表是最簡單的一種鏈表,其數(shù)據(jù)元素是單向排列的單鏈表鏈表的數(shù)據(jù)結(jié)構(gòu)可以用“結(jié)構(gòu)體”來實現(xiàn)。一個結(jié)構(gòu)體變量可包含若干成員,這些成員可以是數(shù)值類型、字符類型、數(shù)組類型,也可以是指針類型。利用指針類型成員存放下一個結(jié)點的指針。例如:structnode{intdata;structnode*next;};循環(huán)單鏈表循環(huán)單鏈表如圖9-4所示,它的特點是最后一個結(jié)點的指針域存放著第一個結(jié)點的地址,這樣一來,鏈表中的所有結(jié)點構(gòu)成一個環(huán),每個結(jié)點都有直接前驅(qū)和直接后繼結(jié)點。循環(huán)單鏈表的優(yōu)點是從任何一個結(jié)點出發(fā),能到達(dá)其他任何結(jié)點。雙向鏈表如果為每個結(jié)點增加一個指向直接前驅(qū)結(jié)點的指針域,就可以構(gòu)成雙向鏈表。雙向鏈表可以沿著求前驅(qū)和求后繼兩個方向搜索結(jié)點。雙向鏈表的結(jié)點數(shù)據(jù)結(jié)構(gòu)實現(xiàn)如下:structnode{intdata; structnode*next,*previous;//next是后繼結(jié)點指針,previous是前驅(qū)結(jié)點指針};處理動態(tài)鏈表的函數(shù)鏈表結(jié)構(gòu)是動態(tài)分配存儲空間的,即在需要時才開辟一個結(jié)點的存儲單元。動態(tài)分配和釋放存儲空間需要用到以下幾個庫函數(shù):(1)malloc函數(shù)函數(shù)原型為:void*malloc(unsignedintsize);(2)calloc函數(shù)函數(shù)原型為:void*calloc(unsignedn,unsignedsize);(3)free函數(shù)函數(shù)原型為:voidfree(void*p);動態(tài)鏈表的基本操作——單鏈表的建立建立單鏈表是在程序執(zhí)行過程中從無到有的建立起一個鏈表,即一個一個的開辟結(jié)點和輸入各結(jié)點數(shù)據(jù),并建立起前后相連的關(guān)系。單鏈表的建立參考例9-6寫動態(tài)內(nèi)存分配的程序應(yīng)注意,請盡量對分配是否成功進(jìn)行檢測。單鏈表的查找運算對單鏈表進(jìn)行查找的思路為:對單鏈表的結(jié)點依次掃描,檢測其數(shù)據(jù)域是否是我們所要查找的值,若是返回該結(jié)點的指針,否則返回NULL。因為在單鏈表的鏈域中包含了后繼結(jié)點的存儲地址,所以當(dāng)我們實現(xiàn)的時候,只要知道該單鏈表的頭指針,即可依次對每個結(jié)點的數(shù)據(jù)域進(jìn)行檢測。查找實現(xiàn)算法見例9-7單鏈表的插入操作假設(shè)例9-6中建立的鏈表為一個班級中的10名同學(xué)的成績,現(xiàn)在如果該班又進(jìn)入了一名同學(xué),則需要將該新同學(xué)的成績加入到單鏈表中,即要對單鏈表進(jìn)行插入操作。設(shè)在一個單鏈表中存在兩個個連續(xù)結(jié)點p、q(其中p為q的直接前驅(qū)),若我們需要在p、q之間插入一個新結(jié)點s,那么我們必須先為s分配存儲空間并賦值,然后使p的鏈域存儲s的地址,s的鏈域存儲q的地址,這樣就完成了插入操作。見圖9-6。單鏈表的插入操作完成插入操作的主要語句為:s->next=q;p->next=s;單鏈表的刪除操作有時我們需要使用單鏈表的刪除操作,例如某班級調(diào)走了一名同學(xué),則需要在成績管理系統(tǒng)中將該名同學(xué)的成績刪除。假如我們已經(jīng)知道了要刪除的結(jié)點q的位置,那么要刪除q結(jié)點時只要令q結(jié)點的前驅(qū)結(jié)點的鏈域由存儲q結(jié)點的地址改為存儲q的后繼結(jié)點的地址,并回收q結(jié)點即可。如圖9-7所示:單鏈表的刪除操作刪除操作的主要語句為:p->next=q->next;free(q);單鏈表的刪除操作單鏈表的刪除操作需注意以下幾點:①要刪除q結(jié)點還需要找到q的前驅(qū)結(jié)點,改變q的前驅(qū)結(jié)點的指針域,使其直接指向q的后繼結(jié)點,達(dá)到刪除q結(jié)點的目的,所以在單鏈表的刪除操作中需要用到指向q結(jié)點的前驅(qū)結(jié)點的指針,例9-9中用p指向q結(jié)點的前驅(qū)結(jié)點。②刪除結(jié)點的函數(shù)del中用到了free函數(shù)來釋放刪除結(jié)點占用的內(nèi)存空間。棧和隊列棧、隊列和鏈表都屬于線性結(jié)構(gòu),線性結(jié)構(gòu)的特點是:在數(shù)據(jù)元素的非空有限集中,(1)存在唯一的一個被稱為“第一個”的數(shù)據(jù)元素;(2)存在唯一的一個被稱為“最后一個”的數(shù)據(jù)元素;(3)除第一個之外,集合中的每個數(shù)據(jù)元素均只有一個前驅(qū);(4)除最后一個之外,集合中每個數(shù)據(jù)元素均只有一個后繼。棧和隊列都是操作受限制的特殊的線性表。棧是一種只允許在表頭進(jìn)行插入和刪除操作的特殊的線性表,其操作的原則是后進(jìn)先出(或先進(jìn)后出)。棧又稱為后進(jìn)先出表,簡稱LIFO(LastInFirstOut)表。隊列是刪除操作只在表頭進(jìn)行,插入操作只在表尾進(jìn)行的特殊的線性表,其操作的原則是先進(jìn)先出。隊列又稱為先進(jìn)先出表,簡稱FIFO(FirstInFirstOut)表。共用體共用體,有的也稱為聯(lián)合(Union),是將不同類型的數(shù)據(jù)組織在一起共同占用同一段內(nèi)存的一種構(gòu)造數(shù)據(jù)類型。同樣都是將不同類型的數(shù)據(jù)組織在一起,但與結(jié)構(gòu)體不同的是,共用體是從同一起始地址開始存放成員的值,即讓所有成員共享同一段內(nèi)存單元。共用體與結(jié)構(gòu)體的類型定義方法相似,只是關(guān)鍵字變?yōu)閡nion。共用體聲明一個共用體類型的一般形式為:union共用體名{數(shù)據(jù)類型成員1的名字; 數(shù)據(jù)類型成員2的名字; 數(shù)據(jù)類型成員3的名字; ……};例:unionsample{ inti; charc; floatf;};共用體共用體數(shù)據(jù)類型和結(jié)構(gòu)體數(shù)據(jù)類型都屬于構(gòu)造數(shù)據(jù)類型,都可以由程序員根據(jù)實際需要來定義的,其不同之處在于共用體的所有成員共同占用一段內(nèi)存,共用體變量所占內(nèi)存空間大小取決于其成員中占內(nèi)存空間最多的那個成員變量;而結(jié)構(gòu)體的每個成員自己占用一段內(nèi)存,結(jié)構(gòu)體變量所占內(nèi)存空間大小取決于所有成員中占內(nèi)存空間的大小。枚舉類型枚舉,即“一一列舉”之意,當(dāng)某些量僅由有限個數(shù)據(jù)值組成時,通常用枚舉類型表示。枚舉數(shù)據(jù)類型描述的是一組整型值的集合。聲明枚舉類型需用關(guān)鍵字enum,如: enumweekday{sun,mon,tue,wed,thu,fri,sat};聲明了一個枚舉數(shù)據(jù)類型enumweekday,程序中可以用此數(shù)據(jù)類型來定義枚舉類型的變量,如:enumweekdaya;則枚舉變量a的取值只有7種,即sun,mo

溫馨提示

  • 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)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論