第6章 結(jié)構(gòu)體_第1頁
已閱讀1頁,還剩43頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、第六章 結(jié)構(gòu)體,一、問題的提出經(jīng)常會碰到一些表格,例如下面的學(xué)生成績管理表格。,利用數(shù)組來進(jìn)行編程,必須按列來存儲,即同一類型,而不能按照記錄來存儲,不符合人們的日常習(xí)慣。,二、結(jié)構(gòu)體的聲明 結(jié)構(gòu)體——是一個或多個可以是相同數(shù)據(jù)類型、也可以是不相同的數(shù)據(jù)類型的變量集合在一個名稱下,便于應(yīng)用的數(shù)據(jù)類型。結(jié)構(gòu)體聲明的格式如下:,struct 結(jié)構(gòu)體名{ 成員表列};,第六章 結(jié)構(gòu)體,,整體是新的

2、數(shù)據(jù)類型名,關(guān)鍵字,構(gòu)成結(jié)構(gòu)體的成員,;聲明結(jié)束,不能省略,例如對于前面的學(xué)生成績管理例子中,可以聲明如下結(jié)構(gòu)體:struct ST{ int StudentID; char StudentName[10]; char StudentSex[4]; int TimeOfEnter; int Score_1; int Score_2; int Score_3; int Score_4;

3、};,,成員由不同數(shù)據(jù)類型的變量組成,共同組成一條學(xué)生記錄。,第六章 結(jié)構(gòu)體,第六章 結(jié)構(gòu)體,注意:此時只是聲明了一種新的數(shù)據(jù)類型,這種數(shù)據(jù)類型就是 Struct ST,此時并不為其分配空間。三、定義結(jié)構(gòu)體變量(1) 先聲明結(jié)構(gòu)類型再定義結(jié)構(gòu)體變量 struct ST student1, student2;,數(shù)據(jù)類型,變量名,,,一旦定義了結(jié)構(gòu)體類型的變量student1,student

4、2,它們就具有了struct ST類型結(jié)構(gòu),系統(tǒng)為每個變量分配相應(yīng)的內(nèi)存,內(nèi)存的大小由聲明的結(jié)構(gòu)體決定,即結(jié)構(gòu)體中所有成員占用內(nèi)存的總和。,(2) 在聲明結(jié)構(gòu)體類型的同時定義變量struct ST{ int StudentID; char StudentName[10]; char StudentSex[4]; int TimeOfEnter; int Score_1; int Score_2

5、; int Score_3; int Score_4;}student1, student2;,struct 結(jié)構(gòu)體名{ 成員表列;} 變量名表列;,,第六章 結(jié)構(gòu)體,(3)直接定義結(jié)構(gòu)體變量 struct { int year; int month; int day; } birthday;,,struct { 成員表列} 變量名表列;,第

6、六章 結(jié)構(gòu)體,第六章 結(jié)構(gòu)體,若表格的形式如下:,則結(jié)構(gòu)體形式如下:struct date{ int year; char month[10]; int day;};,struct ST{ int StudentID; char StudentName[10]; char StudentSex[4]; struct date TimeOfEnter; int Score

7、_1; int Score_2; int Score_3; int Score_4;}student1, student2;,四、定義指向結(jié)構(gòu)體的指針 一個結(jié)構(gòu)體變量的指針是該結(jié)構(gòu)體變量所占的內(nèi)存空間的首地址。定義的方法與定義結(jié)構(gòu)體變量的方法相似,也有三種。例如:struct ST *pt;/*pt 是指向struct ST 結(jié)構(gòu)體數(shù)據(jù)類型的指針變量*/ struct ST

8、 student1; pt=&student1;,第六章 結(jié)構(gòu)體,五、結(jié)構(gòu)體變量的引用 結(jié)構(gòu)體類型的變量有:普通變量、指針變量和數(shù)組。定義了一個結(jié)構(gòu)體變量以后,就可以引用此變量。 C語言規(guī)定,不能將一個結(jié)構(gòu)體變量作為一個整體進(jìn)行輸入、輸出(即不可以:printf(“%d%s%d”, student); ),而必須對其成員在輸出表列中逐一顯示列出,然后再逐一輸入其

