第十二章結構體與共用體_第1頁
第十二章結構體與共用體_第2頁
第十二章結構體與共用體_第3頁
第十二章結構體與共用體_第4頁
第十二章結構體與共用體_第5頁
已閱讀5頁,還剩62頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

C語言程序設計第十二章結構體與共用體1學習內(nèi)容結構體(結構structure)、共用體(聯(lián)合union)類型的定義結構體變量、結構體數(shù)組與指針向函數(shù)傳遞結構體變量、結構體數(shù)組、結構體指針動態(tài)數(shù)據(jù)結構、動態(tài)鏈表12-2從基本數(shù)據(jù)類型到抽象數(shù)據(jù)類型12-3二進制數(shù)——類型本不存在內(nèi)存里存的內(nèi)容,你認為它是什么,它就是什么在早期的機器指令及匯編語言中,數(shù)據(jù)對象均用二進制數(shù)表示,沒有類型的概念一般的CPU只支持兩種類型整數(shù)、浮點數(shù)4在高級語言引入了基本數(shù)據(jù)類型整型、浮點型、字符型等不同語言會定義不同的基本類型基本數(shù)據(jù)類型并不能方便地解決所有問題有些語言(如PL/1)中試圖規(guī)定較多的類型,如數(shù)組、樹、棧等,但實踐證明不是個好辦法從基本數(shù)據(jù)類型到抽象數(shù)據(jù)類型5用戶自己構造數(shù)據(jù)類型——復合數(shù)據(jù)類型由基本數(shù)據(jù)類型迭代派生而來,表示復雜的數(shù)據(jù)對象典型的代表就是“結構體”抽象數(shù)據(jù)類型(AbstractDataType,ADT)在復合數(shù)據(jù)類型基礎上增加了對數(shù)據(jù)的操作抽象數(shù)據(jù)類型進而進化為“類(Class)”這是一個跨時代的進步Class是Object-Oriented的一個重要概念從基本數(shù)據(jù)類型到抽象數(shù)據(jù)類型思考一個問題在程序里表示一個人(姓名、年齡、性別、……),怎么表示?想表示多個人呢?如何用計算機程序實現(xiàn)下述表格的管理?表12-1某學校學生成績管理表學號姓名性別入學時間計算機原理英語數(shù)學音樂1令狐沖男1999908372822林平之男1999789288783岳靈珊女1999897298664任瑩瑩女1999789587905……6……12-6int studentId[30];/*每個學生的學號*/char studentName[30][10];/*每個學生的姓名*/char studentSex[30][2];/*每個學生的性別*/int

timeOfEnter[30];/*入學時間用int表示*/int scoreComputer[30];/*計算機原理課的成績*/int scoreEnglish[30];/*英語課的成績*/

int scoreMath[30]; /*數(shù)學課的成績*/int scoreMusic[30]; /*音樂課的成績*/數(shù)組解決方法(1)12-7數(shù)組解決方法(2)intstudentId[30]={1,2,3,4,5,6};charstudentName[30][10]={{"令狐沖"},{"林平之"},{"岳靈珊"},{"任瑩瑩"}};charstudentSex[30][2]={{"男"},{"男"},{"女"},{"女"}};inttimeOfEnter[30]={1999,1999,1999,1999};intscoreComputer[30]={90,78,89,78};intscoreEnglish[30]={83,92,72,95};intscoreMath[30]={72,88,98,87};intscoreMusic[30]={82,78,66,90};12-8數(shù)組解決方法(3)數(shù)據(jù)的內(nèi)存管理方式90788978……83927295……72889887……82786690……1234……令狐沖林平之岳靈珊任瑩瑩……男男女女……1999199919991999……12-9分配內(nèi)存不集中,尋址效率不高對數(shù)組進行賦初值時,容易發(fā)生錯位結構顯得比較零散,不容易管理希望的內(nèi)存分配圖1令狐沖男1999908372822林平之男1999789288783岳靈珊女1999897298664任瑩瑩女199978958790

問題提出12-10結構體的解決方法structSTUDENT

{

intnumber;/*每個學生的學號*/

charname[10];/*每個學生的姓名*/

charsex[4];/*每個學生的性別*/

intenter;/*每個學生的入學時間*/

int computer;/*每個學生的計算機原理成績*/

int english;/*每個學生的英語成績*/

int math; /*每個學生的數(shù)學成績*/

int music;/*每個學生的音樂成績*/

};struct

STUDENTstudent;/*定義結構體變量*/struct

STUDENTstudents[4];/*定義結構體數(shù)組*/12-11是一個類型structstudent{

intnum;

charname[20];

charsex;

intage;

floatscore;

charaddr[30];};結構體定義struct

