《C語言程序設計教程》課件第9章 結構體_第1頁
《C語言程序設計教程》課件第9章 結構體_第2頁
《C語言程序設計教程》課件第9章 結構體_第3頁
《C語言程序設計教程》課件第9章 結構體_第4頁
《C語言程序設計教程》課件第9章 結構體_第5頁
已閱讀5頁,還剩50頁未讀 繼續免費閱讀

下載本文檔

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

文檔簡介

第九章結構體、共用體和枚舉類型2第九章

結構體、共用體和枚舉類型教學目標:

掌握結構體類型和結構體類型變量的定義方法

掌握結構體類型變量、數組和指針的引用方法熟悉共用體和枚舉類型的概念及應用

了解鏈表的構成原理和鏈表的實現方法了解自定義類型的用法3第九章

結構體、共用體和枚舉類型教學重點與難點:熟悉結構體類型和結構體類型變量的定義方法熟悉結構體類型變量、數組和指針的引用方法了解鏈表的構成原理和鏈表的實現方法49.1結構體概述

結構體是可以將若干個不同數據類型的變量組合在一起的又一種數據類型。

結構體和數組類似,都是多個數據的集合體。

兩者不同的是:數組是相同類型數據的集合體,而結構體則可以是不同類型數據的集合體。

借助C語言提供的結構體將表達同一對象的不同屬性封裝在一起,使之達到邏輯概念與程序變量一一對應的目的,從而提高程序的清晰度,降低程序的復雜度,改善程序的可維護性。59.1.1定義結構體類型9.1.1定義結構體類型定義一個結構體類型的一般格式為:struct結構體名{

數據類型

成員1;

數據類型

成員2;

……

數據類型

成員n;};69.1.1定義結構體類型說明:(1)struct是構建結構體類型的關鍵字,也就是說,在構建結構體類型時,必須用“struct”進行聲明(2)結構體名和各成員由用戶自行命名。關鍵字struct連同其后的結構體名一起稱為結構體類型名。(3)花括號內是該結構體所包含的子項,稱為結構體的成員,每個成員是結構體中的一個域。(4)在同一結構體內,各成員的名稱不能相同;但不同結構體中的成員名可以相同,并且結構體的成員名可以與程序中的變量名相同。(5)花括號}后面的“;”不可缺少。(6)結構體類型定義的位置,可以在函數內部,也可以在函數外部。在函數內部定義的結構體類型,只能在函數內部使用;在函數外部定義的結構類型,其有效范圍從定義處開始,直到其所在的源程序文件結束。7【例9.1】構建學生信息所需要的結構體類型。程序如下:structstudent/*定義結構體類型*/{intnum;/*學號為整型*/charname[20];/*姓名為字符串*/charsex[10];/*性別為字符串*/intage;/*年齡為整型*/intscore;/*成績為整型*/charaddr[30];/*地址為字符串*/};9.1.1定義結構體類型8

9.1.2定義結構體變量

結構體類型是由若干的基本類型復合而成。在概念上必須清楚地認識到,結構體類型也只是一種類型,而不是變量實體。

為了能在程序中使用結構體類型的數據,還需要定義結構體類型的變量,并在其中存放具體的數據。

定義結構體類型變量的方法有三種。9.1.2定義結構體變量9方法一:在定義結構體類型的同時,定義變量。格式:struct結構體名

{

數據類型

成員1;

數據類型

成員2;

……

數據類型

成員n;}變量1,變量2,……,變量n;9.1.2定義結構體變量109.1.2定義結構體變量【例9.2】定義兩個結構體類型的變量。程序如下:structstudent{intnum;charname[20];charsex[10];intage;intscore;charaddr[30];}student1,student2;

以上程序中定義了兩個變量student1和student2,它們的類型為結構體。11方法二:先定義結構體的類型,再定義該類型的變量。格式:結構體類型名

變量1,變量2,……,變量n;【例9.3】定義兩個結構體類型的變量。程序如下:structstudent{intnum;charname[20];charsex[10];intage;intscore;charaddr[30];};structstudentstudent1,student2;9.1.2定義結構體變量12方法三:不指定結構體類型名,直接定義結構體類型的變量。例9.2采用方法三程序如下:struct{intnum;charname[20];charsex[10];intage;intscore;charaddr[30];}student1,student2;

