第10章 結構體(最終講稿)_第1頁
第10章 結構體(最終講稿)_第2頁
第10章 結構體(最終講稿)_第3頁
第10章 結構體(最終講稿)_第4頁
第10章 結構體(最終講稿)_第5頁
已閱讀5頁,還剩36頁未讀, 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

結構體、共用體及枚舉類型第

10

章10.1結構體類型和結構體變量10.2結構體數組10.3結構體指針10.4用指針處理鏈表

10.5共用體類型

10.6枚舉類型

10.7用typedef命名類型本章小結結構體類型和結構體變量10.1教學進程10.1.1結構體類型的定義有時需要將不同類型的數據組合成一個有機的整體,以便于引用。如:一個學生有學號、姓名、性別、年齡、成績、地址等屬性

intnum;charname[20];charsex;

intage;floatscore;

intcharaddr[30];問題定義:100101

LiFun

M1887.5Beijing

Numnamesexagescoreaddr應當把它們組織成一個組合項,在一個組合項中包含若干個類型不同(當然也可以相同)的數據項。教學進程結構體類型struct

結構體名{類型標識符成員名表1;類型標識符成員名表2;

…;類型標識符成員名表n;};定義一個結構體類型的一般形式為:其中struct是用于定義具體結構體類型的關鍵字,與結構體名共同組成結構體類型名。在“成員表列”中可以定義該類型中有哪些成員,各成員屬于什么數據類型,由它們組成結構體。教學進程結構體類型structstudent{intnum;charname[20];charsex;

intage;floatscore;charaddr[30];};結構體類型名成員類型名成員名例如:structstudent{intnum;charname[20];charsex;

intage;floatscore;charaddr[30];};structdate{intmonth;

intday;

intyear;}structstudent{intnum;charneme[20],sex;

intage;

structdatebirthday;charaddr[30];}student1,student2;已定義的結構體類型可以像基類型一樣使用。教學進程結構體類型的定義可以嵌套在這個定義中,結構體“日期”類型date中又嵌套定義了結構體“時間”類型time。這就是結構體的嵌套定義。定義一個結構體“日期”類型date:

structdate{intyear; /*年*/

intmonth; /*月*/

intday; /*日*/

structtime/*結構體“時間”類型*/{inthour; /*小時*/

intminute; /*分*/

intsecond; /*秒*/}t;

};結構體類型(2)當一個結構體類型定義在函數之外時,它具有全局作用域;若定義在任一對花括號之內,則具有局部作用域,其作用范圍是所在花括號構成的塊。(3)結構體是一種復雜的數據類型,是數目固定、類型不同的若干成員的集合,結構體類型的定義只是列出了該結構的組成情況,編譯系統并未因此而分配存儲空間,當定義了結構體類型的變量或數組后,編譯系統才會分配存儲空間。(4)成員名可以與程序中的變量名相同,二者不代表同一個對象。例如,程序中可以定義一個變量num,它與struct

stu中的num是兩回事,互不干擾。(5)如果兩個結構體的成員類型、名稱、個數相同,但結構體名不同,也是兩個不同的結構類型。結構體類型教學進程要強調的是,結構體類型名(如上例中的date)是定義的類型名,而不是變量名,就好像整型的類型名為int,雙精度實型的類型名為double,字符型的類型名為char一樣,只不過整型、雙精度實型、字符型等基本數據類型是C編譯系統已經定義的,用戶可以直接用它們來定義相應類型的變量,而結構體類型是用戶根據數據處理的需要臨時定義的一種類型,一經定義就可以像系統定義的類型一樣使用了。但系統并不為類型分配存儲空間,為了能在程序中使用結構體類型的數據,必須定義結構體類型的變量。定義結構體類型的變量教學進程結構體類型和結構體變量結構體變量的定義可以采取以下3種方法定義結構體變量:(1)先定義結構體類型,再定義結構體變量例如:structstudent

student1,student2;↑↑↑

結構體類型名結構體變量名定義了student1和student2為structstudent類型(應事先已定義)的變量,即它們具有structstudent類型的結構。student1100101ZhangXinM1990.5Shanghai100102WangLiF2098Beijingstudent2在TC中占字節(jié)數2201243059定義結構體類型變量教學進程●一般形式為:

struct結構體名{成員表列}變量名表列;(2)在定義結構體類型的同時定義結構體變量例如:structstudent{intnum;

charname[20];

charsex;

intage;

floatscore;

charaddr[30];}student1,student2;它的作用與第一種方法相同,即定義了兩個structstudent類型的變量student1,student2。如果需要,在程序中還可以定義該種結構體類型的其它變量。結構體類型變量的定義教學進程(3)不指定類型名而直接定義結構體變量●

