第8章結(jié)構(gòu)體共用體和枚舉類型-PPT課件_第1頁
第8章結(jié)構(gòu)體共用體和枚舉類型-PPT課件_第2頁
第8章結(jié)構(gòu)體共用體和枚舉類型-PPT課件_第3頁
第8章結(jié)構(gòu)體共用體和枚舉類型-PPT課件_第4頁
第8章結(jié)構(gòu)體共用體和枚舉類型-PPT課件_第5頁
已閱讀5頁,還剩84頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、第8章 結(jié)構(gòu)體、共用體和枚舉類型教學(xué)目的:通過本章的學(xué)習(xí),要求了解結(jié)構(gòu)型、鏈表、共用型和枚舉型數(shù)據(jù)的特點(diǎn),熟練掌握結(jié)構(gòu)型的定義方法,結(jié)構(gòu)型變量、數(shù)組、指針變量的定義、初始化和成員的引用方法;掌握簡單鏈表的基本操作原理和應(yīng)用;掌握共用型和枚舉型的定義方法及對應(yīng)變量的定義與引用;掌握用戶自定義類型的定義和使用。學(xué)習(xí)本章內(nèi)容可以為今后學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)中的鏈表創(chuàng)建和使用打下基礎(chǔ)。第8章 結(jié)構(gòu)體、共用體和枚舉類型 教學(xué)內(nèi)容 結(jié)構(gòu)型的引入,很好的處理生活總的各種表格或表格中的記錄結(jié)構(gòu)型的定義,結(jié)構(gòu)型變量的定義、賦值、引用及引用鏈表等方法共用型的定義,共用型變量的定義、賦值、引用枚舉型的定義,共用型變量的定義、

2、賦值、引用第8章 結(jié)構(gòu)體、共用體和枚舉類型重點(diǎn)和難點(diǎn)重點(diǎn): (1)結(jié)構(gòu)型、共用型、枚舉型數(shù)據(jù)的特點(diǎn)和定義 (2)結(jié)構(gòu)型變量、數(shù)組、指針變量的定義、初始化和成員引用方法 (3)共用型和枚舉型變量的定義和引用方法難點(diǎn): (1)嵌套的結(jié)構(gòu)型數(shù)據(jù)的處理 (2)用結(jié)構(gòu)體解決鏈表問題(建立、插入、刪除、輸出和查詢)。 8.1 結(jié)構(gòu)體類型結(jié)構(gòu)型是用戶自己定義的數(shù)據(jù)類型8.1.1 結(jié)構(gòu)體型的實(shí)例 前面我們學(xué)習(xí)過了基本數(shù)據(jù)類型,例如:short、long、int 、float、double、char等,這些基本數(shù)據(jù)類型都是系統(tǒng)已經(jīng)定義好的,用戶可以直接使用它們。但現(xiàn)實(shí)世界是復(fù)雜的,在我們的日常生活中有很多的表格

3、,各表格之間又有關(guān)聯(lián)。因此用戶需要自己定義數(shù)據(jù)類型,用戶自己定義的數(shù)據(jù)類型一旦定義好之后,就可以像使用系統(tǒng)類型一樣使用它。例如:對一個(gè)新生進(jìn)行入學(xué)登記時(shí),就需要填一張表格,填寫的內(nèi)容包括姓名、性別、學(xué)號、年齡、家庭住址、聯(lián)系電話、總分等多個(gè)數(shù)據(jù)項(xiàng),其中姓名是字符串型(可以用字符數(shù)組來表示),性別是字符型(用m表示男性、用f表示女性),年齡是整型,總分是實(shí)型。 如圖8-1所示, 這些數(shù)據(jù)項(xiàng)之間關(guān)系緊密,每一個(gè)學(xué)生通過姓名、性別、學(xué)號、年齡、家庭地址、聯(lián)系電話、總分等屬性構(gòu)成一個(gè)整體反映一個(gè)學(xué)生的基本情況。如果將姓名、性別、學(xué)號、年齡、家庭地址、聯(lián)系電話、總分分別定義為互相獨(dú)立的簡單變量,難以反映

4、它們之間的內(nèi)在聯(lián)系。為了方便處理此類數(shù)據(jù),常常把這些關(guān)系密切但類型不同的數(shù)據(jù)項(xiàng)組織在一起,即“封裝”起來,并為其取一個(gè)名字,在語言中就稱其為結(jié)構(gòu)體(也人稱為構(gòu)造體),結(jié)構(gòu)體是用戶自定義數(shù)據(jù)類型的一種。8.1.2 結(jié)構(gòu)體類型的定義結(jié)構(gòu)體類型定義的一般形式struct 結(jié)構(gòu)型名數(shù)據(jù)類型標(biāo)識符成員; 數(shù)據(jù)類型標(biāo)識符成員; 數(shù)據(jù)類型標(biāo)識符成員n; ; 請讀者注意結(jié)構(gòu)體定義語句的右花括號后面用分號(;)做語句結(jié)束標(biāo)記。8.1.2 結(jié)構(gòu)體類型的定義結(jié)構(gòu)體型定義實(shí)例例如:為了存放一個(gè)人的姓名、性別、年齡、工資,可以定義如下的結(jié)構(gòu)型: struct person char name10; char sex;

5、int age; float wage; ; /*這個(gè)名為person的結(jié)構(gòu)型共含有4個(gè)成員*/8.1.2 結(jié)構(gòu)體類型的定義 結(jié)構(gòu)型嵌套定義【例8.1】一開始所講的例題中的birthday類型和person類型。 struct birthday /*定義含有3個(gè)整型成員的結(jié)構(gòu)型 birthday*/ int year; int month; int day;struct person /*定義含有4個(gè)成員的結(jié)構(gòu)型 person*/char name20; char sex; struct birthday bir; /*該成員的數(shù)據(jù)類型是結(jié)構(gòu)型*/ float wage;8.2.1結(jié)構(gòu)型變量的