用這種形式來定義結構體變量,只能使用一次,因為該結構體類型沒有類型名,程序的其他位置就無法再次使用該類型去定義別的變量了。9.1.2定義結構體變量139.1.3引用結構體變量數據1.結構體變量成員的引用

結構體變量的運算都是基于它的成員變量。也就是說,要通過引用它的成員變量來進行結構體變量的運算。

引用結構體變量中的成員的一般形式為:結構體變量名.成員名

其中,“.”稱為成員運算符。在所有的運算符中,它的優先級最高。注意:

如果結構體變量的成員又是一個結構體變量,則只能對最底層的成員進行各種運算。在引用最底層的成員時,要增加成員運算符,一層一層地找到最底層的成員。9.1.3引用結構體變量數據149.1.3引用結構體變量數據【例9.4】在例9.1的基礎上,構建學生年齡信息的結構體類型。程序如下:structdate/*定義一個結構體類型structdate*/{intmonth;/*月份*/intday;/*日期*/intyear;/*年份*/};structstudent/*定義一個結構體類型structstudent*/{intnum;charname[20];charsex[10];intage;structdatebirthday;/*成員birthday屬于structdate類型*/charaddr[30];}student1,student2;152.結構體變量的初始化

與基本類型的變量一樣,結構體變量的初始化也可以通過賦值語句及相關函數的形式實現初始化。(1)通過賦值語句對結構體變量的成員賦值。

方法一:定義變量的同時給變量的成員賦值。【例9.5】

定義結構體類型的變量并對其成員賦初值。structstudent{intnum;charname[20];charsex[10];intage;intscore;charaddr[30];};structstudentstudent1={10001,"ZhangSan","male",21,91,"100wuhanroad"};9.1.3引用結構體變量數據16方法二:同時定義結構體類型和結構體變量,并對結構體變量的成員賦值。structstudent{intnum;charname[20];charsex[10];intage;intscore;charaddr[30];}student1={10001,"ZhangSan","male",21,91,"100wuhanroad"};9.1.3引用結構體變量數據17(2)通過相關函數對結構體變量的成員賦值。

【例9.6】對例9.2中的結構體變量student1的成員進行初始化。structstudent{intnum;charname[20];charsex[10];intage;intscore;charaddr[30];}student1;9.1.3引用結構體變量數據18輸入學號可用:scanf("%d",&student1.num);輸入姓名可用:gets();或者scanf("%s",);輸入性別可用:gets(student1.sex);或者scanf("%s",student1.sex);輸入年齡可用:scanf("%d",student1.age);輸入成績可用:scanf("%d",student1.score);輸入家庭地址可用:gets(student1.addr);或者scanf("%s",&student1.addr);9.1.3引用結構體變量數據19

9.2.1結構體類型的數組結構體數組是指每個數組元素都是一個結構體變量,它們都分別包括各個成員項。例如:structstudent{intnum;charname[20];charsex[10];intage;intscore;charaddr[30];}student1,student2[2];

這里定義了structstudent結構體類型的變量student1和結構體類型的數組student2。9.2結構體類型209.2.1結構體類型的數組對結構體數組進行初始化,可采用以下兩種方式:方式1:通過賦值的方式對結構體數組初始化structstudent{intnum;charname[20];charsex[10];intage;intscore;charaddr[30];}student2[2]={{10001,"ZhangSan","male",21,91,"100wuhanroad"},{10002,"LiSi","female",20,93,"31hepingroad"}};219.2.1結構體類型的數組方式2:通過函數對結構體數組初始化for(i=0;i<2;i++){scanf("%d",&student2[i].num);getchar();/*讀到回車符*/gets(student2[i].name);gets(student2[i].sex);scanf("%d",&student2[i].age);getchar();/*讀到回車符*/scanf("%d",&student2[i].score);getchar();/*讀到回車符*/gets(student2[i].addr);getchar();/*讀到回車符*/}229.2.2結構體類型的指針9.2.2結構體類型的指針

結構體類型的指針,就是指向結構體變量的指針,結構體類型的指針中存放的是它所指向的結構體變量的起始地址。

指向結構體對象的指針變量既可以指向結構體變量,也可以指向結構體數組中的元素。

注意:

指針變量的類型必須與結構體變量的類型一致。231.指向結構體變量的指針例如:structstudent{

intnum;charname[20];charsex[10];intage;intscore;charaddr[30];}student1,student2[2],*p;