struct

{成員表}變量表;例如:

struct

{intnum;

charname[10];

charsex;

intage;

floatscore;

}studernt1,

student2;指定了一個無名的結構體類型,它沒有名字,顯然不能再以此結構體類型去定義其它變量了。未出現結構體名結構體類型變量的定義教學進程注意(1)結構體類型與結構體變量是不同的概念,不能混同。(2)結構體類型中的成員名可以與程序中的變量名相同,但二者不代表同一對象。(3)對結構體變量中的成員,可以單獨使用,它的作用與地位相當于普通變量。教學進程結構體變量中的每個成員與普通變量一樣,可進行各種運算。

st.num=115;

[0]=‘z';

[1]='a';

[2]='\0';

st.sex='M';

st.age=19;

st.score=95.0;

scanf("%d",&st.num);

printf("%s",);方式●結構體變量名.成員名其中“.”為結構體成員運算符,它的優(yōu)先級最高。結構體變量的引用和初始化結構體變量的引用在定義結構體變量后,就可以引用其成員。引用結構體類型變量教學進程(1)同類的結構體變量可以互相賦值如:student1=student2;

但不能將一個結構體變量作為一個整體進行輸入和輸出。如:已定義student1和student2為結構體變量并已有值,

printf(″%d,%s,%c,%d,%f,%\n″,student1);(2)如果成員本身又屬一個結構體類型,則要用若干個成員運算符,一級一級地找到最低一級的成員,進行賦值或存取及運算。

如:訪問上面定義的結構體變量student1的各成員

student1.numstudent1.birthday.month定義了結構體變量后,便可以引用這個變量。但應遵守以下規(guī)則:引用結構體類型變量教學進程(3)對結構體變量的成員可以像普通變量一樣進行各種運算(根據其類型決定可以進行的運算)。

如:student2.score=student1.score;sum=student1.score+student2.score;student1.age++;++student2.age;(4)可引用結構體變量成員的地址,也可引用結構體變量的地址。

如:scanf(″%d″,&student1.num);//為成員student1.num賦值

printf(″%o″,&student1);//輸出變量student1的首地址

但不能用以下語句整體讀入結構體變量如:

scanf(″%d,%s,%c,%d,%f,%s″,&student1);

結構體變量的地址主要用作函數參數,傳遞結構體變量的地址。教學進程與普通變量一樣,在定義結構體類型變量的同時也可以對結構體類型變量賦初值。結構體變量的引用和初始化結構體變量的初始化例10-1對結構變量初始化。#include<stdio.h>main(){struct

stu

{intnum;charname[20];charsex;

intage;floatscore;}boy2,boy1={102,"Zhangping",'M',20,78.5};boy2=boy1;printf("Number:%d\nName:%s\n",boy2.num,);printf("Sex:%c\nage:%dScore:%4.1f\n",boy2.sex,boy2.age,boy2.score);}

本例中,對結構體變量boy1作了初始化賦值,然后把boy1的值整體賦予boy2,最后用printf函數輸出boy2各成員的值。程序運行結果如下:Number:102Name:ZhangpingSex:MAge:20Score:78.5結構體數組10.310.3.1定義結構體數組教學進程與整型數組、實型數組、字符型數組一樣,在程序中也可以定義結構體類型的數組,并且同一個結構體數組中的元素應為同一種結構體類型。與定義結構體變量的方法相似,只需說明其為數組即可。如:structstudent{intnum;charname[20];charsex;intage;floatscore;charaddr[30];

};structstudentstu[3];}stu[3];/*直接定義結構體數組*/定義了一個數組stu,數組有3個元素,均為structstudent類型數據。結構體數組10.310.3.2結構體數組的初始化教學進程與其它類型的數組一樣,對結構體數組可以初始化。如:

structstudent{int

num;charname[20];charsex;

intage;floatscore;charaddr[30];

}stu[3]={{10101,″LiLin″,′M′,18,87.5,″103BeijingRoad″},{10102,″ZhangFun″,′M′,19,99,″130ShanghaiRoad″},{10104,″WangMin″,′F′,20,78.5,″1010ZhongshanRoad″}};圖9-4定義結構體數組教學進程數組各元素在內存中連續(xù)存放,如圖所示。一個結構體數組的元素相當于一個結構體變量,引用結構體數組元素的一般形式為:數組名[下標].成員名10.3.3結構體數組的引用教學進程【例10.2】計算學生的平均成績和不及格的人數。#include<stdio.h>struct