結構體名{

類型關鍵字

成員名1;

類型關鍵字成員名2;…...

類型關鍵字成員名n;};結構體的定義只定義了數(shù)據(jù)的形式,即聲明了一種復雜的數(shù)據(jù)類型,并未生成任何變量。numnamesexagescoreaddr結構體定義形成一個樣板,用于生成結構體變量結構體的定義結構體12-12先定義結構體類型再定義變量名在定義類型的同時定義變量直接定義結構體變量(不出現(xiàn)結構體名)struct

studentstudent1,student2;struct

student{intnum;charname[20];

charsex;

intage;floatscore;charaddr[30];}student1,student2;struct{intnum;charname[20];

charsex;

intage;floatscore;

charaddr[30];}student1,student2;結構體變量的定義(1)

結構體12-13用typedef為已存在的類型定義新名字結構體變量的定義(2)struct

student{

intnum;

charname[20];

charsex;

intage;

floatscore;

charaddr[30];};typedef

struct

student

STUD;STUDstudent1,student2;用STUD代替struct

student類型12-14結構體定義可以嵌套結構體變量的定義(3)學號姓名性別年齡出生年月住址年月日struct

student{

intnum;

charname[20];

charsex;

intage;struct

data

birthday;

charaddr[30];}student1,student2;struct

date{

intyear;

intmonth;

intday;};typedefstruct

dateDATE;DATEbirthday;12-15等價于12.2.4結構體變量的初始化等價于注意!12-16訪問結構體變量的成員必須使用成員選擇運算符(也稱圓點運算符)12.2.6結構體變量的引用當出現(xiàn)結構體嵌套時,必須以級聯(lián)方式訪問結構體成員12-17STUDENTstu1;【例12.1】演示結構體變量的賦值和引用方法12.2.6結構體變量的引用按結構體的成員順序逐一對相應成員進行賦值格式符%02d中2d前面的前導符0表示輸出數(shù)據(jù)時,若左邊有多余位,則補012-18【例12.1】若要從鍵盤輸入結構體變量stu1的內(nèi)容,那么程序如何修改?兩個地址有何不同?12-19【例12.1】若要從鍵盤輸入結構體變量stu1的內(nèi)容,那么程序如何修改?結構體成員的地址與該成員在結構體中所處的位置及其所占內(nèi)存的字節(jié)數(shù)相關結構體變量的地址&stu2是該變量所占內(nèi)存空間的首地址12-2012.2.7結構體所占內(nèi)存的字節(jié)數(shù)struct類型用內(nèi)存字節(jié)數(shù)=?是所有成員變量的內(nèi)存總和嗎?printf("%d\n",sizeof(struct

sample));用運算符sizeof獲得結構體大小sizeof(變量或表達式)sizeof(類型)12Why?printf("%d\n",sizeof(SAMPLE));【例12.2】12-212212.2.7結構體所占內(nèi)存的字節(jié)數(shù)事實上,所有數(shù)據(jù)類型在內(nèi)存中都是從偶數(shù)地址開始存放的且結構所占的實際空間一般是按照機器字長對齊的不同的編譯器、平臺,對齊方式會有變化結構體變量的成員的存儲對齊規(guī)則是與機器相關的具有特定數(shù)據(jù)類型的數(shù)據(jù)項大小也是與機器相關的所以一個結構體在內(nèi)存中的存儲格式也是與機器相關的非所有成員變量的內(nèi)存總和12個字節(jié)chfchchchfnumnamesexagebirthdayaddrmonthdayyear結構體成員的初始化student1.birthday.year=2007struct

student{

intnum;

charname[20];

charsex;

intage;struct

data

birthday;

charaddr[30];}student1,student2;struct

date{

intyear;

intmonth;

intday;};12-23結構體變量的引用和初始化注意不能將一個結構體變量作為一個整體輸入/輸出,只能對每個具體的成員進行輸入/輸出。例:假設聲明structSTUDENTstudent1,student2;printf("%d%s%d",student1);具有相同結構體類型的變量可以整體賦值student1=student212-2412.3結構體數(shù)組的定義和初始化建立了數(shù)據(jù)庫中的多條記錄,每條對應一個學生信息12-25【例12.3】利用結構體數(shù)組計算每個學生的平均分12-2612.4結構體指針的定義和初始化ptstu1

STUDENT

stu1;

STUDENT

*pt;pt=&stu1;成員1成員2成員3成員4成員5如何定義指向結構體變量的指針?STUDENT