其中,*p即定義的結構體類型的指針。9.2.2結構體類型的指針24使用結構體指針時需要注意:(1)結構體指針必須先賦值后才能使用。賦值是把結構體變量的首地址賦給該指針變量。(2)如果p已經指向結構體變量student1,則以下三種用法是等價的:p->num=10001;(*p).num=10001;student1.num=10001;

其中“->”稱為結構體指針成員運算符,其作用是引用結構體指針的成員。(3)如果結構體指針已經指向一個結構體變量,就不能再使之指向結構體變量的成員。9.2.2結構體類型的指針259.2.2結構體類型的指針【例9.8】通過結構體指針引用前面例子中的結構體變量。程序如下:#include<stdio.h>#include<string.h>structstudent{intnum;charname[20];charsex[10];intage;intscore;charaddr[30];};26voidmain(){structstudentstudent1,*p;p=&student1;student1.num=10001;strcpy(,"ZhangSan");strcpy(student1.sex,"male");student1.age=21;student1.score=91;strcpy(student1.addr,"100wuhanroad");printf("num:%d\nname:%s\nsex:%s\nage:%d\nscore:%d\naddr:%s\n",

(*p).num,(*p).name,(*p).sex,p—>age,p—>score,p—>addr);}9.2.2結構體類型的指針272.指向結構體數組的指針也可以用指針變量指向結構體數組的元素。【例9.9】有3個學生的信息,放在結構體數組中,要求輸出這3個學生的信息。程序如下:#include<stdio.h>structstudent{intnum;charname[20];charsex[10];intage;intscore;charaddr[30];};9.2.2結構體類型的指針28structstudentstudent1[3]={{10001,"ZhangSan","male",21,91,"100wuhanroad"},{10002,"LiSi","female",20,93,"31hepingroad"},

{10003,"WangWu","male",20,86,"76youyiroad"}};voidmain(){structstudent*p;for(p=student1;p<student1+3;p++)printf("numnamesexagescoreaddr\n");printf("%5d%-20s%-10s%4d%6d%-30s\n",p—>num,p—>name,p—>sex,p—>age,p—>score,p—>addr);}9.2.2結構體類型的指針程序運行結果:293.用結構體變量作函數參數

將一個結構體變量的值傳遞給另一個函數,可用以下三種方法:用結構體變量的成員作參數。其用法和用普通變量作實參是一樣的,屬于“值傳遞”方式。(2)用結構體變量作實參。用結構體變量作實參時,采取的也是“值傳遞”方式,將結構體變量所占的內存單元的內容全部按順序傳遞給形參,形參也必須是同類型的結構體變量。(3)用指向結構體變量(或數組元素)的指針作實參,將結構體變量(或數組元素)的地址傳給形參。9.2.2結構體類型的指針309.2.3鏈表1.鏈表概述

使用數組存放一組同類型的數據時,其元素的個數在定義時必須指定,大小不能改變,換成鏈表來處理這組數據,則沒有這種缺點。

鏈表是一種常見的重要的數據結構。在C語言中,利用結構體的遞歸就可以實現動態存儲分配,它可以使不占連續內存單元的數據連接起來,構成動態的數據結構。這種數據結構稱為鏈表,它是根據需要來開辟內存單元的。9.2.3鏈表31

最簡單的一種單向鏈表結構:

圖中head表示鏈表中的“頭指針”變量,它存放一個地址,該地址指向一個元素。鏈表中每一個元素稱為“結點”,每個結點包含兩個部分:(1)用戶需要的實際數據;(2)下一個結點的地址。鏈表中的第一個結點稱為“表頭”,鏈表的最后一個結點稱為“表尾”。從圖中可以看出,“表頭”指向第一個元素,第一個元素又指向第二個元素,……,直到鏈表的最后一個元素。“表尾”不再指向任何其它元素,其地址部分存放一個空地址“NULL”,鏈表到此結束。9.2.3鏈表32

鏈表中各元素在內存中的地址可以是不連續的。要找某一個元素,必須先找到上一個元素,根據它提供的下一個元素的地址才能找到下一個元素。如果沒有提供“頭指針”head,則整個鏈表都無法訪問。

可以利用指針變量來實現鏈表的這種數據結構,即一個結點應包含有一個指針變量,用它存放下一個結點的地址。9.2.3鏈表33

定義鏈表結點,可以采用以下形式:structstudent{intnum;intscore;structstudent*next;};