6、定義和初始化先定義結(jié)構(gòu)型,后定義變量定義結(jié)構(gòu)型的同時(shí)定義變量 定義無名稱的結(jié)構(gòu)型的同時(shí)定義變量 8.2 結(jié)構(gòu)體變量的定義和引用 例如:為學(xué)生信息定義2個(gè)變量x和y , 程序段如下:struct studentlong number; char name20; char sex; float score3;struct student x,y;在定義變量的同時(shí),可以變量賦初值,例如上例中的定義語句可以改寫如下:struct student x=100001L,”Tom”,m,86,94,89, y=100002L,”Lucy”,f,78,88,45;1. 先定義結(jié)構(gòu)型,后定義變量 2. 定義結(jié)構(gòu)

7、型的同時(shí)定義變量例如:為學(xué)生信息定義2個(gè)變量x和y , 并給他們賦初值,程序段如下:struct studentlong number; char name10; char sex; float score3;x=100001L,”Tom”,m,86,94,89, y=100002L,”Lucy”,f,78,88,45,;這種方法是將類型定義和變量定義同時(shí)進(jìn)行。以后仍然可以使用這種結(jié)構(gòu)型來定義其它的變量。 3. 定義無名稱的結(jié)構(gòu)型的同時(shí)定義變量例如:為學(xué)生信息定義2個(gè)變量x和y ,并給它們賦初值,程序段如下:structlong number; char name10; char sex; f

8、loat score3;x=100001L,”Tom”,m,86,94,89, y=100002L,”Lucy”,f,78,88,45,;這種方法是將類型定義和變量定義同時(shí)進(jìn)行,但結(jié)構(gòu)型的名稱省略,以后將無法使用這種結(jié)構(gòu)型來定義其它變量,建議盡量少用。 8.2.2 結(jié)構(gòu)型變量成員的引用1.結(jié)構(gòu)型變量成員的引用方法2.結(jié)構(gòu)型變量成員地址的引用方法3.結(jié)構(gòu)型變量地址的引用方法1. 結(jié)構(gòu)型變量成員的引用方法結(jié)構(gòu)型變量成員的引用格式如下:結(jié)構(gòu)型變量名. 成員名 其中的“.”稱為成員運(yùn)算符,其運(yùn)算級別是最高的,和圓括號運(yùn)算符“()”、下標(biāo)運(yùn)算符“”是同級別的,運(yùn)算順序是自左向右。如果某個(gè)結(jié)構(gòu)型變量的成員

9、數(shù)據(jù)類型又是一個(gè)結(jié)構(gòu)型,則其成員的引用方法如下:外層結(jié)構(gòu)型變量. 外層成員名. 內(nèi)層成員名結(jié)構(gòu)型變量成員的引用實(shí)例【例8.2】求Tom的三門課程的成績總分,并在顯示器顯示出來(使用結(jié)構(gòu)型變量成員的引用)。 #include”string.h” struct student long number; char name10; char sex; float score3; ; main() struct student stu1; /*定義student類型的變量stu1*/ stu1.number=100001L; /*給結(jié)構(gòu)型變量stu1的成員number賦值*/ strcpy(stu1.n

10、ame;”Tom”); /*給結(jié)構(gòu)型變量stu1的成員name賦值*/ stu1.sex=f; /*給結(jié)構(gòu)型變量stu1的成員sex賦值*/ stu1.score0=89; /*給結(jié)構(gòu)型變量stu1的成員score賦值*/ stu1.score1=91; stu1.score2=86; printf(“%s的總分是:%fn”,,stu1.score0+stu1.score1+stu1.score2); 2. 結(jié)構(gòu)型變量成員地址的引用方法結(jié)構(gòu)型的變量成員地址引用格式如下: &結(jié)構(gòu)型的變量名.成員名存放結(jié)構(gòu)型變量成員地址的指針變量類型必須和該成員的類型相同?!纠?.4】結(jié)構(gòu)型變量成

11、員地址引用。 #include “string.h” /*程序中使用了字符串處理函數(shù)*/ sturct student2 /*定義student2結(jié)構(gòu)型*/ long number; char name10; main() struct student2 x; /*定義student2類型的變量x*/ long *p_number; /*定義能指向結(jié)構(gòu)型student成員number的指針變量*/ char *p_name; /*定義能指向結(jié)構(gòu)型student成員namer的指針變量*/ p_number=&x.number; /*讓指針變量指向結(jié)構(gòu)型變量x的成員*/ *p_ number=1

12、00001L; /*用指針變量給結(jié)構(gòu)型變量x的所有成員賦值*/ strucpy(p_ name,”zhongxin”); printf(“number=%1d name=%sn”,*p_number,*p_ name); /*用指針變量輸出結(jié)構(gòu)型變量x所有成員的值*/ 從這個(gè)例子可以看出,使用指向結(jié)構(gòu)型變量成員的指針變量來引用成員的方法比較繁瑣,可以直接使用結(jié)構(gòu)型變量的指針成員來引用成員。具體使用方法請參看第8章8.4節(jié)。3. 結(jié)構(gòu)型變量地址的引用方法 結(jié)構(gòu)型變量地址的引用格式如下: &結(jié)構(gòu)型變量名 例如:借用例8.4中的結(jié)構(gòu)型struct student2: struct student2