*pt=&stu1;等價于12-2712.4結構體指針的定義和初始化如何訪問結構體指針變量所指向的結構體成員呢?STUDENT

stu1;

STUDENT

*pt=&stu1;ptstu1成員1成員2成員3成員4成員5通過stu1和成員選擇運算符訪問結構體成員stu1.studentID=1;通過pt和指向運算符訪問結構體成員(*pt).studentID=1;

pt->studentID=1;12-2812.4結構體指針的定義和初始化ptstu1成員1成員2成員3成員4成員5當結構體嵌套時,如何訪問結構體指針變量所指向的結構體成員?stu1.

birthday.

year=1999;(*pt).

birthday.

year=1999;pt->

birthday.

year=1999;STUDENT

stu1;

STUDENT

*pt=&stu1;12-2912.4結構體指針的定義和初始化

STUDENT

stu[30];

STUDENT

*pt;pt=stu;

如何定義指向結構體數(shù)組的指針?STUDENT

*pt=stu;等價于STUDENT

*pt=&stu[0];等價于ptstu[30]stu[0]stu[1]stu[2]stu[3]stu[4]stu[5]......stu[29]12-30使用pt++,使pt指向stu[1]pt->studentID等價于

stu[1].studentIDpt12.4結構體指針的定義和初始化

STUDENT

stu[30];

STUDENT

*pt=stu;

如何訪問結構體數(shù)組指針指向的結構體成員?stu[30]stu[0]stu[1]stu[2]stu[3]stu[4]stu[5]......stu[29]12-3112.5向函數(shù)傳遞結構體向函數(shù)傳遞結構體的單個成員復制單個成員的內(nèi)容函數(shù)內(nèi)對結構內(nèi)容的修改不影響原結構向函數(shù)傳遞結構體的完整結構向函數(shù)傳遞結構體的首地址12-32structdate{

intyear;

intmonth;

intday;};voidfunc(structdate

p){

p.year=2000;

p.month=5;

p.day=22;}Beforefunctioncall:1999/04/23Afterfunctioncall:1999/04/23結構體變量

作函數(shù)參數(shù)【例12.4】12-33structdate{

intyear;

intmonth;

intday;};voidfunc(structdate

*p){

p->year=2000;

p->month=5;

p->day=22;}Beforefunctioncall:1999/04/23Afterfunctioncall:2000/05/22結構體指針

作函數(shù)參數(shù)指針作函數(shù)形參實參必須為地址值【例12.5】12-34structdate{

intyear;

intmonth;

intday;};structdatefunc(structdate

p){

p.year=2000;

p.month=5;

p.day=22;

returnp;}Beforefunctioncall:1999/04/23Afterfunctioncall:2000/05/22結構體變量

作函數(shù)返回值【例12.6】12-3512.5向函數(shù)傳遞結構體向函數(shù)傳遞結構體的完整結構復制整個結構體成員的內(nèi)容,多個值函數(shù)內(nèi)對結構內(nèi)容的修改不影響原結構內(nèi)容傳遞更直觀,但開銷大向函數(shù)傳遞結構體的首地址用結構體數(shù)組/結構體指針作函數(shù)參數(shù)僅復制結構體的首地址,一個值修改結構體指針所指向的結構體的內(nèi)容指針傳遞效率高12-3612.5向函數(shù)傳遞結構體#include<stdio.h>#defineN30typedefstructdate{intyear;intmonth;intday;}DATE;typedefstructstudent{longID;charName[80];charSex;DATEbirthday;floatscore[3];}STUDENT;voidInputScore(STUDENTstu[],intn,intm);voidAverScore(STUDENTstu[],floataver[],intn,intm);voidPrintScore(STUDENTstu[],floataver[],intn,intm);【例12.7】修改例12.3程序,用結構體數(shù)組作函數(shù)參數(shù)編程并輸出計算學生的平均分12-371.結構體數(shù)組做函數(shù)參數(shù)12-38intmain(){floataver[N];STUDENTstu[N];intn;printf("Howmanystudent?");scanf("%d",&n);InputScore(stu,n,3);AverScore(stu,aver,n,3);PrintScore(stu,aver,n,3);return0;}【例12.7】修改例12.3程序,用結構體數(shù)組作函數(shù)參數(shù)編程并輸出計算學生的平均分12.5向函數(shù)傳遞結構體函數(shù)1:數(shù)據(jù)讀取函數(shù)2:計算平均分函數(shù)3:打印輸出12-39voidInputScore(STUDENTstu[],intn,intm){inti,j;for(i=0;i<n;i++){scanf("%ld%s%c",&stu[i].ID,stu[i].Name,&stu[i].Sex);scanf("%d%d%d",&stu[i].birthday.year,&stu[i].birthday.month,&stu[i].birthday.day);for(j=0;j<m;j++) scanf("%f",&stu[i].score[j]);}}【例12.7】修改例12.3程序,用結構體數(shù)組作函數(shù)參數(shù)編程并輸出計算學生的平均分12.5向函數(shù)傳遞結構體函數(shù)1:數(shù)據(jù)讀取12-40voidAverScore(STUDENTstu[],floataver[],intn,intm){floatsum;inti,j;for(i=0;i<n;i++){sum=0;for(j=0;j<m;j++)sum=sum+stu[i].score[j];aver[i]=(float)sum/m;}}【例12.7】修改例12.3程序,用結構體數(shù)組作函數(shù)參數(shù)編程并輸出計算學生的平均分12.5向函數(shù)傳遞結構體函數(shù)2:計算平均分12-41voidPrintScore(STUDENTstu[],floataver[],intn,intm){inti,j;for(i=0;i<n;i++){printf("%ld\t%s\t%c\t",stu[i].ID,stu[i].Name,stu[i].Sex);printf("%d/%d/%d/",stu[i].birthday.year,stu[i].birthday.month,stu[i].birthday.day);for(j=0;j<m;j++)printf("\t%f",stu[i].score[j]);printf("\t%f\n",aver[i]);}}