其中,成員num和成員score存放的是用戶需要的數據,稱為數據域;而next是指針類型的成員,稱為指針域,它指向structstudent類型數據。9.2.3鏈表342.動態存儲分配函數(1)內存分配函數malloc(size)

作用是在內存的動態存儲區中分配一個長度為size的連續空間。形參size的類型為無符號整型(不允許為負數)。函數的返回值是所分配區域的第一個字節的地址,即此函數為一個指針型函數。(2)釋放內存函數free(p)

作用是釋放指針變量p所指向的動態空間地,使這部分空間能夠重新被其他變量使用。p必須為最近一次調用malloc函數時得到的返回值。

上面兩個函數在頭文件stdlib.h中,使用時應當有包含語句“#include<stdlib.h>”。9.2.3鏈表353.鏈表的建立

建立鏈表是指在程序執行過程中從無到有地建立起一個鏈表,即一個一個地開辟結點和輸入各結點數據,并建立起前后結點相鏈的關系。

建立鏈表的過程是先建立鏈表的頭結點,并將該頭結點作為尾結點,然后不斷增加新結點,將新增的結點連接在當前尾結點的后面作為新的尾結點。為此,建立鏈表時需要設置三個指針,分別指向鏈表的頭結點、新建結點和尾結點。9.2.3鏈表36建立鏈表的過程如下:(1)定義三個結構體指針變量h、p1和p2。(2)使用malloc函數申請一段存儲空間存放頭結點,將該存儲空間的起始地址存放在指針h中,且其數據域和指針域均為空,并使p1和p2同時指向頭結點,表示該結點既是頭結點,也是當前結點,又是尾結點。(3)向當前結點數據域輸入數據。(4)若輸入數據為結束標志,則轉至(7);否則繼續。(5)再次使用malloc函數申請一段存儲空間存放下一個新建結點,該存儲空間的起始地址存放在指針p1中。向p1結點數據域輸入數據,并將p1結點的起始地址存入p2結點的指針域,這樣,p1結點被鏈接在p2結點之后。再將p1起始地址存入指針p2使新建結點成為新的尾結點。(6)返回(3)。(7)結束建立鏈表,并在尾結點的指針域中放入NULL,作為鏈表結束的標記。9.2.3鏈表37【例9.11】將鍵盤輸入的非0整數依次存入鏈表各個結點的數據域中,當輸入整數0時,結束建立鏈表。程序如下:#include<stdio.h>#include<stdlib.h>structnode/*結點*/{intdata;/*結點數據域*/structnode*next;/*結點指針域*/};structnode*creatlist()/*建立鏈表函數*/{structnode*h,*p1,*p2;/*定義三個結構體指針變量*/inta;h=(structnode*)malloc(sizeof(structnode));/*頭結點*/p1=p2=h;9.2.3鏈表38scanf(“%d",&a);/*從鍵盤輸入一個整數*/while(a!=0){p1=(structnode*)malloc(sizeof(structnode));/*插入結點起始地址*/p1—>data=a;/*向結點數據域輸入數據*/p2—>next=p1;/*將當前結點作為新的尾結點*/scanf("%d",&a);}p2—>next=NULL;/*在尾結點放入結束標記*/return(h);}voidmain(){structnode*head;head=creatlist();/*創建鏈表并保存鏈表起始地址*/}9.2.3鏈表394.鏈表的輸出

輸出鏈表的過程是根據鏈表的頭結點找到下一個結點,先輸出數據域中的數據,然后根據指針域中的地址,取出后繼結點,輸出其中的數據,直到鏈表的末尾。

輸出鏈表的過程如下:(1)根據調用函數傳遞來的鏈表首地址找到該鏈表的頭結點。(2)由頭結點的指針域中的地址找到下一個結點。(3)若結點在指針域中的地址不是NULL,輸出其中的數據,并繼續找下一個結點;若指針域中的地址為NULL,返回調用函數。9.2.3鏈表40

【例9.12】依次輸出例9.11中鏈表各結點的數據。

程序如下:voidprintlist(structnode*h)/*輸出鏈表函數*/{structnode*p1;p1=h—>next;/*取頭結點之后一結點*/while(p1!=NULL){printf("%d",p1—>data);p1=p1—>next;/*繼續取后繼結點*/}printf("\n");return;}然后在函數中調用輸出鏈表函數即可。9.2.3鏈表419.3共用體類型1.共用體的定義與意義