stu{intnum;charname[20];charsex;floatscore;}boy[5]={{101,"Liping",'M',45},{102,"Zhangping",'M',62.5},{103,"Hefang",'F',92.5},{104,"Chengling",'F',87},{105,"Wangming",'M',58}};main(){int

i,c=0;floatave,s=0;

for(i=0;i<5;i++){s+=boy[i].score;

if(boy[i].score<60)c+=1;}

ave=s/5;

printf("average=%f\ncount=%d\n",ave,c);}

本例程序中定義了一個結構體數組boy,共5個元素,并作了初始化賦值。在main函數中用for語句逐個累加各元素的score成員值存于s之中,如果score的值小于60(不及格),那么計數器c加1,循環(huán)完畢后輸出全班平均分及不及格人數。程序運行結果如下:average=69.000000count=2結構體指針10.410.4.1指向結構體變量的指針變量教學進程結構體類型的指針變量指向結構體變量或數組(或數組元素)的起始地址。

structstudent{intnum;

charname[10];

charsex;

intage;

floatscore;

};

structstudentst1,st2,

st[10],*p;例如令p=&st1,st1.num(*p).nump->num令p=st,

st[0].num(*p).nump->num指向結構體變量的指針變量教學進程當結構體類型的指針變量p指向一個結構體類型變量后,下列三種表示是等價的:結構體變量名.成員

(*p).成員

p->成員必須注意,當p定義為指向結構體類型的變量后,它不能指向某一成員。例如,p=&st1.num;是錯誤的,因為它企圖讓結構體指針變量指向結構體變量st1中的成員num。10.4.2指向結構體數組的指針教學進程

#include<stdio.h>structstudent{intnum;charname[20];charsex;

intage;};【例10.4】

指向結構體數組元素的指針的應用。structstudentstu[3]={{10101,"LiLin",'M',18},{10102,"ZhangFun",'M',19},{10104,"WangMin",'F',20}};voidmain(){structstudent*p;

printf("No.Namesexage\n");

for(p=stu;p<stu+3;p++)printf("%5d%-20s%2c%4d\n",p->num,p->name,p->sex,p->age);}結構體指針10.4指向結構體數組的指針教學進程程序分析:p是指向structstudent結構體類型數據的指針變量。在for語句中先使p的初值為stu,也就是數組stu第一個元素的起始地址。在第一次循環(huán)中輸出stu[0]的各個成員值。然后執(zhí)行p++,使p自加1。p加1意味著p所增加的值為結構體數組stu的一個元素所占的字節(jié)數。執(zhí)行p++后p的值等于stu

+1,p指向stu[1]。在第二次循環(huán)中輸出stu[1]的各成員值。在執(zhí)行p++后,p的值等于stu+2,再輸出stu[2]的各成員值。在執(zhí)行p++后,p的值變?yōu)閟tu+3,已不再小于stu+3了,不再執(zhí)行循環(huán)。圖9-8教學進程注意:(1)

如果p的初值為stu,即指向第一個元素,則p加1后p就指向下一個元素。例如:

(++p)->num先使p自加1,然后得到它指向的元素中的num成員值(即10102)。

(p++)->num先得到p->num的值(即10101),然后使p自加1,指向stu[1]。(2)

程序已定義了p是一個指向structstudent類型數據的指針變量,它用來指向一個structstudent類型的數據,不應用來指向stu數組元素中的某一成員。指向結構體數組的指針用指針處理鏈表10.710.7.1鏈表概述1.鏈表的一般結構存儲節(jié)點數據域 存放數據元素指針域 存放下一個結點元素的地址鏈表是一種常見的重要的數據結構,是動態(tài)地進行存儲分配的一種結構。鏈表的組成:頭指針:存放一個地址,該地址指向一個元素

結點:用戶需要的實際數據和鏈接節(jié)點的指針鏈表是一種常見的重要的數據結構,是動態(tài)地進行存儲分配的一種結構。鏈表的組成:頭指針:存放一個地址,該地址指向一個元素

結點:用戶需要的實際數據和鏈接節(jié)點的指針鏈表是一種常見的重要的數據結構,是動態(tài)地進行存儲分配的一種結構。鏈表的組成:頭指針:存放一個地址,該地址指向一個元素

結點:用戶需要的實際數據和鏈接節(jié)點的指針教學進程教學進程鏈表的概述2.結點結構體類型的定義

struct

結構體名