13、y,*sty=&y;存放結(jié)構(gòu)型變量地址的指針變量必須是類型相同的結(jié)構(gòu)型指針,關(guān)于如何使用結(jié)構(gòu)型變量地址的例子請參見8.4節(jié)中介紹的指向結(jié)構(gòu)型數(shù)據(jù)的指針變量。8.3 結(jié)構(gòu)型數(shù)組的定義和引用 在實(shí)際應(yīng)用中,我們經(jīng)常要處理的是具有 相同數(shù)據(jù)結(jié)構(gòu)的一個(gè)群體。比如一批書,所有員工的通信地址,一個(gè)班級的學(xué)生等。由相同結(jié)構(gòu)類型變量組成的數(shù)組,稱為結(jié)構(gòu)型數(shù)組。例如,全班有40人,在總成績單上每人占一行,每行的內(nèi)容包括學(xué)號、姓名、3門功課的成績、平均分、名次,這樣一個(gè)總成績單就可以用結(jié)構(gòu)型數(shù)組表示。8.3.1 結(jié)構(gòu)型數(shù)組的定義和初始化1.先定義結(jié)構(gòu)型,然后再定義結(jié)構(gòu)型數(shù)組并賦初值 2.定義結(jié)構(gòu)型的同時(shí)定義數(shù)組并

14、賦初值 3.定義無名稱的結(jié)構(gòu)型的同時(shí)定義數(shù)組并賦初值 1.先定義結(jié)構(gòu)型,再定義結(jié)構(gòu)型數(shù)組并賦初值運(yùn)算 struct student /*定義結(jié)構(gòu)型*/ long number; char name10; char sex; float score3; ; struct student s3= 200001L,”Tom”,m,78,86,92 , 200002L,”Lucy”,f,85,69,82 , 200003L,”Jack”,m,84,88,96 ;2. 定義結(jié)構(gòu)型的同時(shí)定義數(shù)組并賦初值 struct student /*定義結(jié)構(gòu)型*/long number;char name10;cha

15、r sex;float score3;s3= 200001L,”Tom”,m,78,86,92 , 200002L,”Lucy”,f,85,69,82 , 200003L,”Jack”,m,84,88,96 ;3. 定義無名稱的結(jié)構(gòu)型的同時(shí)定義數(shù)組并賦初值 struct /*定義結(jié)構(gòu)型*/long number;char name10;char sex;float score3;s3= 200001L,”Tom”,m,78,86,92 , 200002L,”Lucy”,f,85,69,82 , 200003L,”Jack”,m,84,88,96 ;8.3.2 結(jié)構(gòu)型數(shù)組元素成員的引用1.結(jié)構(gòu)型

16、數(shù)組元素的引用格式如下; 結(jié)構(gòu)型數(shù)組名下標(biāo) . 成員名2.結(jié)構(gòu)型數(shù)組元素成員地址的引用格式如下: &結(jié)構(gòu)型數(shù)組名下標(biāo).成員名1. 結(jié)構(gòu)型數(shù)組元素的引用:結(jié)構(gòu)型數(shù)組名下標(biāo) . 成員名【例8.5】輸入3個(gè)學(xué)生的數(shù)據(jù),每個(gè)學(xué)生的信息由學(xué)號、姓名和三門功課的成績組成,然后計(jì)算每一個(gè)學(xué)生的總分,并輸出總分最高的學(xué)生信息。分析:將3個(gè)學(xué)生定義為結(jié)構(gòu)型類型數(shù)組,學(xué)號為長整型、成績?yōu)閷?shí)型數(shù)組,總分存在成績數(shù)組中。#define N 3struct student /*定義結(jié)構(gòu)型*/ long number; char name10; float scoreN+1; /*score數(shù)組前三個(gè)元素用來存放成績,第