9、值。,第六章 結(jié)構(gòu)體,第六章 結(jié)構(gòu)體,訪問結(jié)構(gòu)體成員的方法:(1)對于定義的結(jié)構(gòu)體類型的普通變量,使用圓點運算符訪問。 結(jié)構(gòu)體變量名 . 成員名 如:student1.name=“張三”(2)對于定義為指向結(jié)構(gòu)體的指針變量,使用箭頭運算符訪問。 指向結(jié)構(gòu)體的指針變量名 -> 成員名 如:pt->name=“張三”(3)前兩者的結(jié)合

10、。例如: struct ST *pt, student; pt=&student; (*pt).studentId=12; /*不要寫成(*pt)->studentId=12;*/,幾點說明:(1)對于結(jié)構(gòu)體成員,可以像普通變量一樣進(jìn)行運算、賦值。 例如:student1.age=20; student

11、1.score1++;(2)當(dāng)結(jié)構(gòu)體成員又屬于一個結(jié)構(gòu)體類型,即結(jié)構(gòu)體嵌套, 訪問需一級一級到最低級成員。,第六章 結(jié)構(gòu)體,例如:struct date{ int year; int month; int day;} ;,struct st{ char name[20]; char sex; struct date birthday; int score;}student

12、1,student2;,訪問month成員可以采用如下方法: student1.birthday.month對于指向結(jié)構(gòu)體的指針的引用方式如下: struct st *pt; pt=&student1; pt->birthday.month=12;,第六章 結(jié)構(gòu)體,(3)可以引用結(jié)構(gòu)體變量成員的地址,也可以引用結(jié)構(gòu)體變量的地址。如: scanf(“%d”,&stu

13、dent1.num); scanf(“%s”,student1.name); /*為什么不加“&”符號*/ scanf(“%d”,&student1.birthday.year); printf(“%o”,&student1);(4)可以對具有相同結(jié)構(gòu)體類型的變量進(jìn)行整體賦值。如: struct ST student1,

14、 student2; student1賦值過程; student2=student1;,第六章 結(jié)構(gòu)體,六、結(jié)構(gòu)體變量初始化 main( ) { struct student { int num; char name[20]; char sex; char addr[20]; }

15、 a={9001,“Li Lin”,‘M’,“123 Beijing Road”}; printf(“NO.:%d\nname:%s\nsex:%c\naddress:%s\n”,a.num, a.name,a.sex,a.addr); },第六章 結(jié)構(gòu)體,第六章 結(jié)構(gòu)體,說明:(1)結(jié)構(gòu)體變量在初始化時,要注意數(shù)據(jù)類型的匹配。(2)結(jié)構(gòu)體聲明可以在所有函數(shù)體

16、的外部,也可以在函數(shù)體 的內(nèi)部。前者聲明的結(jié)構(gòu)體可以被其下的所有函數(shù)使用, 稱為全局聲明;而后者只能在相應(yīng)的函數(shù)內(nèi)部使用,稱 為局部聲明。,六、結(jié)構(gòu)體數(shù)組 一個結(jié)構(gòu)體變量只能代表一個實體,即一個數(shù)據(jù)表格中的一行, 若要表示多行,就需定義一個結(jié)構(gòu)體數(shù)組。 結(jié)構(gòu)體類型是一種數(shù)據(jù)類型,因此也可以作為數(shù)組的數(shù)據(jù)類型。 (1) 結(jié)構(gòu)體數(shù)組的

17、定義: struct 結(jié)構(gòu)體名 或 struct 結(jié)構(gòu)體名 { { 成員表列 成員表列 }數(shù)組名;

18、 }; struct 結(jié)構(gòu)體名 數(shù)組名;,第六章 結(jié)構(gòu)體,例如: struct st{ int num; char name[20]; char sex; char addr[20]; }stu[3];,struct s