【例12.7】修改例12.3程序,用結構體數(shù)組作函數(shù)參數(shù)編程并輸出計算學生的平均分12.5向函數(shù)傳遞結構體函數(shù)3:打印輸出12.5向函數(shù)傳遞結構體#include<stdio.h>#defineN30typedefstructdate{intyear;intmonth;intday;}DATE;typedefstructstudent{longID;charName[80];charSex;DATEbirthday;floatscore[3];}STUDENT;voidInputScore(STUDENTstu[],intn,intm);voidAverScore(STUDENTstu[],floataver[],intn,intm);voidPrintScore(STUDENTstu[],floataver[],intn,intm);【例12.7】修改例12.3程序,用結構體指針作函數(shù)參數(shù)編程并輸出計算學生的平均分voidInputScore(STUDENT*pstu,intn,intm);voidAverScore(STUDENT*pstu,float*paver,intn,intm);voidPrintScore(STUDENT*pstu,float*paver,intn,intm);12-422.結構體指針做函數(shù)參數(shù)12-43intmain(){intn;floataver[N];STUDENTstu[N];

printf("Howmanystudent?");scanf("%d",&n);InputScore(stu,n,3);AverScore(stu,aver,n,3);PrintScore(stu,aver,n,3);return0;}12.5向函數(shù)傳遞結構體函數(shù)1:數(shù)據(jù)讀取函數(shù)2:計算平均分函數(shù)3:打印輸出2.結構體指針做函數(shù)參數(shù)12-44voidInputScore(STUDENTstu[],intn,intm){inti,j;for(i=0;i<n;i++){scanf("%ld%s%c",&pstu1[i].ID,pstu1[i].Name,&pstu1[i].Sex);scanf("%d%d%d",&pstu1[i].birthday.year,&pstu1[i].birthday.month,&pstu1[i].birthday.day);for(j=0;j<m;j++) scanf("%f",&pstu1[i].score[j]);}}【例12.7】修改例12.3程序,用結構體指針作函數(shù)參數(shù)編程并輸出計算學生的平均分12.5向函數(shù)傳遞結構體函數(shù)1:數(shù)據(jù)讀取voidInputScore(STUDENT*pstu1,intn,intm)2.結構體指針做函數(shù)參數(shù)12-45voidAverScore(STUDENTstu[],floataver[],intn,intm){floatsum;inti,j;for(i=0;i<n;i++){sum=0;for(j=0;j<m;j++)sum=sum+pstu1[i].score[j];

paver1[i]=(float)sum/m;}}【例12.7】修改例12.3程序,用結構體指針作函數(shù)參數(shù)編程并輸出計算學生的平均分12.5向函數(shù)傳遞結構體函數(shù)2:計算平均分voidAverScore(STUDENT*pstu1,float*paver1,intn,intm)2.結構體指針做函數(shù)參數(shù)12-46voidPrintScore(STUDENTstu[],floataver[],intn,intm){inti,j;for(i=0;i<n;i++){printf("%ld\t%s\t%c\t",pstu1[i].ID,pstu1[i].Name,pstu1[i].Sex);printf("%d/%d/%d/",pstu1[i].birthday.year,pstu1[i].birthday.month,pstu1[i].birthday.day);for(j=0;j<m;j++)printf("\t%f",pstu1[i].score[j]);printf("\t%f\n",paver1[i]);}}