17、四個(gè)元素用來存 放總分*/ stuN; main() float max=0;int i,j,max_i=0;for(i=0;iN;i+)printf(“輸入第%d個(gè)學(xué)生的信息,依次輸入學(xué)號,姓名,三個(gè)成績,各數(shù)據(jù)之間用,隔開”,i);scanf(“%ld,%s,%f,%f,%f”, ,&stui.number,&,&stui.score0, &stui.score1, &stui.score2);stui.score3=stui.score0+ stui.score1+ stui.score2;if (max成員名 方式1比較好理解,其中“*指針變量”就代表了它所指向的結(jié)構(gòu)

18、型變量,利用“成員運(yùn)算符”來引用,其作用相當(dāng)于“結(jié)構(gòu)型變量.成員名”。需要注意的是“*指針變量”必須用圓括號括住,因?yàn)椤?”運(yùn)算符的級別低于“.”運(yùn)算符,如果不加括號,則優(yōu)先處理“.”運(yùn)算符,將出現(xiàn)“指針變量.成員名”,會造成語法錯(cuò)誤。 方式2是一種新的引用方法,其中“-”稱為“指向成員運(yùn)算符”,也簡稱“指向運(yùn)算符”。其運(yùn)算級別和“()”、“”、“.”是同級的。指向運(yùn)算符的左邊必須是已指向某個(gè)結(jié)構(gòu)型變量或數(shù)組元素的指針變量,其右邊必須是對應(yīng)結(jié)構(gòu)型數(shù)據(jù)的成員名。8.4.2 指向結(jié)構(gòu)型數(shù)組的指針1.指針變量指向數(shù)組元素 如果一個(gè)結(jié)構(gòu)型數(shù)組元素的地址已賦予相同結(jié)構(gòu)型指針變量(即指針變量指向結(jié)構(gòu)型數(shù)組

19、元素),可以使用下列兩種方法來引用數(shù)組該元素的成員,其作用完全相同。 方式1 (*指針變量)。成員名 方式2 指針變量-成員名 注意:這里的指針變量必須是指向某個(gè)數(shù)組元素的。例如,它指向的數(shù)組元素為“數(shù)組名k”,則上述兩種引用方式均代表“數(shù)組名k。成員名”。2.指針變量指向數(shù)組首地址 當(dāng)一個(gè)結(jié)構(gòu)型數(shù)組的首地址已經(jīng)賦予相同結(jié)構(gòu)型的指針變量(即指針變量指向結(jié)構(gòu)型數(shù)組),可以使用下列兩種方式來引用下標(biāo)為i的數(shù)組元素成員,其作用完全相同。 方式1(*(指針變量+i).成員名 方式2(指針變量+i) 成員名 注意:這里的指針變量必須是指向某個(gè)數(shù)組首地址的,則上述兩種引用方式均代表“數(shù)組名i。成員名8.4

20、.3 在函數(shù)間傳遞結(jié)構(gòu)型數(shù)據(jù)1. 采用“全局外部變量方式傳遞數(shù)據(jù)” 2. 采用“返回值方式傳遞數(shù)據(jù)” 3. 采用“形式參數(shù)和實(shí)際參數(shù)結(jié)合的地址傳遞方式雙向傳遞數(shù)據(jù)” 8.5 用指針處理鏈表 我們知道用數(shù)組存放數(shù)據(jù)時(shí),必須事先定義好數(shù)組的大小,不能在程序中隨便進(jìn)行調(diào)整。比如有的班有100人,有的班只有30人,如果要用同一個(gè)數(shù)組先后存放不同班級的學(xué)生數(shù)據(jù),則必須定義長度為100的數(shù)組。如果事先難以確定一個(gè)班的最多人數(shù),則必須把數(shù)組定義的足夠大,以存放任何班級的學(xué)生數(shù)據(jù),這顯然非常浪費(fèi)存儲空間。為此C語言提供了動態(tài)數(shù)組的構(gòu)建,即鏈表。8.5.1 什么是鏈表 鏈表如同一條鐵鏈一樣,一環(huán)扣一環(huán),中間是不

21、能斷開的。這好比幼兒園的老師帶領(lǐng)孩子出去玩,老師牽著第一個(gè)孩子的手,第一個(gè)孩子的另一只手牽著第二個(gè)孩子的手這就是一個(gè)“鏈”,最后一個(gè)孩子有一只手空著,他就是“鏈尾”。要找這個(gè)隊(duì)伍,就必須先找到老師,然后順序找到每一個(gè)孩子。 鏈表是一種動態(tài)數(shù)據(jù)結(jié)構(gòu),在程序的執(zhí)行過程中可以根據(jù)需要隨時(shí)間系統(tǒng)申請存儲空間,動態(tài)地進(jìn)行存儲空間的分配。動態(tài)數(shù)據(jù)結(jié)構(gòu)最顯著的特點(diǎn)是包含的數(shù)據(jù)對象個(gè)數(shù)及其相互關(guān)系都可以按需要改變。常用的動態(tài)數(shù)據(jù)結(jié)構(gòu)有鏈表、循環(huán)鏈表、雙向鏈表三種。本章只介紹動態(tài)數(shù)據(jù)結(jié)構(gòu)中最簡單的單鏈表的建立及其基本操作。1.單鏈表的結(jié)構(gòu) 鏈表有一個(gè)“頭指針”head,它存放鏈表第一個(gè)結(jié)點(diǎn)的首地址,它沒有數(shù)據(jù),

22、只是一個(gè)指針變量。從圖8-2中我們看到它指向鏈表的第一個(gè)元素。鏈表的每一個(gè)元素稱為一個(gè)“結(jié)點(diǎn)”(node)。每個(gè)結(jié)點(diǎn)都分為兩個(gè)域,一個(gè)是數(shù)據(jù)域,存放各種實(shí)際的數(shù)據(jù),如學(xué)號num、姓名name、性別sex、和成績score等。另一個(gè)域?yàn)橹羔樣?,存放下一個(gè)結(jié)點(diǎn)的首地址,即指向下一個(gè)結(jié)點(diǎn)。鏈表中的每一個(gè)結(jié)點(diǎn)都是同一個(gè)結(jié)構(gòu)類型。最后一個(gè)結(jié)點(diǎn)稱為“鏈尾”,尾結(jié)點(diǎn)無后續(xù)點(diǎn),因此不指向其他的元素,表尾結(jié)點(diǎn)的指針為空(NULL)。 2.鏈表結(jié)點(diǎn)的構(gòu)成 由于每個(gè)結(jié)點(diǎn)包含數(shù)據(jù)域或者指針域兩部分內(nèi)容,所以鏈表結(jié)點(diǎn)采用結(jié)構(gòu)體表示。例如鏈表結(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)定義如下:struct node int num; char na

23、me10; float score; struct node *next; 在鏈表結(jié)構(gòu)中,除了數(shù)據(jù)項(xiàng)成員之外,還應(yīng)包含一個(gè)指向本身的指針,該指針在使用時(shí)指向具有相同類型結(jié)構(gòu)體的下一個(gè)結(jié)點(diǎn)。 在鏈表結(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)中,比較特殊的一點(diǎn)就是結(jié)構(gòu)體內(nèi)指針域的數(shù)據(jù)類型使用了未定義成功的數(shù)據(jù)類型。這是在C語言中唯一可以先使用后定義的數(shù)據(jù)結(jié)構(gòu)。3.如何建立和輸出一個(gè)簡單靜態(tài)鏈表 【例 8.10】建立一個(gè)如圖8-3所示的簡單鏈表,它由三個(gè)學(xué)生數(shù)據(jù)結(jié)點(diǎn)組成。請輸出各結(jié)點(diǎn)中的數(shù)據(jù)。分析:為方便操作,將學(xué)生定義為一個(gè)結(jié)構(gòu)體類型student,它有三個(gè)成員分別用來表示學(xué)生的學(xué)號、姓名和下一個(gè)結(jié)點(diǎn)的地址。在程序中逐個(gè)輸入