{數據成員表;

struct

結構體名*指針變量名;

};鏈表結點結構的一般形式:其函數原型為void*malloc(unsigned

intsize);又如:float*pc;pc=(float*)malloc(5*sizeof(float));3.結點的動態(tài)分配

malloc(存儲區(qū)字節(jié)數)

該函數返回存儲區(qū)的首地址。形式是:釋放存儲區(qū)用如下函數:free(p);它表示釋放由p指向的存儲空間。教學進程教學進程結點的動態(tài)分配用結構體建立鏈表:

structstudent{intnum;

floatscore;

structstudent*next;};

其中成員num和score用來存放結點中的有用數據(用戶需要用到的數據),next是指針類型的成員,它指向structstudent類型數據(這就是next所在的結構體類型)教學進程教學進程#include<stdio.h>structstudent{longnum;floatscore;

structstudent*next;};voidmain(){structstudenta,b,c,*head,*p;

a.num=99101;a.score=89.5;

b.num=99103;b.score=90;c.num=99107;c.score=85;用指針處理鏈表10.710.7.2建立簡單的靜態(tài)鏈表【例10.7】建立上圖所示的簡單鏈表,它由個學生數據的節(jié)點組成。輸出個節(jié)點中的數據。head=&a;

a.next=&b;

b.next=&c;

c.next=NULL;p=head;do{printf("%ld%5.1f\n“,p->num,p->score);p=p->next; }while(p!=NULL);}教學進程教學進程建立鏈表指從無到有建立一個鏈表,即一個一個地開辟結點和輸入各結點數據,并建立前后相鏈的關系,其算法如下:①讀取數據;②生成新結點;③將數據存入新結點;④將新結點插入到鏈表中。重復上述步驟,直到輸入結束。可以根據需要將新結點插入到鏈表不同位置,如鏈表頭、鏈表中間、鏈表尾等,例10-10將新結點插入到鏈表尾部。10.7.3創(chuàng)建動態(tài)鏈表

【例10.7】從鍵盤讀入學生的信息,包括學號、成績,當輸入的學號為0時,表示建立鏈表結束。#include<stdlib.h>#include<alloc.h>#defineLENsizeof(struct

stu)/*LEN為結構體類型struct

stu的長度*/struct

stu{intnum;floatscore;

struct

stu*next;};struct

stu*creat(){struct

stu*head;/*用于指向鏈表的第一個結點*/struct

stu*p;/*用于指向新生成的結點*/struct

stu*tail;/*用于指向鏈表的最后一個結點*/

intx;floaty;tail=head=NULL;

scanf("%d",&x);

while(x!=0){p=(struct

stu*)malloc(LEN);p->num=x;

if(head==NULL)head=p;

scanf("%f",&y);p->score=y;

if(tail!=NULL)tail->next=p;tail=p;

scanf("%d",&x);}

if(tail!=NULL)tail->next=NULL;

return(head);}所謂“訪問”就是對各結點的數據域中的值進行修改、運算、輸出等。例10-11編寫函數,順序輸出鏈表中各結點數據域中的內容。順序輸出鏈表的算法比較簡單,只需利用一個指針p從頭到尾依次指向鏈表中的每個結點,即可以完成順序訪問。10.7.4順序訪問鏈表中的結點voidlist(struct

stu*head){struct

stu*p;

printf("Thelistrecordsare:\n");p=head;

if(head!=NULL)do{printf("%d\t%5.1f\n",p->num,p->score);p=p->next;}while(p!=NULL);else

printf("Thelistisnull");}main(){struct

stu*head;head=creat();

list(head);}程序運行結果如下:10190↙10289↙0↙Thelistrecordsare:1019010289共用體類型10.8教學進程使幾個不同的變量共占同一段內存的結構。一般形式union共用體名

{成員表}變量表列;雖然共用體與結構體在定義形式上類似,但它們在存儲空間的分配上是有本質區(qū)別的。按照定義中各個成員所需要的存儲空間的總和來分配存儲單元,其中各成員的存儲位置是不同的。結構體按定義中需要存儲空間最大的成員來分配存儲單元,其他成員也使用該空間,它們的首地址是相同的。共用體10.8.1什么是共用體類型共用體教學進程例如:

uniondatauniondata

{inti;{inti;charch;或charch;floatf;floatf;}a,b,c;};uniondataa,b,c;上面定義的“共用體”變量a、b、c各占4個字節(jié)(因為一個實型變量占4個字節(jié)),而不是各占2+1+4=7個字節(jié)。

溫馨提示

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

評論

0/150

提交評論