【例12.7】修改例12.3程序,用結構體指針作函數(shù)參數(shù)編程并輸出計算學生的平均分12.5向函數(shù)傳遞結構體函數(shù)3:打印輸出voidPrintScore(STUDENT*pstu1,float*paver1,intn,intm)2.結構體指針做函數(shù)參數(shù)12.5向函數(shù)傳遞結構體【例12.7】修改例12.3程序,主函數(shù)用可變長一維數(shù)組編程并輸出計算學生的平均分3.指針做實參12-47函數(shù)2:計算平均分函數(shù)3:打印輸出函數(shù)1:數(shù)據(jù)讀取12.5向函數(shù)傳遞結構體3.指針做實參12-48函數(shù)1:數(shù)據(jù)讀取12.5向函數(shù)傳遞結構體3.指針做實參12-49函數(shù)2:計算平均分12.5向函數(shù)傳遞結構體3.指針做實參12-50函數(shù)3:打印輸出12.5向函數(shù)傳遞結構體3.指針做實參12-51結構體(Struct)把關系緊密且邏輯相關的多種不同類型的變量,組織到統(tǒng)一的名字之下占用相鄰的一段內(nèi)存單元共用體,也稱聯(lián)合(Union)把情形互斥但邏輯相關的多種不同類型的變量,組織到統(tǒng)一的名字之下占用同一段內(nèi)存單元,每一時刻只有一個數(shù)據(jù)起作用12-52用戶自定義的數(shù)據(jù)類型12.6共用體structsample{

shorti;

charch;

floatf;};0x0037b00unionsample{

shorti;

charch;

floatf;};printf("%d\n",sizeof(structsample));8個字節(jié)ichf4個字節(jié)printf("%d\n",sizeof(unionsample));ichf【例12.8】12-5312.6共用體sizeof(unionnumber)取決于占空間最多的那個成員變量0x0037b00同一內(nèi)存單元在每一瞬時只能存放其中一種類型的成員起作用的成員是最后一次存放的成員,不能作為函數(shù)參數(shù)不能進行比較操作,只能對第一個成員初始化f4個字節(jié)12-5412-5512.6共用體12-5612.6共用體12.7.1枚舉數(shù)據(jù)類型枚舉(Enumeration)數(shù)據(jù)類型描述的是一組整型值的集合用于當某些量僅由有限個數(shù)據(jù)值組成時

enumweeks{SUN,MON,TUE,WED,THU,FRI,SAT};

enumweekstoday;enumresponse{no,yes,none};enumresponseanswer;

today=TUE;

answer=yes;

enumresponse{no=-1,yes=1,none=0};其值為2其值為112-5758下面的結構是什么意思?structtemp

{

int data;

structtemppt;

};CB下的錯誤提示:field'pt'hasincompletetypeVC下的錯誤提示:'pt'usesundefinedstruct'temp'下面的結構是什么意思呢?structtemp

{

intdata;

structtemp*pt;

};結構體聲明時不能包含本結構體類型成員,系統(tǒng)將無法為這樣的結構體類型分配內(nèi)存

可包含指向本結構體類型的指針變量問題的提出12.7.2動態(tài)數(shù)據(jù)結構——單向鏈表structLink{

intdata;

structLink*next;};datanextheaddatanextdatanextdataNULL鏈表(LinkedTable):線性表的鏈式存儲結構特點:用一組任意的存儲單元存儲線性表的數(shù)據(jù);存儲單元可以是連續(xù)的,也可是不連續(xù)的12-59鏈表的定義datanextheaddatanextdatanextdataNULL鏈表(Linkedtable):線性表的鏈式存儲結構為表示每個元素與后繼元素的邏輯關系,除存儲元素本身信息外,還要存儲其直接后繼信息兩部分信息組成一個節(jié)點structLink{

intdata;

structLink*next;};12-60頭節(jié)點中間節(jié)點中間節(jié)點末節(jié)點datanextheaddatanextdatanextdataNULL數(shù)據(jù)域:存儲數(shù)據(jù)元素信息(不局限一個成員數(shù)據(jù))指針域:存儲直接后繼的節(jié)點信息鏈表(LinkedTable):線性表的鏈式存儲結構為表示每個元素與后繼元素的邏輯關系,除存儲元素本身信息外,還要存儲其直接后繼信息structLink{

intdata;

structLink*next;};n個節(jié)點鏈接成一個鏈表(因為只包含一個指針域,故又稱線性鏈表或單向鏈表)12-

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論