24、各學(xué)生的數(shù)據(jù),通過地址賦值操作建立鏈表。利用當(dāng)型循環(huán)用printf語句逐個(gè)輸出個(gè)結(jié)點(diǎn)中成員的值。程序如下:#includestruct student char no6; char name10; struct student *next;void main() struct student A=“02019”,”tom”, B=“02019”,”jane”, C=“02019”,”henry”; struct srudent *head=NULL,*p; head=&A;A.next=&B;B.next=&C;C.next=NULL;p=head;while (p!=NULL) printf

25、(“No:%stName:%sn”,p-no,p-name); p=p-next;在本例中,所有結(jié)點(diǎn)都是在程序中定義的、不是臨時(shí)開辟的、用完后也不能釋放,我們把這種鏈表稱為“靜態(tài)鏈表”4動態(tài)存儲分配函數(shù)所謂“動態(tài)鏈表”就是鏈表的結(jié)構(gòu)是動態(tài)分配和存儲的,在程序的執(zhí)行過程中要根據(jù)需要隨時(shí)向系統(tǒng)申請存儲空間,動態(tài)地進(jìn)行存儲空間的分配。在C語言中,提供了一下函數(shù)完成存儲空間的動態(tài)分配和釋放。malloc函數(shù)calloc函數(shù)free函數(shù)malloc函數(shù)其函數(shù)原型為:void * malloc(unsigned size) 其作用是在內(nèi)存的動態(tài)存儲區(qū)中分配一個(gè)長度為size的連續(xù)空間,并返回指向該空間起始

26、地址的指針。若分配失敗(如系統(tǒng)不能提供所需內(nèi)存),則返回空指針NULL。calloc函數(shù)其函數(shù)原型為:void * calloc(unsigned n,unsigned size) 該函數(shù)有兩個(gè)形參n和size。其作用是在內(nèi)存的動態(tài)存儲區(qū)中分配n個(gè)長度為size的連續(xù)空間,并返回指向該空間首地址的指針。如用calloc(20,20)可以開辟20個(gè)(每個(gè)大小為20字節(jié))的空間,即空間總長為400字節(jié)。若分配失敗,則返回空指針NULL。free函數(shù)其函數(shù)原型為:void * free(void * ptr)其作用是釋放由malloc、calloc等函數(shù)申請的內(nèi)存空間,使這部分內(nèi)存區(qū)能夠被其他變量所

27、使用。ptr是最近一次調(diào)用malloc()或calloc()函數(shù)返回的值。Free函數(shù)沒有返回值。在使用上述函數(shù)時(shí)要注意,函數(shù)的原型在文件malloc.h和stdlib.h中定義。在程序中必須包含這兩個(gè)頭文件。下面的程序就是malloc()和free()兩個(gè)函數(shù)配合使用的簡單實(shí)例?!纠?8.11】存儲空間的動態(tài)分配。#include#include#includemain() char *str; if(str=(char*) malloc(10)=NULL) printf(“Not enough memory to allocate buffern”);exit(1);strcpy(str,

28、”welcome”);printf(“String is %sn”,str);free(str); 本例中首先用malloc函數(shù)向內(nèi)存申請一塊內(nèi)存區(qū),并把首地址賦予指針變量str,是str指向該區(qū)域。最后用free函數(shù)釋放str指向的內(nèi)存空間。整個(gè)程序包含了申請內(nèi)存空間、使用內(nèi)存空間、釋放內(nèi)存空間三個(gè)步驟,實(shí)現(xiàn)存儲空間的動態(tài)分配。8.5.2 動態(tài)鏈表的基本操作鏈表有五種基本操作:建立插入刪除輸出查找1.單鏈表的創(chuàng)建建立動態(tài)鏈表就是建立結(jié)點(diǎn)空間、輸入各結(jié)點(diǎn)數(shù)據(jù)和進(jìn)行結(jié)點(diǎn)鏈接的過程,也就是在程序執(zhí)行過程中從無到有地建立起一個(gè)鏈表。通過以下實(shí)例來說明如何建立一個(gè)動態(tài)鏈表。 【例 8.12】建立一個(gè)鏈

29、表存放學(xué)生數(shù)據(jù)。為簡單起見,我們假定學(xué)生數(shù)據(jù)結(jié)構(gòu)中有學(xué)號和年齡兩項(xiàng)。編寫一個(gè)建立鏈表的函數(shù)creat。創(chuàng)建單鏈表的算法單鏈表創(chuàng)建過程分析創(chuàng)建單鏈表實(shí)例程序清單#define LEN sizeof(struct stu)sruct stu /*結(jié)構(gòu)stu定義為外部類型,方便程序中的各個(gè)函數(shù)使用*/ int num; int age; struct stu *next;struct stu *creat(void)/*creat函數(shù)用語動態(tài)建立一個(gè)有n個(gè)結(jié)點(diǎn)的鏈表,返回與結(jié)點(diǎn)相同類型的指針*/ struct stu *p1,*p2,*head;/*head為頭指針,p2指向已建鏈表的最后一個(gè)結(jié)點(diǎn),