共用體又稱聯合體(union),是幾個不同類型的變量共享同一段內存單元的一種存儲結構,這些不同類型的變量在內存中所占用的起始單元相同。

共用體聲明的一般形式為:union共用體名{

類型1成員1;

類型2成員2;

類型n成員n;};429.3共用體類型例如:uniondata{inti;charch;floatf;};

聲明一個名為data的共用體類型,共有3個成員:成員i為整型,成員ch為字符型,成員f為實型,這3個成員共用一段內存且起始地址是相同的。說明:結構體變量所占內存大小是所有成員所占內存大小的總和;而共用體變量所占內存大小等于它最長成員的長度。432.共用體變量的定義

共用體變量的定義形式與結構體類似,可以采用如下三種方法:

(1)定義共用體時同時定義其變量

(2)先定義共用體后定義變量。

(3)直接定義共用體類型變量。9.3共用體類型443.共用體變量的引用

共用體變量只有先定義了才能引用。共用體變量的引用與結構體變量一樣,不能直接引用共用體變量,而只能引用共用體變量中的成員,如a.i、b.f。

以下的引用是錯誤的:printf("%d",a);

因為a的存儲區中包含有不同類型的數據,系統無從判別究竟應該輸出哪一個成員的值。9.3共用體類型454.共用體類型數據的特點

共用體類型的數據具有以下特點,使用中要加以注意:(1)系統采用覆蓋技術實現共用體變量各成員的內存共享,所以某一時刻,存放和起作用的是最后一次存入的成員值。在對共用體變量中的一個成員賦值后,原有變量存儲單元中的值就被取代。(2)與結構體變量不同,不能對共用體變量進行初始化,但可以對共用體變量中指定的某一個成員初始化。(3)由于所有成員共享同一個內存空間,所以共用體變量的地址與其各成員的地址都是同一個地址。如&a,&a.i,&a.ch,&a.f都是同一值。(4)共用體類型可以出現在結構體類型定義中,也可以定義共用體數組。反之,結構體也可以出現在共用體類型定義中,數組也可以作為共用體的成員。9.3共用體類型469.3共用體類型【例9.13】利用共用體成員共享存儲單元的特點,將int類型數據的高字節和低字節進行分離。

程序如下:#include<stdio.h>unionun/*共用體類型聲明*/{inta;/*共用體成員a*/charch[2];/*共用體成員ch*/}data;/*定義共用體類型變量data*/voidmain(){scanf("%x",&data.a);printf("%x%x\n",data.ch[0],data.ch[1]);}479.4枚舉類型

如果一個變量只有有限幾種可能的值,就可以將它定義成枚舉類型變量。所謂“枚舉”是將變量可能的值一一列舉出來,變量的值只限于列舉值的范圍內。1.枚舉類型及枚舉變量的定義

枚舉類型的定義形式為:

enum枚舉名{枚舉元素列表};

其中,enum為關鍵字,enum連同枚舉名一起稱為枚舉類型名,枚舉元素名為一個個由用戶自行定義的標識符。

枚舉變量的定義與結構體變量及共用體變量的定義方式一樣,即:枚舉類型名枚舉變量名。482.枚舉元素的取值(1)枚舉元素是常量而不是變量,所以不能對枚舉元素賦值。它們的值只能在定義或初始化時獲得。(2)枚舉元素若未初始化,則按各元素在定義時的排列次序依次從0開始取值。(3)每一個枚舉元素都代表一個整數,可以在初始化時人為指定各元素的取值,也可以只對部分枚舉元素初始化,未初始化的枚舉元素取值比它前面的元素大1。9.4枚舉類型49【例9.14】利用枚舉變量作循環變量和數組下標。程序如下:#include<stdio.h>enumcoin{penny,nickel,dime,quarter,half_dollar,dollar};/*定義枚舉類型enumcoin*/charname[][10]={“January”,“February”,“March”,“April”,“May”,“June”,“July”,“August”,“September”,“October”,“November”,“December”};/*定義字符數組name并初始化*/voidmain(){enumcoini;for(i=Penny;i<=dollar;i++)/*枚舉元素未初始化,penny默認為0,dollar默認為5*/printf("%s",name[i]);}9.4枚舉類型程序運行結果:Ja

溫馨提示

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

評論

0/150

提交評論