19、t{ int num; char name[20]; char sex; char addr[20]; }; struct st stu[3];,第六章 結(jié)構(gòu)體,結(jié)構(gòu)體數(shù)組在內(nèi)存中是連續(xù)存放的,占用的空間為43*3個字節(jié)。問題:若結(jié)構(gòu)體是嵌套定義的,空間如何計算。,(2) 初始化結(jié)構(gòu)體數(shù)組struct st{ int num; char name[20]; char sex;

20、 char addr[20]; }stu[2]={{10101,“Li Lin”,‘M’,“103 Beiing Road”}, {10102,“Zhang fun”,‘F’,“130 Shanghai Road”}};問題:若含有嵌套定義,則應(yīng)該如何進(jìn)行初始化。,第六章 結(jié)構(gòu)體,第六章 結(jié)構(gòu)體,例:對候選人得票的統(tǒng)計程序。設(shè)有3個候選人,每次輸入一個得票的候選人的名字,要求最后輸

21、出各人得票結(jié)果。# include struct person{ char name[20]; int count;} leader[3]={“Li”,0,”Zhang”,0,”Fun”,0};,main( ){ int i,j; char leader_name[20]; for(i=1; i<=10; i++) { scanf(“%s”,leader_name);

22、 for(j=0; j<3; j++) if(strcmp(leader_name, leader[j].name) == 0) leader[j].count++; } printf(“\n”); for(i=0; i<3; i++) printf(“%5s:%d\n”, leader[i].name, leader

23、[i].count); },第六章 結(jié)構(gòu)體,第六章 結(jié)構(gòu)體,七、結(jié)構(gòu)體數(shù)組與指針 結(jié)構(gòu)體數(shù)組變量一旦定義,系統(tǒng)將為其申請一段相應(yīng)的結(jié)構(gòu)體類型的內(nèi)存空間,指向該結(jié)構(gòu)體的指針將可以用來對結(jié)構(gòu)體數(shù)組進(jìn)行操作,也可以通過指針對結(jié)構(gòu)體數(shù)組元素的成員進(jìn)行操作。例6.7 計算學(xué)生各科的平均成績(書中例題的簡化)。#include struct ST{ int StudentID; int sc

24、ore1; int score2;}stu[4]={{1,90,85},{2,88,79},{3,98,86},{4,73,64}};/*書中數(shù)組長為30*/,第六章 結(jié)構(gòu)體,main( ){ struct ST *pt; float altogether[2]={0.0}, average[2]={0.0}; int i; for(pt=stu; ptscore1; alt

25、ogether[1] = altogether[1]+pt->score2; } for(i=0; i<2; i++){ average[i] = altogether[i] / 4; printf(“score%d:%f\n”, i+1, *(average+i)); }},第六章 結(jié)構(gòu)體,八、結(jié)構(gòu)體與函數(shù) 把結(jié)構(gòu)體傳遞給函數(shù)的方式有三種:傳遞單個

26、成員、傳遞整個結(jié)構(gòu)、傳遞指向結(jié)構(gòu)的指針。1、用結(jié)構(gòu)體的單個成員作參數(shù) 結(jié)構(gòu)體的成員是確定的數(shù)據(jù)類型,所以單個成員作為實參與普通的值傳遞沒有分別。2、用結(jié)構(gòu)體整體作為函數(shù)的參數(shù)傳遞 要求實參與形參是同一數(shù)據(jù)類型才可以傳遞,同樣也是值傳遞。這種方式占用的局部空間大,通常不用。3、用指向結(jié)構(gòu)體的指針作為參數(shù)傳遞 可以用一個指向結(jié)構(gòu)體的指針作為函數(shù)參數(shù),比前一種方法有效。實質(zhì)上就是指針調(diào)用形式。,4、可