30、p1始終指向當(dāng)前新開辟的結(jié)點(diǎn)*/ int n=0; p1=p2=(struct stu *) malloc(LEN);/*申請新結(jié)點(diǎn),長度與stu長度相等;同時(shí)使指針變量p1、p2指向新結(jié)點(diǎn)*/ scanf (“%d %d”,&p1-num,&p1-page); /*輸入結(jié)點(diǎn)的值*/ head=NULL; while (p1-num!=0) /*輸入結(jié)點(diǎn)的數(shù)值不為0*/ n+; if(n=1)head=p1; /*輸入的結(jié)點(diǎn)為第一個(gè)新結(jié)點(diǎn)即空表,將輸入的結(jié)點(diǎn)數(shù)據(jù)接入表頭*/ else p2-next=p1;/*非空表即輸入的結(jié)點(diǎn)不是第一個(gè)結(jié)點(diǎn),將輸入的結(jié)點(diǎn)數(shù)據(jù)接到表尾*/p2=p1;p1=(s

31、truct stu *)malloc(LEN); /*申請下一個(gè)新結(jié)點(diǎn)*/scanf(“%d %d”,&p1-num,&p1-page);p2-next=NULL;return(head); /*返回鏈表的頭指針*/建立鏈表的具體步驟(1)定義鏈表的數(shù)據(jù)結(jié)構(gòu)。(2)創(chuàng)建一個(gè)空表。(3)利用malloc()函數(shù)向系統(tǒng)申請分配一個(gè)結(jié)點(diǎn)。(4)若是空表,則將新結(jié)點(diǎn)接到表頭;若是非空表,則將新結(jié)點(diǎn)接到表尾。(5)判斷一下是否有后續(xù)結(jié)點(diǎn)要接入鏈表,若有則轉(zhuǎn)到步驟(3),否則結(jié)束。2.單鏈表的插入 鏈表的插入是指將一個(gè)結(jié)點(diǎn)插入到一個(gè)已有的鏈表中。 【例 8.13】以前面建立的動態(tài)鏈表為例,編寫一個(gè)函數(shù),使

32、其能夠在鏈表中指定的位置插入一個(gè)結(jié)點(diǎn)。單鏈表插入實(shí)例分析要在一個(gè)鏈表的指定位置插入結(jié)點(diǎn),要求鏈表本身必須已按某種規(guī)律進(jìn)行了排序。例如學(xué)生數(shù)據(jù)鏈表中,各結(jié)點(diǎn)的成員項(xiàng)按學(xué)號由小到大順序排列。如果要求按學(xué)號順序插入一個(gè)結(jié)點(diǎn),則要將插入的結(jié)點(diǎn)依次與鏈表中各結(jié)點(diǎn)比較,尋找插入位置。結(jié)點(diǎn)可以插在表頭、表中、表尾。結(jié)點(diǎn)插入存在以下幾種情況。1. 如果原表是空表,只需使鏈表的頭指針head指向被插結(jié)點(diǎn)。2. 如果被插結(jié)點(diǎn)值最小,則應(yīng)插入第一個(gè)結(jié)點(diǎn)之前。將頭指針head指向被插結(jié)點(diǎn),被插結(jié)點(diǎn)的指針域指向原來的第一個(gè)結(jié)點(diǎn)。3. 如果在鏈表中某位置插入,使插入位置的前一結(jié)點(diǎn)的指針域指向被插結(jié)點(diǎn),使被插結(jié)點(diǎn)的指針域指

33、向插入位置的后一個(gè)結(jié)點(diǎn)。4. 如果被插結(jié)點(diǎn)值最大,則在表尾插入,使原表尾結(jié)點(diǎn)指針域指向被插結(jié)點(diǎn),被插結(jié)點(diǎn)指針域置為NULL。單鏈表插入實(shí)例圖形分析單鏈表插入實(shí)例操作步驟單鏈表插入實(shí)例程序清單struct stu *insert (struct stu *head,struct stu *p1) struct stu *p2,*p3; p2=head; if(head=NULL) /*空表插入*/ head=p1; p1-next=NULL;else while (p1-nump2-num)&(p2-next!=NULL) p3=p2; p2=p2-next; /*找插入位置*/if ( p1-

34、numnum) if (head=p2) head=p1; /*在第一結(jié)點(diǎn)之前插入*/ else p3-next=p1; /*在其他位置插入*/ p1-next=p2; else p2-next=p1;p1-next=NULL; /*在表末插入*/ return head; /*返回鏈表的頭指針*/鏈表插入操作的具體步驟定義一個(gè)指針變量p1指向被插結(jié)點(diǎn)。首先判斷鏈表是否為空,為空則使head指向被插結(jié)點(diǎn)。鏈表若不是空,用當(dāng)型循環(huán)查找插入位置。找到插入位置后判斷是否在第一個(gè)結(jié)點(diǎn)之前插入,若是則使head指向被插入結(jié)點(diǎn),被插結(jié)點(diǎn)指針域指向原第一結(jié)點(diǎn);否則在其他位置插入;若插入的結(jié)點(diǎn)大于表中所有結(jié)點(diǎn)

35、,則在表末插入。函數(shù)返回值為鏈表的頭指針。3.單鏈表的刪除 鏈表中不再使用的數(shù)據(jù),可以將其從表中刪除并釋放其所占用的空間,但注意在刪除結(jié)點(diǎn)的過程中不能破壞鏈表的結(jié)構(gòu)?!纠?8.14】以前面建立的動態(tài)鏈表為例,編寫一個(gè)刪除鏈表中指定結(jié)點(diǎn)的函數(shù)delete1。單鏈表的刪除實(shí)例分析假設(shè)鏈表按學(xué)生的學(xué)號排列,當(dāng)某結(jié)點(diǎn)的學(xué)號與指定值相同時(shí),將該結(jié)點(diǎn)從鏈表中刪除。首先從頭到尾依次查找鏈表中給結(jié)點(diǎn),并與各結(jié)點(diǎn)的學(xué)生學(xué)號做比較,若相同,則查找成功,否則,找不到結(jié)點(diǎn)。由于結(jié)點(diǎn)在鏈表中可以有三種不同位置:位于開頭,中間或結(jié)尾,因此從鏈表中刪除一個(gè)結(jié)點(diǎn)主要分兩種情況,即刪除鏈表頭結(jié)點(diǎn)和非表頭結(jié)點(diǎn)。1. 如果被刪除的

