C語(yǔ)言程序設(shè)計(jì)教程第9章結(jié)構(gòu)體與共用體.ppt
1,第9章結(jié)構(gòu)體與共用體,北京科技大學(xué)計(jì)算機(jī)系,C語(yǔ)言程序設(shè)計(jì),2020/4/25,2,第9章結(jié)構(gòu)體與共用體,9.1結(jié)構(gòu)體9.2共用體9.3枚舉類型與類型命名,2020/4/25,3,一個(gè)學(xué)生的信息有學(xué)號(hào)、姓名、性別、年齡、住址、成績(jī)等。一本圖書(shū)的信息有分類編號(hào)、書(shū)名、作者、出版社、出版日期、價(jià)格、庫(kù)存量等。如何描述這些類型不同的相關(guān)數(shù)據(jù)?,9.1結(jié)構(gòu)體,9.1.1結(jié)構(gòu)體與結(jié)構(gòu)體類型的定義,?,信息管理,結(jié)構(gòu)體一種構(gòu)造類型數(shù)據(jù)結(jié)構(gòu)體由若干不同類型的數(shù)據(jù)項(xiàng)組成,構(gòu)成結(jié)構(gòu)體的各個(gè)數(shù)據(jù)項(xiàng)稱為結(jié)構(gòu)體成員。,2020/4/25,4,struct結(jié)構(gòu)體名數(shù)據(jù)類型1成員名1;數(shù)據(jù)類型2成員名2;數(shù)據(jù)類型n成員名n;,9.1結(jié)構(gòu)體,9.1.1結(jié)構(gòu)體與結(jié)構(gòu)體類型的定義,結(jié)構(gòu)體類型定義的一般形式:,struct為關(guān)鍵字;結(jié)構(gòu)體名是用戶定義的類型標(biāo)識(shí)。中是組成該結(jié)構(gòu)體的成員。成員的數(shù)據(jù)類型可以是C語(yǔ)言所允許的任何數(shù)據(jù)類型。,2020/4/25,5,例如圖書(shū)類型的定義:structbookcardcharnum10;/*圖書(shū)分類編號(hào)是字符數(shù)組類型*/charname30;/*書(shū)名是字符數(shù)組類型*/charauthor30;/*作者是字符數(shù)組類型*/charpublisher60;/*出版社是字符數(shù)組類型*/floatprice;/*價(jià)格是單精度實(shí)型*/intn;/*庫(kù)存量是整型*/;,例如學(xué)生類型的定義:structstudentcharnum8;/*學(xué)號(hào)是字符數(shù)組類型*/charname30;/*姓名是字符數(shù)組類型*/charsex;/*性別是字符型*/intage;/*年齡是整型*/charaddr60;/*住址是字符數(shù)組類型*/intscore6;/*成績(jī)是整型數(shù)組類型*/;,9.1結(jié)構(gòu)體,9.1.1結(jié)構(gòu)體與結(jié)構(gòu)體類型的定義,2020/4/25,6,9.1結(jié)構(gòu)體,9.1.2結(jié)構(gòu)體變量的定義與初始化,1.結(jié)構(gòu)體類型變量的定義,利用已定義的結(jié)構(gòu)體類型名定義變量struct結(jié)構(gòu)體名變量名表;例如:structbookcardbook1100;structstudents30,t1,t2;,按照結(jié)構(gòu)體類型的組成,系統(tǒng)為定義的結(jié)構(gòu)體變量分配內(nèi)存單元。結(jié)構(gòu)體變量的各個(gè)成員在內(nèi)存中占用連續(xù)存儲(chǔ)區(qū)域,結(jié)構(gòu)體變量所占內(nèi)存大小為結(jié)構(gòu)體中每個(gè)成員所占用內(nèi)存的長(zhǎng)度之和。,2020/4/25,7,9.1結(jié)構(gòu)體,結(jié)構(gòu)體類型與變量的說(shuō)明,類型與變量是不同的概念。應(yīng)先定義一個(gè)結(jié)構(gòu)體類型,而后再定義結(jié)構(gòu)體變量。系統(tǒng)對(duì)類型不分配空間,僅對(duì)變量分配空間。只能對(duì)變量賦值、存取或運(yùn)算,而不能對(duì)一個(gè)類型賦值、存取或運(yùn)算。,成員也可以是結(jié)構(gòu)變量。,對(duì)結(jié)構(gòu)中的成員,可以單獨(dú)使用,它的作用與地位相當(dāng)于普通變量。成員名可與程序中的變量名相同時(shí),也可與不同結(jié)構(gòu)體類型的成員名相同,二者代表不同的對(duì)象。,structdateintyear,month,day;structstudentcharnum8;charname30;charsex;structdatebirthday;/*成員為結(jié)構(gòu)體類型*/charaddr60;intscore6;,2020/4/25,8,9.1結(jié)構(gòu)體,9.1.2結(jié)構(gòu)體變量的定義與初始化,1.結(jié)構(gòu)體類型變量的定義,在定義結(jié)構(gòu)體類型的同時(shí)定義變量,例如:structstudentcharnum8,name20,sex;intage;floatscore;st30;,struct結(jié)構(gòu)體名成員定義表;變量名表;,2020/4/25,9,9.1結(jié)構(gòu)體,9.1.2結(jié)構(gòu)體變量的定義與初始化,1.結(jié)構(gòu)體類型變量的定義,直接定義結(jié)構(gòu)體類型變量,例如:structcharnum8,name20,sex;intage;floatscore;st30,a,b,c;,struct成員定義表;變量名表;,2020/4/25,10,9.1結(jié)構(gòu)體,9.1.2結(jié)構(gòu)體變量的定義與初始化,2.結(jié)構(gòu)體變量的初始化,【例9.4】結(jié)構(gòu)體變量的初始化。structdateintyear,month,day;structstudentcharnum8,name20,sex;structdatebirthday;floatscore;a="9606011","Liming",M,1977,12,9,83,b="9608025","Zhangliming",F,1978,5,10,87,c;,如果初值個(gè)數(shù)少于結(jié)構(gòu)體成員個(gè)數(shù),則將無(wú)初值對(duì)應(yīng)的成員賦以0值。如果初值個(gè)數(shù)多于結(jié)構(gòu)體成員個(gè)數(shù),則編譯出錯(cuò)。,2020/4/25,11,9.1結(jié)構(gòu)體,9.1.2結(jié)構(gòu)體變量的定義與初始化,2.結(jié)構(gòu)體變量的初始化,【例9.5】結(jié)構(gòu)體數(shù)組的初始化。structscharnum8,name20,sex;floatscore;stu3="9606011","Liming",M,87.5,"9606012","Zhangjiangguo",M,79,"9606013","Wangping",F,90;,元素的個(gè)數(shù)可以省略,根據(jù)賦初值時(shí)結(jié)構(gòu)體常量的個(gè)數(shù)確定數(shù)組元素的個(gè)數(shù),2020/4/25,12,9.1結(jié)構(gòu)體,9.1.2結(jié)構(gòu)體變量的定義與初始化,3.結(jié)構(gòu)體變量的運(yùn)算,用sizeof運(yùn)算符計(jì)算結(jié)構(gòu)體變量所占內(nèi)存空間,structdateintyear,month,day;structstudentcharnum8,name20,sex;structdatebirthday;floatscore;a;,sizeof(a)的結(jié)果為8+20+1+6+4=39sizeof(structstudent)的結(jié)果為39,2020/4/25,13,9.1結(jié)構(gòu)體,9.1.2結(jié)構(gòu)體變量的定義與初始化,3.結(jié)構(gòu)體變量的運(yùn)算,同類型結(jié)構(gòu)體變量之間的賦值運(yùn)算,結(jié)構(gòu)體變量之間進(jìn)行賦值時(shí),系統(tǒng)將按成員一一對(duì)應(yīng)賦值。,structdateintyear,month,day;structstudentcharnum8,name20,sex;structdatebirthday;floatscore;a="9606011","Liming",M,1977,12,9,83,b,c;c=a;,2020/4/25,14,9.1結(jié)構(gòu)體,9.1.2結(jié)構(gòu)體變量的定義與初始化,3.結(jié)構(gòu)體變量的運(yùn)算,對(duì)結(jié)構(gòu)體變量進(jìn)行取址運(yùn)算,structdateintyear,month,day;structstudentcharnum8,name20,sex;structdatebirthday;floatscore;a;,對(duì)結(jié)構(gòu)體變量a進(jìn)行;structstudentcharnum8,name20,sex;structdatebirthday;floatscore;a;,“.”是分量運(yùn)算符,運(yùn)算級(jí)別最高。,a.birthday.yeara.birthday.montha.birthday.day,結(jié)構(gòu)體變量的各個(gè)成員可進(jìn)行何種運(yùn)算,由該成員的數(shù)據(jù)類型決定,2020/4/25,16,9.1結(jié)構(gòu)體,9.1.2結(jié)構(gòu)體變量的定義與初始化,【例9.6】編寫(xiě)一個(gè)統(tǒng)計(jì)選票的程序。structcandidatecharname20;/*name為候選人姓名*/intcount;/*count為候選人得票數(shù)*/list="invalid",0,"Zhao",0,"Qian",0,"Sun",0,"Li",0,"Zhou",0;,2020/4/25,17,9.1結(jié)構(gòu)體,9.1.2結(jié)構(gòu)體變量的定義與初始化,main()inti,n;printf("Entervoten");scanf("%d",/*輸入所投候選人編號(hào)*/,2020/4/25,18,9.1結(jié)構(gòu)體,9.1.2結(jié)構(gòu)體變量的定義與初始化,for(i=1;iyearp->monthp->day,“->”是指向結(jié)構(gòu)體成員運(yùn)算符,優(yōu)先級(jí)為一級(jí),p=today,*p=,2020/4/25,22,9.1結(jié)構(gòu)體,9.1.3結(jié)構(gòu)體的指針,3.指向結(jié)構(gòu)體數(shù)組的指針,【例9.7】利用結(jié)構(gòu)體指針輸出一組化學(xué)元素名稱及其原子量。structlistinti;charname4;floatw;tab4=1,"H",1.008,2,"He",4.0026,3,"Li",6.941,4,"Be",9.01218;,2020/4/25,23,9.1結(jié)構(gòu)體,9.1.3結(jié)構(gòu)體的指針,3.指向結(jié)構(gòu)體數(shù)組的指針,main()structlist*p;printf("NotNametAtomicWeightn");for(p=tab;pi,p->name,p->w);,NoNameAtomicWeight,1H1.008,2He4.0026,3Li6.941,4Be9.01218,2020/4/25,24,9.1結(jié)構(gòu)體,9.1.3結(jié)構(gòu)體的指針,【例9.8】分析自增自減運(yùn)算對(duì)程序結(jié)果的影響。structcodeinti;charc;a=100,A,200,B,300,C,400,D;,2020/4/25,25,9.1結(jié)構(gòu)體,9.1.3結(jié)構(gòu)體的指針,main()structcode*p=a;printf("%dt",+p->i);printf("%ct",(+p)->c);printf("%dt",(p+)->i);printf("%ct",+p->c);printf("%dt",p->i+);printf("%dn",p->i);,p,101,D,301,101,B,200,D,300,301,2020/4/25,26,9.1結(jié)構(gòu)體,9.1.4函數(shù)間結(jié)構(gòu)體數(shù)據(jù)的傳遞,方法一:在函數(shù)之間直接傳遞結(jié)構(gòu)體數(shù)據(jù)。函數(shù)的形參定義為結(jié)構(gòu)體變量。函數(shù)調(diào)用時(shí),可將主調(diào)函數(shù)的結(jié)構(gòu)體類型實(shí)參傳遞給被調(diào)函數(shù)的形參。如果將函數(shù)定義為結(jié)構(gòu)體類型函數(shù),可利用return語(yǔ)句將一個(gè)結(jié)構(gòu)體數(shù)據(jù)結(jié)果返回到主調(diào)函數(shù)中。,2020/4/25,27,9.1結(jié)構(gòu)體,9.1.4函數(shù)間結(jié)構(gòu)體數(shù)據(jù)的傳遞,方法二:在函數(shù)之間傳遞結(jié)構(gòu)體指針。形參定義為指向結(jié)構(gòu)體類型的指針變量,可將主調(diào)函數(shù)的結(jié)構(gòu)體指針傳遞給被調(diào)函數(shù)的形參變量,通過(guò)指針形參的指向域的擴(kuò)展,操作主調(diào)函數(shù)中結(jié)構(gòu)體變量及其成員。如果將函數(shù)定義為結(jié)構(gòu)體指針型函數(shù),可利用return語(yǔ)句將被調(diào)函數(shù)中結(jié)構(gòu)體變量的指針?lè)祷亟o主調(diào)函數(shù)的結(jié)構(gòu)體指針變量。方法三:利用全局結(jié)構(gòu)體變量傳遞結(jié)構(gòu)體數(shù)據(jù)。,2020/4/25,28,9.1結(jié)構(gòu)體,9.1.4函數(shù)間結(jié)構(gòu)體數(shù)據(jù)的傳遞,【例9.9】編制一個(gè)復(fù)數(shù)乘法函數(shù),采用值傳遞的方法傳送數(shù)據(jù)。structcomplex/*定義存放復(fù)數(shù)的結(jié)構(gòu)體類型*/floatre;/*re成員用于存放復(fù)數(shù)的實(shí)部*/floatim;/*im成員用于存放復(fù)數(shù)的虛部*/;,2020/4/25,29,9.1結(jié)構(gòu)體,9.1.4函數(shù)間結(jié)構(gòu)體數(shù)據(jù)的傳遞,structcomplexmultiplier(structcomplexcx,structcomplexcy)structcomplexcz;cz.re=cx.re*cy.re-cx.im*cy.im;cz.im=cx.re*cy.im+cx.im*cy.re;return(cz);,形參是結(jié)構(gòu)體變量。調(diào)用此函數(shù)時(shí),系統(tǒng)將分別為形參cx和cy各分配一個(gè)sizeof(structcomplex)大小的內(nèi)存空間,每個(gè)成員都要一一傳遞。,2020/4/25,30,9.1結(jié)構(gòu)體,9.1.4函數(shù)間結(jié)構(gòu)體數(shù)據(jù)的傳遞,main()structcomplexx,y,z;x.re=3.2;x.im=1.5;y.re=2.7;y.im=4.6;z=multiplier(x,y);printf("%f+%fin",z.re,z.im);/*以復(fù)數(shù)形式輸出*/,2020/4/25,31,9.1結(jié)構(gòu)體,9.1.4函數(shù)間結(jié)構(gòu)體數(shù)據(jù)的傳遞,【例9.10】編制一個(gè)復(fù)數(shù)乘法函數(shù),采用傳遞指針的方法達(dá)到傳送數(shù)據(jù)的目的。structcomplexfloatre,im;voidmultiplier(structcomplex*px,structcomplex*py,structcomplex*pz)pz->re=px->re*py->re-px->im*py->im;pz->im=px->re*py->im+px->im*py->re;,形參定義為指針型參數(shù)。函數(shù)調(diào)用時(shí),實(shí)參傳遞的是結(jié)構(gòu)體指針(地址),因此形參px、py可讀取主調(diào)函數(shù)中變量的內(nèi)容,乘積結(jié)果也可通過(guò)形參pz指針存到主調(diào)函數(shù)中的目標(biāo)變量。這樣實(shí)參與形參之間的數(shù)據(jù)傳遞由多值(每個(gè)成員的值)變成了單值(結(jié)構(gòu)體變量的首地址)。,2020/4/25,32,9.1結(jié)構(gòu)體,9.1.4函數(shù)間結(jié)構(gòu)體數(shù)據(jù)的傳遞,main()structcomplexx,y,z;x.re=3.2;x.im=1.5;y.re=2.7;y.im=4.6;multiplier(,2020/4/25,33,鏈表是一種動(dòng)態(tài)數(shù)據(jù)結(jié)構(gòu),可根據(jù)需要?jiǎng)討B(tài)地分配存儲(chǔ)單元。在數(shù)組中,插入或刪除一個(gè)元素都比較繁瑣,而用鏈表則相對(duì)容易。但是數(shù)組元素的引用比較簡(jiǎn)單,對(duì)于鏈表中結(jié)點(diǎn)數(shù)據(jù)的存取操作則相對(duì)復(fù)雜。,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,鏈表中每個(gè)元素稱為一個(gè)結(jié)點(diǎn)。構(gòu)成鏈表的結(jié)點(diǎn)必須是結(jié)構(gòu)體類型數(shù)據(jù)。,1.鏈表的基本結(jié)構(gòu),相鄰結(jié)點(diǎn)的地址不一定是連續(xù)的,依靠指針將它們連接起來(lái)。,structnodecharc;structnode*next;,2020/4/25,34,C語(yǔ)言提供了相關(guān)的存儲(chǔ)管理庫(kù)函數(shù)。這里僅介紹其中三個(gè),它們的原型說(shuō)明在“stdlib.h”頭文件和“alloc.h”頭文件中,使用這三個(gè)函數(shù)時(shí),應(yīng)選擇其中一個(gè)頭文件包含到源程序中。,動(dòng)態(tài)分配存儲(chǔ)區(qū)函數(shù)malloc()函數(shù)原型:void*malloc(unsignedsize);調(diào)用格式:malloc(size)功能:在內(nèi)存分配一個(gè)size字節(jié)的存儲(chǔ)區(qū)。調(diào)用結(jié)果為新分配的存儲(chǔ)區(qū)的首地址,是一個(gè)void類型指針。若分配失敗,則返回NULL(即0)。,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,2.動(dòng)態(tài)分配和釋放存儲(chǔ)單元,在ANSIC標(biāo)準(zhǔn)中,關(guān)鍵字void有兩種用法。第一種用法,可將無(wú)返回值的函數(shù)定義為void類型第二種用法,用void*定義指針,這是一個(gè)指向非具體數(shù)據(jù)類型的指針,稱為無(wú)類型指針。,2020/4/25,35,【例9.11】調(diào)用malloc函數(shù)分配所需存儲(chǔ)單元。#includemain()structstintn;structst*next;*p;p=(structst*)malloc(sizeof(structst);p->n=5;p->next=NULL;printf("p->n=%dtp->next=%xn",p->n,p->next);,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,2.動(dòng)態(tài)分配和釋放存儲(chǔ)單元,將函數(shù)返回值轉(zhuǎn)換成結(jié)構(gòu)體指針,2020/4/25,36,動(dòng)態(tài)分配存儲(chǔ)區(qū)函數(shù)calloc()函數(shù)原型:void*calloc(unsignedintn,unsignedintsize);調(diào)用格式:calloc(n,size)功能:在內(nèi)存分配一個(gè)n倍size字節(jié)的存儲(chǔ)區(qū)。調(diào)用結(jié)果為新分配的存儲(chǔ)區(qū)的首地址,是一個(gè)void類型指針。若分配失敗,則返回NULL(即0)。,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,2.動(dòng)態(tài)分配和釋放存儲(chǔ)單元,2020/4/25,37,【例9.12】調(diào)用calloc函數(shù)分配所需存儲(chǔ)單元。#includemain()inti,*ip;ip=(int*)calloc(10,2);for(i=0;i<10;i+)scanf("%d",ip+i);for(i=0;iname,name);/*為新結(jié)點(diǎn)中的成員賦值*/printf("tel:");gets(p->tel);p->next=NULL;if(h=NULL)/*h為空,表示新結(jié)點(diǎn)為第一個(gè)結(jié)點(diǎn)*/h=p;/*頭指針指向第一個(gè)結(jié)點(diǎn)*/else/*h不為空*/q->next=p;/*新結(jié)點(diǎn)與尾結(jié)點(diǎn)相連接*/q=p;/*使q指向新的尾結(jié)點(diǎn)*/printf("name:");gets(name);returnh;,structnode*create()staticstructnode*h;structnode*p,*q;charname20;h=NULL;printf("name:");gets(name);while(strlen(name)!=0)/*當(dāng)輸入的姓名不是空串循環(huán)*/p=NEW;/*開(kāi)辟新結(jié)點(diǎn)*/if(p=NULL)/*p為NULL,新結(jié)點(diǎn)分配失敗*/printf("Allocationfailuren");exit(0);/*結(jié)束程序運(yùn)行*/,#include#include#defineNEW(structnode*)malloc(sizeof(structnode)structnodecharname20,tel9;structnode*next;,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,main()structnode*head;head=create();,2020/4/25,41,【例9.14】輸出學(xué)生電話簿鏈表函數(shù)。,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,4.輸出單向鏈表中各結(jié)點(diǎn)信息,2020/4/25,42,voidprlist(structnode*head)structnode*p;p=head;while(p!=NULL)printf("%st%sn",p->name,p->tel);p=p->next;,#include#include#defineNEW(structnode*)malloc(sizeof(structnode)structnodecharname20,tel9;structnode*next;,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,main()structnode*head;head=create();prlist(head);,2020/4/25,43,在鏈表中,如果要?jiǎng)h除第i個(gè)結(jié)點(diǎn),一般是將第(i-1)個(gè)結(jié)點(diǎn)直接與第(i+1)個(gè)結(jié)點(diǎn)相連接,然后再釋放第i個(gè)結(jié)點(diǎn)的存儲(chǔ)單元。,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,5.刪除單向鏈表中指定的結(jié)點(diǎn),2020/4/25,44,【例9.15】刪除學(xué)生電話簿鏈表中指定學(xué)生的信息。,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,刪除第一個(gè)結(jié)點(diǎn),刪除中間結(jié)點(diǎn)或尾結(jié)點(diǎn),學(xué)生姓名,當(dāng)姓名不同并且不是尾結(jié)點(diǎn)循環(huán),2020/4/25,45,【例9.15】刪除學(xué)生電話簿鏈表中指定學(xué)生的信息。,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,(a)刪除第一個(gè)結(jié)點(diǎn)(head=p->next),2020/4/25,46,【例9.15】刪除學(xué)生電話簿鏈表中指定學(xué)生的信息。,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,(b)刪除中間結(jié)點(diǎn)或尾結(jié)點(diǎn)(q->next=p->next),2020/4/25,47,【例9.15】刪除學(xué)生電話簿鏈表中指定學(xué)生的信息。,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,(c)未找到指定的結(jié)點(diǎn)(strcmp(x,p->name)!=0),2020/4/25,48,if(strcmp(x,p->name)=0)if(p=head)head=p->next;/*刪除頭結(jié)點(diǎn)*/elseq->next=p->next;/*刪除中間或尾結(jié)點(diǎn)*/free(p);/*釋放被刪除的結(jié)點(diǎn)*/elseprintf("Notfound.");/*未找到指定的結(jié)點(diǎn)*/h=head;returnh;,#include#include#defineNEW(structnode*)malloc(sizeof(structnode)structnodecharname20,tel9;structnode*next;,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,2020/4/25,49,將一個(gè)新結(jié)點(diǎn)插入到鏈表中,首先要尋找插入的位置。如果要求在第i個(gè)結(jié)點(diǎn)前插入,可設(shè)置三個(gè)工作指針p0、p和q,p0是指向待插入結(jié)點(diǎn)的指針。利用p和q指針查找第i個(gè)結(jié)點(diǎn),找到后再將新結(jié)點(diǎn)鏈接到鏈表上。,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,6.在單向鏈表中插入結(jié)點(diǎn),q,q,新的第i個(gè)結(jié)點(diǎn),2020/4/25,50,【例9.16】在學(xué)生電話簿鏈表中插入一個(gè)學(xué)生的信息。要求將新的信息插入在指定學(xué)生信息之前,如果未找到指定學(xué)生,則追加在鏈表尾部。,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,當(dāng)姓名不同并且不是尾結(jié)點(diǎn)循環(huán),空表時(shí)插入結(jié)點(diǎn),在表尾追加結(jié)點(diǎn),在表頭插入結(jié)點(diǎn),在表中間插入結(jié)點(diǎn),2020/4/25,51,【例9.16】在學(xué)生電話簿鏈表中插入一個(gè)學(xué)生的信息。要求將新的信息插入在指定學(xué)生信息之前,如果未找到指定學(xué)生,則追加在鏈表尾部。,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,(a)在表頭插入結(jié)點(diǎn)(head=p0;p0->next=p),2020/4/25,52,【例9.16】在學(xué)生電話簿鏈表中插入一個(gè)學(xué)生的信息。要求將新的信息插入在指定學(xué)生信息之前,如果未找到指定學(xué)生,則追加在鏈表尾部。,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,(b)在表中間插入結(jié)點(diǎn)(q->next=p0;p0->next=p),2020/4/25,53,【例9.16】在學(xué)生電話簿鏈表中插入一個(gè)學(xué)生的信息。要求將新的信息插入在指定學(xué)生信息之前,如果未找到指定學(xué)生,則追加在鏈表尾部。,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,(c)在表尾追加結(jié)點(diǎn)(p->next=p0;p0->next=NULL),2020/4/25,54,if(strcmp(x,p->name)=0)if(p=head)head=p0;/*在表頭插入結(jié)點(diǎn)*/elseq->next=p0;/*在表中間插入結(jié)點(diǎn)*/p0->next=p;elsep->next=p0;/*在表尾插入結(jié)點(diǎn)*/p0->next=NULL;h=head;returnh;,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,#include#include#defineNEW(structnode*)malloc(sizeof(structnode)structnodecharname20,tel9;structnode*next;,2020/4/25,55,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,【例9.17】學(xué)生電話簿鏈表管理程序。,編制此程序可利用例9.13至例9.16的4個(gè)函數(shù)完成鏈表的建立、輸出、刪除和插入等功能,這里只需編制一個(gè)main函數(shù)完成對(duì)這4個(gè)函數(shù)的調(diào)用。#include#defineNEW(structnode*)malloc(sizeof(structnode)structnodecharname20,tel9;structnode*next;,2020/4/25,56,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,main()structnode*create(),*delnode(structnode*,char*);structnode*insert(structnode*,structnode*,char*);voidprlist(structnode*);structnode*head=NULL,*stu;chars80,name20;intc;,2020/4/25,57,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,dodoprintf("n*MENU*n");printf("1.Createalistn");printf("2.Printalistn");printf("3.Deleteanoden");printf("4.Insertanoden");printf("0.Quitn");printf("Enteryourchoice(0-4):");gets(s);c=atoi(s);while(c4);,可以先選擇1建立一個(gè)鏈表,然后根據(jù)需要選擇功能2、功能3、功能4、直到選擇0退出程序的運(yùn)行,2020/4/25,58,9.1結(jié)構(gòu)體,9.1.5結(jié)構(gòu)體的應(yīng)用鏈表,switch(c)case1:head=create();break;case2:prlist(head);break;case3:printf("nInputanamedeleted:n");gets(name);head=delnode(head,name);break;case4:stu=NEW;printf("nInputanewnoden");printf("name:");gets(stu->name);printf("tel:");gets(stu->tel);stu->next=NULL;printf("nInsertpositionn");printf("name:");gets(name);head=insert(head,stu,name);while(c);,2020/4/25,59,結(jié)構(gòu)體類型解決了如何描述一個(gè)邏輯上相關(guān),但數(shù)據(jù)類型不同的一組分量的集合。在需要節(jié)省內(nèi)存儲(chǔ)空間時(shí),c語(yǔ)言還提供了一種由若干個(gè)不同類型的數(shù)據(jù)項(xiàng)組成,但共享同一存儲(chǔ)空間的構(gòu)造類型。,9.2共用體,9.2.1共用體與共用體類型的定義,共用體一種構(gòu)造類型數(shù)據(jù)共用體由若干不同類型的數(shù)據(jù)項(xiàng)組成,構(gòu)成共用體的各個(gè)數(shù)據(jù)項(xiàng)稱為共用體成員。,由于共享的特性,只有最新存儲(chǔ)的數(shù)據(jù)是有效的。,2020/4/25,60,union共用體名數(shù)據(jù)類型1成員名1;數(shù)據(jù)類型2成員名2;數(shù)據(jù)類型n成員名n;,9.2共用體,9.2.1共用體與共用體類型的定義,共用體類型定義的一般形式:,union為關(guān)鍵字;共用體名是用戶定義的類型標(biāo)識(shí)。中是組成該共用體的成員。成員的數(shù)據(jù)類型可以是C語(yǔ)言所允許的任何數(shù)據(jù)類型。,2020/4/25,61,例如:unionutypeinti;charch;longl;charc4;,9.2共用體,9.2.1共用體與共用體類型的定義,定義了一個(gè)unionutype共用體類型,共用體類型定義不分配內(nèi)存空間,只是說(shuō)明此類型數(shù)據(jù)的組成情況。,2020/4/25,62,9.2共用體,9.2.2共用體變量的定義與初始化,1.共用體變量的定義,利用已定義的共用體類型名定義變量union共用體名變量名表;例如:unionutypeu1,u2;,按照共用體類型的組成,系統(tǒng)為定義的共用體變量分配內(nèi)存單元。共用體變量所占內(nèi)存大小等于共用體中占用內(nèi)存的長(zhǎng)度最長(zhǎng)的成員。,2020/4/25,63,9.2共用體,9.2.2共用體變量的定義與初始化,1.共用體變量的定義,在定義共用體類型的同時(shí)定義變量,例如:unionutypeinti;charch;longl;charc4;a,b,c;,union共用體名成員定義表;變量名表;,2020/4/25,64,9.2共用體,9.2.2共用體變量的定義與初始化,1.共用體變量的定義,直接定義共用體類型變量,例如:unioninti;charch;longl;charc4;a,b,c;,union成員定義表;變量名表;,2020/4/25,65,9.2共用體,9.2.2共用體變量的定義與初始化,2.共用體變量的運(yùn)算,用sizeof運(yùn)算符計(jì)算共用體變量所占內(nèi)存空間,unionutypeinti;charch;longl;charc4;a,b,c;,sizeof(a)的結(jié)果為4sizeof(unionutype)的結(jié)果為4,2020/4/25,66,9.2共用體,9.2.2共用體變量的定義與初始化,2.共用體變量的運(yùn)算,同類型共用體變量之間的賦值運(yùn)算,共用體變量之間進(jìn)行賦值時(shí),系統(tǒng)僅賦當(dāng)前有效成員的值(即最新存儲(chǔ)的數(shù)據(jù))。,unionutypeinti;charch;longl;charc4;a,*p=,對(duì)共用體變量進(jìn)行取址運(yùn)算,2020/4/25,67,9.2共用體,9.2.2共用體變量的定義與初始化,3.共用體變量成員的引用,共用體變量成員的引用有三種形式。,例如:unionucharu1;intu2;x,*p=,用共用體變量名的引用形式:x.u1x.u2,用共用體指針變量的引用形式:(*p).u1(*p).u2p->u1p->u2,2020/4/25,68,9.2共用體,9.2.2共用體變量的定義與初始化,4.共用體變量賦初值,【例9.18】共用體變量賦初值。unionucharu1;intu2;main()unionua=0 x9741;printf("1.%c%xn",a.u1,a.u2);a.u1=a;printf("2.%c%xn",a.u1,a.u2);,共用體類型變量在定義時(shí)只能對(duì)第一個(gè)成員進(jìn)行賦初值。由于第一個(gè)成員是字符型,用一個(gè)字節(jié),所以對(duì)于初值0 x9741僅能接受0 x41,初值的高字節(jié)被截去。,1.A41,2.a61,2020/4/25,69,9.2共用體,9.2.2共用體變量的定義與初始化,main()unionlongn;intk;charc;un;un.n=0 x12345678;printf("%lxn",un.n);printf("%xn",un.k);printf("%xn",un.c);un.c=A;printf("%ldn",un.n);printf("%dn",un.k);printf("%cn",un.c);,12345678,5678,78,305419841,22081,A,2020/4/25,70,enum是關(guān)鍵字;枚舉名和枚舉常量是標(biāo)識(shí)符;枚舉常量之間用逗號(hào)分隔。,例如:enumweekdaySun,Mon,Tue,Wed,Thu,Fri,Sat;enumcolor1blue,green,red;enumflagfalse,true;,9.3枚舉類型與類型命名,9.3.1枚舉類型,1.枚舉類型的定義,枚舉類型定義的一般形式:enum枚舉名枚舉常量取值表;,枚舉是一個(gè)具有有限個(gè)整型符號(hào)常量的集合,這些整型符號(hào)常量稱為枚舉常量。每個(gè)枚舉類型都必須進(jìn)行類型的定義,定義時(shí)必須將其所有的枚舉常量一一列舉,以便限定此枚舉類型變量的取值范圍。,2020/4/25,71,在枚舉類型中,每個(gè)枚舉常量都代表一個(gè)整型值。在定義枚舉類型的同時(shí)可隱式或顯式地定義枚舉常量所代表的值。,例如:enumweekdaySun,Mon,Tue,Wed,Thu,Fri,Sat;,9.3枚舉類型與類型命名,9.3.1枚舉類型,2.枚舉常量的整型值,隱式定義:按照類型定義時(shí)枚舉常量列舉的順序分別代表0、1、2、等整型值。,0,1,2,3,4,5,6,2020/4/25,72,例如:enumopplus=43,minus=45,multiply=42,divide=47;enumworkdayMon=1,Tue,Wed,Thu,Fri;,9.3枚舉類型與類型命名,9.3.1枚舉類型,2.枚舉常量的整型值,顯式定義:在定義類型的同時(shí)指定枚舉常量的值,其中如有未指定值的枚舉常量,則根據(jù)前面的枚舉常量的值依次遞增1。,2,3,4,5,2020/4/25,73,例如:enumflagfg;enumcolor1c1;enumcolor2blank,brown,yellow,whitec2;enumlightblue,lightgreen,lightredc3;,9.3枚舉類型與類型命名,9.3.1枚舉類型,3.枚舉變量的定義,枚舉類型變量定義的三種形式:enum枚舉名枚舉變量名表;enum枚舉名枚舉常量取值表枚舉變量表;enum枚舉常量取值表枚舉變量表;,2020/4/25,74,賦值運(yùn)算fg=true;c1=red;c2=yellow;c3=lightblue;c3=white;,9.3枚舉類型與類型命名,9.3.1枚舉類型,4.枚舉數(shù)據(jù)的運(yùn)算,用sizeof運(yùn)算符計(jì)算枚舉變量所占內(nèi)存空間,枚舉變量中存放的是整型值,每個(gè)枚舉變量占用2個(gè)字節(jié),是enumcolor2類型的枚舉值,2020/4/25,75,取址運(yùn)算enumcolor2blank,brown,yellow,whitec2;enumflagfg;printf("%d",fg);,2020/4/25,77,switch(fg)casefalse:printf("false");break;casetrue:printf("true");,9.3枚舉類型與類型命名,9.3.1枚舉類型,5.枚舉數(shù)據(jù)的輸入輸出,枚舉變量的輸出,方法二:利用多分支選擇語(yǔ)句輸出枚舉常量對(duì)應(yīng)的字符串。,2020/4/25,78,enumflagfalse,truefg;char*name="false","true"fg=true;printf("%s",namefg);,9.3枚舉類型與類型命名,9.3.1枚舉類型,5.枚舉數(shù)據(jù)的輸入輸出,枚舉變量的輸出,方法三:依據(jù)枚舉值,運(yùn)用指針?lè)椒ㄝ敵鰧?duì)應(yīng)的字符串。,2020/4/25,79,fg=true;printf("%s",fg);,9.3枚舉類型與類型命名,9.3.1枚舉類型,5.枚舉數(shù)據(jù)的輸入輸出,枚舉變量的輸出,枚舉常量是標(biāo)識(shí)符,不是字符串,以輸出字符串方式輸出枚舉常量是錯(cuò)誤的。,2020/4/25,80,9.3枚舉類型與類型命名,9.3.1枚舉類型,【例9.20】編制一個(gè)程序。當(dāng)輸入今天的星期序號(hào)后,輸出明天是星期幾。enumweekdayMon=1,Tue,Wed,Thu,Fri,Sat,Sun;char*name8="error","Mon","Tue","Wed","Thu","Fri","Sat","Sun",2020/4/25,81,9.3枚舉類型與類型命名,9.3.1枚舉類型,main()enumweekdayd;printf("Inputtodaysnumeral(1-7):");scanf("%d",2020/4/25,82,9.3枚舉類型與類型命名,9.3.2類型的重新命名,1.為類型名定義別名,為類型名定義別名的一般形式:typedef類型名新類型名或typedef類型定義新類型名,用typedef為已存在的類型名再命名一個(gè)新的類型名(即別名)。,typedef是關(guān)鍵字;類型名可以是基本類型、構(gòu)造類型、指針類型或自定義類型名;新類型名是自定義的類型名。,2020/4/25,83,9.3枚舉類型與類型命名,9.3.2類型的重新命名,typedefintCOUNTER;/*定義COUNTER為整型類型名*/typedefstructdateintyear;intmonth;intday;DATE;/*定義DATE為structdate結(jié)構(gòu)體類型名*/,新類型名與舊類型名作用相同,并且可同時(shí)使用。,inti;與COUNTERi;等價(jià)。structdatebirthday;與DATEbirthday;等價(jià)。,2020/4/25,84,9.3枚舉類型與類型命名,9.3.2類型的重新命名,2.為類型命名的方法,為基本類型命名例如:typedeffloatREAL;REALx,y;/*相當(dāng)于floatx,y;*/,以typedef開(kāi)頭,加上變量定義的形式,并用新類型名替代變量名。,為數(shù)組類型命名例如:typedefcharCHARR80;CHARRc,d4;/*相當(dāng)于charc80,d480;*/,2020/4/25,85,9.3枚舉類型與類型命名,9.3.2類型的重新命名,2.為類型命名的方法,為指針類型命名例如:typedefint*IPOINT;IPOINTip;/*相當(dāng)于int*ip;*/IPOINT*pp;/*相當(dāng)于int*pp;*/,typedefint(*FUNpoint)();FUNpointfunp;/*相當(dāng)于int(*funp)();*/,2020/4/25,86,9.3枚舉類型與類型命名,9.3.2類型的重新命名,2.為類型命名的方法,為結(jié)構(gòu)體、共用體類型命名例如:structnodecharc;structnode*next;typedefstructnodeCHNODE;CHNODE*p;/*相當(dāng)于structnode*p;*/,structCHNODE*p;,