27、以用結(jié)構(gòu)體類型作為函數(shù)返回類型方法如下:,第六章 結(jié)構(gòu)體,struct date{ int year; int month; int day;};,struct date FillDate(struct date Dat){ Dat.year=1999; Dat.month=12; Dat.day=26; return Dat;},第六章 結(jié)構(gòu)體,九、動態(tài)數(shù)據(jù)結(jié)

28、構(gòu)1、問題的提出 結(jié)構(gòu)體可以包含任意數(shù)據(jù)類型,不僅可以嵌套結(jié)構(gòu)體類型,而且可以包括指向本結(jié)構(gòu)體類型的指針域,但不可以包括正在聲明的結(jié)構(gòu)體本身。例如:,struct temp{ int data; struct temp *t;}; 可以,struct temp{ int data; struct temp t;}; 不可以,第六章 結(jié)構(gòu)體,另外,處

29、理表格時,通常使用結(jié)構(gòu)體數(shù)組,而數(shù)組的長度沒有辦法確定,這時我們可以對結(jié)構(gòu)體采用動態(tài)內(nèi)存分配的方法,在需要時分配內(nèi)存,而在不需要時再將其釋放。例如:struct temp{ int data; char name[10];};struct temp *p=(struct temp*)malloc(sizeof(struct temp)*10); 或struct temp *p=(struct temp*)ca

30、lloc(sizeof(struct temp), 10);這樣可以分配12*10共120個字節(jié)的空間。,2、鏈表的定義 鏈表不是C語言的規(guī)定,而是計算機的一種數(shù)據(jù)結(jié)構(gòu)。使用它可以將結(jié)構(gòu)體、數(shù)組、指針等基本元素融合在一起。鏈表分為單向鏈表、雙向鏈表等。從鏈表中還可以引出一些特殊而有用的數(shù)據(jù)結(jié)構(gòu),如棧、隊列等。 鏈表的原理如圖:,,,,第六章 結(jié)構(gòu)體,鏈表有一個頭指針變量head,它指向鏈表的第一個元素,鏈表的

31、每一個元素稱為節(jié)點(Node),每個節(jié)點包含兩部分,data是數(shù)據(jù)域,p是指向下一節(jié)點的指針,稱為指針域。,第六章 結(jié)構(gòu)體,鏈表的開頭是指向第一個節(jié)點的指針,即頭指針,鏈表表示一個節(jié)點鏈著一個節(jié)點,每個節(jié)點都存儲在不同的內(nèi)存區(qū),只有通過前一個節(jié)點,才能找到下一個節(jié)點,所以頭指針必須保存好,否則鏈表將無法找到。 鏈表的結(jié)尾是最后一個節(jié)點,該節(jié)點的指針域指向空地址,即NULL。 鏈表的長度不固定,可以添加與刪除,

32、但要保證鏈的連貫性。上述的鏈表結(jié)構(gòu)可以定義如下: struct Link{ int data; struct Link *next; };,3、動態(tài)鏈表的建立 動態(tài)鏈表即從無到有一個節(jié)點一個節(jié)點地建立起一個完整的鏈表。如鏈表中節(jié)點的結(jié)構(gòu)為: struct student { int no; int score;

33、 struct student *next; }; 以下函數(shù)create用于建立一個鏈表,其表頭節(jié)點的指針是head,它是一個全局變量。,第六章 結(jié)構(gòu)體,第六章 結(jié)構(gòu)體,#define LEN sizeof(struct student)struct student *head;struct student *create( ){ struct student *p,*q;

34、 int n,i; printf(“學(xué)生人數(shù):”); scanf(“%d”,&n); for(i=0; ino); printf(“成績:”); scanf(“%d”,&p->score);,if(i == 0) head=p; else q->next=p; q=p; } p->next

35、=NULL; return head;},第六章 結(jié)構(gòu)體,4、顯示鏈表用函數(shù)display顯示由表頭head指向的鏈表。display(){ struct student *p; p=head; while(p!=NULL) { printf(“%d%d\n”,p->no,p->score); p=p->next; }},第六章 結(jié)構(gòu)體,