36、結(jié)點(diǎn)是表頭結(jié)點(diǎn),使head指向第二個(gè)結(jié)點(diǎn)。2. 如果被刪除的結(jié)點(diǎn)不是表頭結(jié)點(diǎn),使被刪結(jié)點(diǎn)的前一結(jié)點(diǎn)指向被刪結(jié)點(diǎn)的后一結(jié)點(diǎn)。單鏈表的刪除實(shí)例圖形分析單鏈表 的刪除實(shí)例操作步驟單鏈表的刪除實(shí)例程序清單struct stu * delete ( struct stu *head,int num) /*以head為頭指針刪除num所在結(jié)點(diǎn)*/ struct stu *p1,*p2; if (head=NULL) /*如為空表,輸出提示信息*/ printf(“nempty list!n”); goto end;p1=head;while ( p1-num!=num & p1-next!=NULL)/*

37、當(dāng)不是要刪除的結(jié)點(diǎn),而且也不是最后一個(gè)結(jié)點(diǎn)時(shí),繼續(xù)循環(huán)*/p2=p1;p1=p1-next; /*p2指向當(dāng)前結(jié)點(diǎn),p1指向下一結(jié)點(diǎn)*/if (p1-num=num) if (p1=head) head=p1-next;/*如找到被刪結(jié)點(diǎn),且為第一結(jié)點(diǎn),則使head指向第二結(jié)點(diǎn),否則使p2所指結(jié)點(diǎn)的指針指向下一結(jié)點(diǎn)*/else p2-next=p1-next;free(p1);printf (“ The node is deletedn”); else printf (“The node not been found!n”); end: return (head);鏈表刪除操作的具體步驟 定義

38、一個(gè)指針變量p指向鏈表的頭結(jié)點(diǎn)。用循環(huán)從頭到尾依次查找鏈表中各結(jié)點(diǎn)并與各結(jié)點(diǎn)的學(xué)生學(xué)號做比較,若相同,則查找成功退出循環(huán)。判斷該結(jié)點(diǎn)是否為表頭結(jié)點(diǎn),如果是使head指向第二個(gè)結(jié)點(diǎn),如果不是使被刪結(jié)點(diǎn)的前一結(jié)點(diǎn)指向被刪結(jié)點(diǎn)的后一結(jié)點(diǎn)。同時(shí)結(jié)點(diǎn)個(gè)數(shù)減1。4.單鏈表的輸出 鏈表的輸出比較簡單,只要將鏈表中的各個(gè)結(jié)點(diǎn)數(shù)據(jù)依次輸出即可 【例 8.15】編寫一個(gè)輸出鏈表的函數(shù)print。設(shè)立一個(gè)指針變量p,先指向鏈表的頭結(jié)點(diǎn),輸出該結(jié)點(diǎn)的數(shù)據(jù)域,然后使指針p指向下一個(gè)結(jié)點(diǎn),重復(fù)上述工作,直到鏈表尾部。具體算法如圖8-9所示。 單鏈表的輸出實(shí)例程序清單#define LEN sizeof (struct s

39、tu)struct stu int num; int age; struct stu *next;void print ( struct stu *head) /*print函數(shù)用于輸出以head為頭的鏈表各結(jié)點(diǎn)的值*/ struct stu *p; p=head; /*取得鏈表的頭指針*/ while (p!=NULL) printf ( “%6d%6d”,p-num,p-page); /*輸出鏈表結(jié)點(diǎn)的值*/p=p-next; /*使指針變量p指向下一個(gè)結(jié)點(diǎn),跟蹤鏈表增長*/鏈表輸出操作的具體步驟定義一個(gè)指針變量p。使p指向鏈表的頭結(jié)點(diǎn)。若是非空表,輸出該結(jié)點(diǎn)的數(shù)據(jù)域;若空表則退出。使指針

40、p指向下一個(gè)結(jié)點(diǎn)。重復(fù)上述操作直到鏈表尾部。鏈表綜合實(shí)例【例 8.16】在前面學(xué)習(xí)的建立鏈表,輸出鏈表,刪除結(jié)點(diǎn),插入結(jié)點(diǎn)操作的基礎(chǔ)上,試編一主函數(shù)將以上的建立鏈表,輸出鏈表,刪除結(jié)點(diǎn),插入結(jié)點(diǎn)的函數(shù)組織在一起,并輸出全部結(jié)點(diǎn)的值。綜合實(shí)例程序清單#define NULL 0main () struct stu *head; struct stu *stu; int del_num; printf (“input records:n”); head=creat(); /*建立鏈表,并返回表頭*/ print (head); /*輸出鏈表 */ printf (“nInput the delet