36、5、查找節(jié)點用find函數(shù)在以head為頭指針的鏈表中查找學(xué)號為n的節(jié)點。void find(){ int n; struct student *p; printf(“輸入學(xué)號:”); scanf(“%d”,&n); p=head; while(p!=NULL && p->no!=n) p=p->next; if(p!=NULL)

37、 printf(“%d,%d”,p->no,p->score); else printf(“不存在%d學(xué)號的學(xué)生.\n”,n);},第六章 結(jié)構(gòu)體,6、插入節(jié)點用函數(shù)insert在由頭指針head指向的鏈表中的第i個節(jié)點后插入一個節(jié)點。insert(){ int i,j; struct student *p,*q; printf(“輸入正整數(shù)i:”); scanf

38、(“%d”,&i); p=(struct student *)malloc(LEN); printf(“學(xué)號:”); scanf(“%d”&p->no); printf(“成績:”); scanf(“%d”,&p->score); if(i==0) { p->next=head; head=p; },else { q

39、=head; for(j=1;jnext; if(q!=NULL) { p->next=q->next; q->next=p; } else printf(“i值太大.”); }},第六章 結(jié)構(gòu)體,7、刪除節(jié)點用函數(shù)delete刪除以head為頭指針的鏈表中的第i個節(jié)點。void delete

40、(){ struct student *p,*q; int i,j; printf(“輸入正整數(shù)”); scanf(“%d”,&i); if(i == 1) { p=head; head=head->next; free(p); } else,{ q=head; for(j=1;jnext

41、; if(q!=NULL) { p=q->next; q->next=p->next; free(p); } else printf(“i值太大.”); }},第六章 結(jié)構(gòu)體,8、鏈表釋放用函數(shù)freelist釋放以head為頭指針的鏈表。freelist(){ struc

42、t student *p; while(head != NULL) { p = head; head = head->next; free(p); }},第六章 結(jié)構(gòu)體,十、typedef的使用 關(guān)鍵字typedef可用來建立已定義好的數(shù)據(jù)類型的別名。如: typedef int integer; typedef

43、 struct ST student; 在C語言中常用typedef定義結(jié)構(gòu)類型,定義形式為: struct point { int x; int y; }; typedef struct point pot; 以后,可以用pot定義結(jié)構(gòu)體變量、結(jié)構(gòu)體數(shù)組、結(jié)構(gòu)體指針等。如:po

44、t pointer, *p, wpoint[10];等同于:struct point pointer, *p, wpoint[10];,第六章 結(jié)構(gòu)體,十一、共用體 共用體又稱為聯(lián)合體,是將不同的數(shù)據(jù)類型組合在一起,共同占用同一段內(nèi)存的用戶定義的數(shù)據(jù)類型。定義格式如下: union number { int x; float

45、 y; };注意:1、共用體所占用的空間的大小為其最大空間成員所占用的空間的大小。2、共用體采用以開始地址對齊的方式分配地址空間。3、共用體在同一時刻只有一個成員是有意義的。4、共用體的操作方式與結(jié)構(gòu)體完全相同,即可以賦值、取地址、使用 圓點運算符或箭頭運算符訪問共用體成員變量。,第六章 結(jié)構(gòu)體,5、共用體不能進(jìn)行比較操作。6、共用體在初始化時,只能對第一個成員的數(shù)據(jù)類型初始化。例6.3

46、 共用體的使用方法,程序見EG6_3,第六章 結(jié)構(gòu)體,*十二、位段 有時,存儲1個信息不必占用1個字節(jié),只需二進(jìn)制的1個(或多個)位就夠用。如果仍然使用結(jié)構(gòu)類型,則造成內(nèi)存空間的浪費。為此,C語言引入了位段類型。 1、位段的概念與定義 所謂位段類型,是一種特殊的結(jié)構(gòu)類型,其所有成員均以二進(jìn)制位為單位定義長度,并稱成員為位段。位段定義的一般格式為: struct [結(jié)構(gòu)體名]

47、{ unsigned [位段名]:常量表達(dá)式; /*常量表達(dá)式表示位字段寬度(位)*/ …… };,例如,CPU的狀態(tài)寄存器,按位段類型定義如下:struct status { unsigned sign: 1; /*符號標(biāo)志*/ unsigned zero: 1

48、; /*零標(biāo)志*/ unsigned carry: 1; /*進(jìn)位標(biāo)志*/ unsigned parity: 1; /*奇偶 / 溢出標(biāo)志*/ unsigned half_carry: 1; /*半進(jìn)位標(biāo)志*/ unsigned negative: 1; /*減標(biāo)志*/ } flags; 顯然,對CP

49、U的狀態(tài)寄存器而言,使用位段類型(僅需1個字節(jié)),比使用結(jié)構(gòu)類型(需要6個字節(jié))節(jié)省了5個字節(jié)。,第六章 結(jié)構(gòu)體,2、說明(1)因為位段類型是一種結(jié)構(gòu)類型,所以位段類型和位段變量的定義,以及 對位段(即位段類型中的成員)的引用,均與結(jié)構(gòu)類型和結(jié)構(gòu)變量一樣。(2)對位段賦值時,要注意取值范圍。一般地說,長度為n的位段,其取值范 圍是:0~(2n - 1)。(3)使用長度為0的無名位段,可

50、使其后續(xù)位段從下1個字節(jié)開始存儲。例如:struct status { unsigned sign: 1; /*符號標(biāo)志*/ unsigned zero: 1; /*零標(biāo)志*/ unsigned carry: 1; /*進(jìn)位標(biāo)志*/ un

51、signed : 0; /*長度為0的無名位段*/ unsigned parity: 1; /*奇偶/溢出標(biāo)志*/ unsigned half_carry: 1; /*半進(jìn)位標(biāo)志*/ unsigned negative: 1; /*減標(biāo)志*/ } flags;,第六章 結(jié)構(gòu)體,

52、第六章 結(jié)構(gòu)體,原本6個標(biāo)志位是連續(xù)存儲在1個字節(jié)中的。由于加入了1個長度 為0的無名位段,所以其后的3個位段,從下1個字節(jié)開始存儲, 一共占用2個字節(jié)。(4)1個位段必須存儲在1個存儲單元(通常為1字節(jié))中,不能跨2個。 如果本單元不夠容納某位段,則從下1個單元開始存儲該位段。(5)可以用%d、%x、%u和%o等格式字符,以整數(shù)形式輸出位段。(6)在數(shù)值表達(dá)式中引用位段

53、時,系統(tǒng)自動將位段轉(zhuǎn)換為整型數(shù)。,第六章 結(jié)構(gòu)體,十三、枚舉常量 枚舉即一一列舉,枚舉類型是C語言提供的一種用標(biāo)識符表示的整型常量的集合。定義的形式如下: enum 枚舉名 {枚舉元素表}枚舉變量表;例如: enum week_day{mon,tue,wed,thu,fri,sat,sun}day; 這里定義了一個week_day的枚舉類型和一個具有該類型的枚舉變量day。 枚舉常量

54、是自動設(shè)置值的符號常量。若沒有指定初始值,第一個枚舉元素的值為0,第二個枚舉元素的值為1,以此類推。例如: enum week_day{mon=1,tue,wed,thu,fri,sat,sun}day;注意:枚舉類型定義時,可設(shè)置任意的枚舉常量的值,并且多個成 員可具有相同的整數(shù)值。,例:今天是星期天,求四天后是星期幾?#include void main(){ enum {sun,m

55、on,tue,wed,thu,fri,sat}day; char weekday[7][7] = {“星期天”,“星期一”, “星期二”, “星期三” “星期四”, “星期五”, “星期六” }; day = sun; printf(“今天是%s,四天后是%s”,weekday[day],week[(day+4)%7]);

溫馨提示

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

評論

0/150

提交評論