41、ed number:”); scanf (“%d”,&del_num);綜合實(shí)例程序清單(續(xù))while (del_num!=0) head=delete1 (head,del_num); /*從鏈表中刪除del_num結(jié)點(diǎn)*/print (head); /*輸出鏈表 */ printf (“nInput the deleted number:”); scanf (“%d”,&del_num);printf (“nInput the inserted record:”);stu=(struct stu *)malloc(LEN);scanf (“%d,%d”,&stu-num,&stu-age

42、);while (stu-num!=0) head=insert (head,stu); /*在鏈表中插入一節(jié)結(jié)點(diǎn)stu*/ print (head); /*輸出鏈表 */ printf (“nInput the inserted record:”); stu=( struct student *)malloc (LEN); scanf (“%d,%d”,&stu-num,&stu-age); free (stu) /*對于num=0的結(jié)點(diǎn),未插入,應(yīng)刪除其空間*/8.6 共 用 型共用型和結(jié)構(gòu)型的比較8.6.1 共用型的定義union共用型名 數(shù)據(jù)類型1 成員名1; 數(shù)據(jù)類型2 成員名2;

43、數(shù)據(jù)類型n 成員名n; ;注意在右花括號的后面有一個(gè)語句結(jié)束符分號。共用型的定義實(shí)例例如:為了節(jié)省內(nèi)存,可以將不同的三個(gè)數(shù)組定義在一個(gè)共用型中,總計(jì)可節(jié)省300個(gè)單元: union c_i_f char c1100; /*該成員占用100個(gè)單元*/ int i2100; /*該成員占用200個(gè)單元*/ float f3100; /*該成員占用400個(gè)單元*/ ; /*該共用型數(shù)據(jù)共用400個(gè)單元*/需要提醒讀者注意的是,共用型數(shù)據(jù)中每個(gè)成員所占用的內(nèi)存單元都是連續(xù)的,而且都是從分配的連續(xù)內(nèi)存單元中第一個(gè)內(nèi)存單元開始存放的。所以,對共用型數(shù)據(jù)來說,所有成員的首地址都是相同的。這是共用型數(shù)據(jù)的一個(gè)

44、特點(diǎn)。8.6.2 共用型變量的定義定義方法基本上與結(jié)構(gòu)型相同,也存在以下三種方法,但不能在定義時(shí)進(jìn)行初始化。1. 先定義共用型,然后定義變量與數(shù)組。2. 定義共用型的同時(shí)定義變量與數(shù)組3. 定義無名稱的共用型同時(shí)定義變量與數(shù)組 1.先定義共用型,然后定義變量u1與數(shù)組u25。union u int i_a10; /*該成員占用20個(gè)單元*/ char c_a34; /*該成員占用12個(gè)單元*/ long l; /*該成員占用4個(gè)單元*/ double d; /*該成員占用8個(gè)單元*/; /*該共用型數(shù)據(jù)共占用20個(gè)單元*/union u u1,u25;2.定義共用型的同時(shí)定義變量u1與數(shù)組u2

45、5 union u int i_a10; /*該成員占用20個(gè)單元*/ char c_a34; /*該成員占用12個(gè)單元*/ long l; /*該成員占用4個(gè)單元*/ double d; /*該成員占用8個(gè)單元*/ u1,u25; 3. 定義無名稱的共用型同時(shí)定義變量u1與數(shù)組u25 union /*無名稱*/int i_a10; /*該成員占用20個(gè)單元*/ char c_a34; /*該成員占用12個(gè)單元*/ long l; /*該成員占用4個(gè)單元*/ double d; /*該成員占用8個(gè)單元*/ u1,u25; 8.6.3 共用型變量的引用共用型變量或數(shù)組元素成員的引用格式如下: 共

46、用型變量名.成員名共用型變量成員地址的引用和指針變量的使用格式如下: 指針變量=&共用型變量名.成員名共用型變量地址的引用和指針變量的使用格式如下: 指針變量=&共用型變量名8.7 枚舉型顧名思義,就是把有限的數(shù)據(jù)一一例舉出來,例如:一個(gè)星期7天性別只有”男”和”女” 中國有23個(gè)省,5個(gè)自治區(qū),4個(gè)直轄市,2個(gè)特別行政區(qū)等。如下圖:在填寫用戶資料中的所在城市時(shí),把中國的23個(gè)省,5個(gè)自治區(qū),4個(gè)直轄市,2個(gè)特別行政區(qū)都列舉出來,供注冊者選擇,這樣有利于數(shù)據(jù)的規(guī)范且不會出錯(cuò)。枚舉型和結(jié)構(gòu)型、共用型一樣,也是一種用戶自定義的數(shù)據(jù)類型,在使用時(shí)必須先定義后使用。8.7.1 枚舉型的定義enum 枚

47、舉型名 枚舉常量1,枚舉常量2,枚舉常量n;注意在右花括號的后面有一個(gè)語句結(jié)束符分號。其中:枚舉型名是用戶取的標(biāo)識符; 枚舉常量是用戶給常量取的標(biāo)識符。該語句定義了一個(gè)名為“枚舉型名”的枚舉類型,該枚舉型中含有n個(gè)枚舉常量,每個(gè)枚舉型常量均有值。C語言規(guī)定枚舉常量的值依次等于0、1、2、n-1.枚舉型定義實(shí)例例如:定義一個(gè)表示星期的枚舉型: enum week sun,mon,tue,wed,thu,fri,sat; 定義的這個(gè)枚舉型共有7個(gè)枚舉常量,它們的值依次為0、1、2、3、4、5、6。 C語言規(guī)定,在定義枚舉型時(shí),可以給枚舉常量賦初值,方法是在枚舉常量的后面跟上“=整型常量”。例如:表示三原色的枚舉型可定義如下: enum color1 red=2,yellow=4,blue=7; 則枚舉常量red的值為2,yellow的值為4,blue的值為7。8.7.2 枚舉型變量的定義當(dāng)某個(gè)枚舉型定義后,可以用這種枚舉型來定義變量、數(shù)組。定義的方法有三種。1. 先定義枚舉型,后定義枚舉型變量、數(shù)組enum colorred,yellow,blue;enum color color_1,color_22; /*定義一個(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)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論