第9章结构体、共用体和枚举类型数据.ppt

上传人:本田雅阁 文档编号:2258263 上传时间:2019-03-12 格式:PPT 页数:73 大小:831.01KB
返回 下载 相关 举报
第9章结构体、共用体和枚举类型数据.ppt_第1页
第1页 / 共73页
第9章结构体、共用体和枚举类型数据.ppt_第2页
第2页 / 共73页
第9章结构体、共用体和枚举类型数据.ppt_第3页
第3页 / 共73页
亲,该文档总共73页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述

《第9章结构体、共用体和枚举类型数据.ppt》由会员分享,可在线阅读,更多相关《第9章结构体、共用体和枚举类型数据.ppt(73页珍藏版)》请在三一文库上搜索。

1、第9章 结构体、共用体和枚举类型数据,9.1 结构体类型数据 9.2 共用体类型数据 9.3 枚举类型数据 9.4 用TYPEDEF定义类型 9.5 动态存储分配链表,9.1 结构体类型数据,9.1.1. 结构体的概念及其定义,结构体概念,“结构”是一种构造类型,它是由若干“成员”组成的。 每一个成员可以是一个基本数据类型或者又是一个构造类型。 结构既是一种“构造”而成的数据类型,在说明和使用之前必须先定义它,如同在说明和调用函数之前要先定义函数一样。,结构体(structure)相当于其它高级语言中的“记录”。,num name sex score age addr,结构体的定义,定义一个结

2、构的一般形式为: struct 结构名 成员表列 ;,struct stu int num; char name20; char sex; float score; ;,成员名的命名应符合标识符的书写规定。例如:,对每个成员也必须作类型说明,其形式为: 类型说明符 成员名;,9.1.2 结构体类型变量的定义和引用,1)先定义结构体类型再定义结构体变量,例: struct student int num; char name20; char sex; int age; float score; char addr30; ;,struct student x1, x2;,则 x1, x2为stud

3、ent 结构型变量,x1, x2可存放student类型数据。,类型标识符,结构体变量定义:,1、结构体类型变量的定义(方法有三),例:struct student int num; char name20; char sex; int age; char addr30; x1, x2;, 成员表列 变量名表列;,2)在定义结构体类型的同时定义变量:,定义形式 struct 结构体名,定义形式 struct 成员表列 变量名表列; 不出现结构体类型名,3. 直接定义结构类型变量,如:struct, int num,char name20;,char sex;,int age;,char add

4、r30;, x1, x2;,1. 类型名与变量名是不同的概念 2. 每一个成员的作用如同该类型的变量 3. 成员名与程序中的变量名可相同但意义不同,几点 说明:,struct date int month; int day; int year; ;,补充:结构体的嵌套定义,struct student int num; char name20; char sex; int age; struct date birthday; char addr30; x1, x2;,2、 结构体变量初始化,结构的初始化就是指结构变量的初始化;先定义结构,在定义结构变量时对每个成员赋初值,struct stud

5、ent x1=8906, “Li Ming “, M, 85.5;,如:struct student, unsigned No;,char name20;,char sex;,float score;,;,若 x1 的起始地址为2000,则 x1 在内存中占有的存储单元为:,共用27个字节的连续单元,结构定义与变量定义及初始化合二为一:,struct exp, int a;,float b;,char yn8;, x=1234, 56. 7, “test“;,但不能这样写:,struct exp, int a=1234;,float b=56.7;,char yn8=“test“;, x;,如

6、:x1为struct student型变量,则 x1.No: 表示x1的学号 x1.name: 表示x1的名字,访问结构变量实质上是引用其成员;有两种运算符可访问结构成员,1)圆点运算符,3、结构体变量的引用,注意:,1. 只能用变量的成员,不可用结构变量名直接运算。,2. 每一个成员的作用与其同类型的简单变量的引用相同。,2)箭头运算符:,例:struct student, char name 10; char sex; int age; float score; char addr20; x1; struct student p;,则p为结构指针变量,它可用来存放student型变量的地址

7、,令 p=,则 p为x1的首地址.,访问结构成员:,pname 表示x1的姓名;等价于 (*p).name或x1.name,page 表示x1的年龄;等价于 (*p).age或x1.age,若有 struct student h;,则:scanf(“%s“, ,printf(“%s“, h);,错误,原因:结构体变量中包含有多个不同类型的数据项。 正确方法:对结构体变量各成员的值进行输入/输出。,如上例:scanf(“%d%s“, , 只能对结构变量的成员进行输入/输出,4、结构体的输入和输出,1、 结构体数组的定义,结构数组的定义方法和结构变量相似(也有三种方法),只需说明它为数组类型即可。

8、例如:,9.1.3 结构体数组,struct stu int num; char *name; char sex; float score; boy5;,struct stu int num; char *name; char sex; float score; ; struct stu boy5;,struct int num; char *name; char sex; float score; boy5;,对外部结构数组或静态结构数组可以作初始化赋值,例如: struct stu int num; char *name; char sex; float score; boy5= 101,

9、“Li ping“,“M“,45, 102,“Zhang ping“,“M“,62.5, 103,“He fang“,“F“,92.5, 104,“Cheng ling“,“F“,87, 105,“Wang ming“,“M“,58 ;,注:当对全部元素作初始化赋值时,也可不给出数组长度。,2、结构体数组的初始化,main() int i,c=0; float ave,s=0; for(i=0;i5;i+) s+=boyi.score; if(boyi.score60) c+=1; printf(“s=%fn“,s); ave=s/5; printf(“average=%fncount=%dn

10、“,ave,c); ,3、结构体数组的引用,9.1.4 结构体变量作为函数参数,struct tree int x; char *s; t; void fun(struct tree a ) printf(“%d, %sn“, a.x, a.s); ,#include main( ) t.x=6; t.s=“minicomputer“;fun(t); ,结果:6, minicomputer,1、指向结构体变量的指针,一个指针变量当用来指向一个结构变量时,称之为结构指针变量。结构指针变量中的值是所指向的结构变量的首地址。 结构指针变量说明的一般形式为: struct 结构名 *结构指针变量名 例

11、如,在前面的例题中定义了stu这个结构,如要说明一个指向stu的指针变量pstu,可写为: struct stu *pstu; 当然也可在定义stu结构时同时说明pstu。,9.1.5 结构体变量与指针,与前面讨论的各类指针变量相同,结构指针变量也必须要先赋值后才能使用。 赋值是把结构变量的首地址赋予该指针变量,不能把结构名赋予该指针变量。如果boy是被说明为stu类型的结构变量,则: pstu=&boy 是正确的,而: pstu=&stu 是错误的。,其访问的一般形式为: (*结构指针变量).成员名 或为: 结构指针变量-成员名 例如: (*pstu).num 或者: pstu-num 应该

12、注意(*pstu)两侧的括号不可少,因为成员符“.”的优先级高于“*”。如去掉括号写作*pstu.num则等效于*(pstu.num),这样,意义就完全不对了。,2、指向结构体数组的指针,指针变量可以指向一个结构数组,这时结构指针变量的值是整个结构数组的首地址。结构指针变量也可指向结构数组的一个元素,这时结构指针变量的值是该结构数组元素的首地址。 设ps为指向结构数组的指针变量,则ps也指向该结构数组的0号元素,ps+1指向1号元素,ps+i则指向i号元素。这与普通数组的情况是一致的。 例 用指针变量输出结构数组。,main() struct stu *ps; printf(“NotNamet

13、ttSextScoretn“); for(ps=boy;psnum,ps-name,ps-sex,ps-score);,struct stu int num; char *name; char sex; float score; ,boy5= 101,“Zhou ping“,M,45, 102,“Zhang ping“,M,62.5, 103,“Liou fang“,F,92.5, 104,“Cheng ling“,F,87, 105,“Wang ming“,M,58, ;,应该注意的是,一个结构指针变量虽然可以用来访问结构变量或结构数组元素的成员,但是,不能使它指向一个成员。也就是说不允许取

14、一个成员的地址来赋予它。因此,下面的赋值是错误的。 ps=(赋予0号元素首地址),9.2 共用体类型数据,9.2.1 共用体的概念, 什么是共用体?它是几个不同的变量共同占用同一段内存空间的结构。这几个不同的变量可以具有不同的类型,但具有相同的指针(地址)。 定义共用体 union 共用体名 成员表列 ; 例如:union data int x; char y; float z; ;,1、共用体变量的定义,共用体变量的说明和结构变量的说明方式相同, 也有三种形式。,union data int x; char y; float z a,b;,union /*无类型名*/ int x; char

15、 y; float z a,b;,union data int x; char y; float z ; union data a,b;,9.2.2 共用体变量,2、 共用体与结构体比较,3、 共用体变量的引用,(1)虽然共用体变量可以存储几种不同类型的成员,但在在同一时刻,只能存储其中的一个,即只能有一个成员起作用。 (2)共用体变量中起作用的是最后一次存放的成员,以前存放的成员皆失效。例如顺序执行 a.x=12; a.y=A; a.z=23.5;语句后,只有成员a.z 有效。 (3)共用体变量的地址和它的各成员的地址都相同。即&a、&a.、&a.、&a.的地址都相同。,4、 共用体类型数据

16、特点,(4)不能单独引用共用体变量名,也不能在定义共用体变量时对其初始化。 例如:union data int x; char y; float z a=12,E,12.5; a=12;m=a; 都是错误的。 (5)在结构体类型的定义中可以有共用体类型的成员;也可定义共用体类型的数组。反之亦然。,例 建立学生与教师的简表,内容有:name、job、class、position。表中前2项一样,第3项采用共用体数据:即job为s(学生)时,第3项采用class(班级);job为t(教师)时,第3项采用position(职务)。,5、 共用体变量的应用,Struct char name20; ch

17、ar job; union int class; char position10; cat; person10;,main() int n; for(n=0;n10;n+) scanf(“%s %c”,personn .name, ,9.3 枚举类型数据,9.3.1 枚举型数据基本概念, 所谓“枚举”类型,是指这种类型的变量的值只能是指定的若干个名字之一。 定义枚举类型:enum 枚举类型名元素表; 例如:enum weekdaysun,mon,tue,wed,thu,fri,sat; 定义了一个枚举类型weekday,该类型只包含7个枚举元素sun、mon、tue、wed、thu、fri、s

18、at,这些枚举元素都是常量。,定义枚举变量有3种方式: 先定义枚举类型再定义枚举变量。例如: enum weekdaysun,mon,tue,wed,thu,fri,sat; enum weekday workday,weekend; 定义枚举类型的同时定义枚举变量。例如: enum weekdaysun,mon,tue,wed,thu,fri,sat workday, weekend; 直接定义枚举变量。例如: enumsun,mon,tue,wed,thu,fri,satworkday, weekend; 变量workday、weekend只能取常量sun、mon、tue、wed、 thu

19、、fri、sat 中的一个。 定义一个枚举变量后,就可将一个枚举常量赋予它,例如: workday= wed;,9.3.2 枚举型变量的定义,枚举元素是符号常量,不能为其赋值。例如:sun=1 是错误的。 枚举元素的值: 枚举元素作为符号常量,是有值的,例如上面的的sun、 sat 的值分别是0、1、2 、 6,即第一个元素的值自动为0,其后的 元素自动依次加1。 枚举元素的值在定义枚举类型时,也可由用户指定,例如: enum weekdaysun=7,mon=1,tue,wed,thu,fri,sat; 则tue,wed,thu,fri,sat依次为2、3、4、5、6。 当把一个枚举常量赋予

20、一个枚举变量后,该变量就有了该常量的值。 例如:workday=mon;printf(“%d”,workday);则输出1。或者说枚举变量的值是通过枚举常量间接获得的。,9.3.3 枚举型变量的引用,枚举值是可比较的。枚举值的大小依据枚举元素的值而定。例如: mon 小于tue,而 sat 大于wed。所以可用于下面的语句: if(workday sun) if(workday= sun) 不能把一个整数直接赋予枚举变量。例如: workday=2 ;是错误的, 原因在于它们类型不一致,可通过强制类型转换把一个整数直接赋予枚举变量,例如:workday=(enum weekday)2;是可行的

21、。,严格的说,枚举变量和常量是不能做算术运算的,例如 workday+、weekend=workday+wed是不允许的,但有些系统采用警告的方式,但不禁止,也就是说系统将按枚举变量和常量的值做算术运算。,9.4 用TYPEDEF定义类型,9.4.1. typedef的概念,用用户喜欢的名字来替换这些类型名,再用用户自定义这些类型名去定义相关的变量。例如: typedef int INTEGER; /*用INTEGER 代替int 类型*/ typedef float REAL; /*用REAL代替float 类型*/ INTEGER a,b; /*定义整型变量a,b */ REAL x,y

22、/*定义实型变量x,y */,typedef int INTEGER; INTEGER m,n; typedef float REAL; REAL x,y; typedef char CHARACTER; CHARACTER c,d; typedef int * INT_POINTER; INT_POINTER p1,p2;(整型指针) typedef char * CH_P; CH_P pa,pb20;(字符型指针) typedef int NUM8; NUM a,b;(含8个元素的整型数组) typedef char(*CP)10; CP pn;(指向一维数组的指针) typedef fl

23、oat(*PFUN)(); PFUN fp;(指向函数的指针),9.4.2 typedef的应用举例,typedef struct int day; int month; int year; DATE; DATE birthday,rest;(结构体) typedef union char a; int b; float c; DATA; DATA x,y,z;(共用体) typedef enumred,green,blueCOLOR; COLOR tv;(枚举类型),1、设有如下定义: struct sk int a; float b; data, *p; 若有p=,3、变量a所占的内存字节

24、数是_. A) 4 B) 5 C) 6 D) 8 union U char st4; int i; long l; ; struct A int c; union U u; a;,4、下列程序的输出结果是_. #include main( ) union int k; char i2; *s,a; s= A) 3839 B) 3938 C) 380039 D) 390038,5、以下程序的输出结果是_. main() union char i2; int k; r; r.i02; r.i1=0; printf(“%dn”, r.k); A) 2 B) 1 C) 0 D) 不确定,6、以下程序

25、#include struct stu int num; char name10; int age; void fun(struct stu *p) printf(“%sn”,(*p).name); main() struct stu student3=9801,”Zhang”,20, 9802,”Wang”,19,9803,”Zhao”,18; fun(student+2); 输出结果是_. A) Zhang B) Zhao C) Wang D) 18,7、下面程序的输出为_. struct st int x; int *y;*p; int dt4=10,20,30,40; struct s

26、t aa4=50, A) 10 B) 50 C) 51 D) 60 20 60 60 70 20 21 21 31,8、以下各项企图说明一种新的类型名,其中正确的是_. A) typedef v1 int; B) typedef v2=int; C) typedef int v3; D) type v4;int; 9、设有以下语句 typedef struct S int f; char h; T; 则下面叙述正确的是_. A) 可用S定义结构变量 B) 可用T定义结构变量 C) S是struct类型的变量 D) T是struct类型的变量,9.5 动态存储分配链表,9.5.1 动态存储分配和

27、链表的概念,链表是一种常见的重要的数据结构。它是动态地进行存储分配的一种结构。,链表的结构特点,首指针,数 据 指 针,数 据 指 针,数 据 指 针,数 据 NULL,链表是一种由首指针和若干结点组成的数据链,形式如下: A B C D,链表的特点是: 其中首指针是不能少的,它含有结点A的起始地址,只有通过它才能找到后面各结点。且首指针千万不能丢失,否则链表将丢失。 各结点是链接在一起的,结点A的指针域包含结点B的起始地址,结点B的指针域包含结点C的起始地址,依此类推。 最后一个结点D又称“表尾”,表尾的指针域包含数据NULL,表示是空地址,链表到此结束。 由于结点中指针域的存在,各结点在内

28、存中占用的存储空间不要求必须是连续排列的。这是一个很重要的特点。,9.5.2 用包含指针的结构体变量构成结点,链表结点含有二个域:数据域和指针域。数据域可以包含用户的各种类型的数据;指针域是一个指向下一个结点的指针变量。由此看出结点采用结构体类型的数据结构最合适。例如: struct student int num; float score; struct student *next; ; 其中:变量num和score是数据域的用户数据。 变量next是指针域的指针变量,用于指向下一个结点。,#include /*含NULL的定义*/ main() struct student a,b,c,*

29、head,*p; a.num=1001;a.score=89;/*建立结点数据域*/ b.num=1002;b.score=90; c.num=1003;c.score=86; head=&a;/*建立首指针变量*/ a.next=&b;/*指向下一个结点*/ b.next=&c; c.next=NULL;/*最后结点指针域为空指针*/ for(p=head;p!=NULL;p=pnext) printf(“%ld %5.1fn”,pnum,pscore); 注:我们此处建立的链表是一个“静态链表”,其特点是:各个结点是在程序中预先以变量的形式开辟出来的,用完后也不会主动释放所占存储空间。这对

30、于需要大量链表的程序来说,无疑是一种极大的存储空间浪费。,struct student long num; float score; struct student *next; ;,例 建立一个由3个学生的数据为结点的链表。,9.5.3 用于动态存储分配的函数,1malloc函数 函数原型:void * malloc(unsigned int size); 功能:在内存的动态存储区,分配一个长度为size个字节的连续存储空间;并返回一个指针,该指针就是已分配的存储空间的起始地址 (基类型是void)。若函数调用失败,例如内存空间不足,则返回空指针(NULL)。此函数常用于为链表的结点开辟存储空

31、间,例如: struct student long num; float score; struct student *next; main() struct student *head,*p; p=(struct student *)malloc(sizeof(struct student); head=p; pnum=1001;pscore=99; ,2calloc函数 函数原型: void * calloc(unsigned n ,unsigned size); 功能:在内存的动态存储区,分配n个长度为size个字节的连续存储空间;并返回一个指针,该指针就是已分配的存储空间的起始地址(基

32、类型是void)。若函数调用失败,例如内存空间不足,则返回空指针(NULL)。此函数常用于为一维数组分配连续存储空间,例如: main() int *p; p=(int *)calloc(10,sizeof(int); /*指针p 指向一个含有10个元素的整型数组*/ ,3free函数 函数原型:void free( void *p ); 功能:其作用是释放由指针变量p指向的内存空间。p是最近一次调用 malloc或 calloc函数时返回的指针。free无返回值。 例如:free( p ); /*释放指针变量p指向的内存空间*/ 注:函数sizeof()的参数可以是变量名或某种类型名,其返回

33、值是参数的长度(以字节为单位)。,4realloc函数 函数原型: void *realloc( void *ptr, unsigned int size); 功能:其作用是使已分配的空间改变大小,即重新分配。将ptr指向的存储区(是原先用malloc函数分配的)的大小改为size个字节。可以使原先分配区扩大也可以缩小。它的函数返回值是一个指针,即新的存储区的首地址。应指出,新的首地址不一定与原来地址相同,因为为了增加空间,存储区会进行必要的移动。,1、建一个动态链表 # include # define NULL 0 #define LEN sizeof(struct student) st

34、ruct student long num; float score; struct student * next; ; int n;,9.5.4 对动态链表的操作,首指针,数 据 指 针,数 据 指 针,数 据 指 针,数 据 NULL,struct student * creat(void) struct student *head,*p1,*p2; n=0; p1=p2=(struct student *) malloc(LEN); scanf(“%ld,%f”,num score,next,p1,p2,head,struct student * creat(void) struct s

35、tudent *head,*p1,*p2; n=0; p1=p2=(struct student *) malloc(LEN); scanf(“%ld,%f”,num score,next,next,num score,p1,p2,head,struct student * creat(void) struct student *head,*p1,*p2; n=0; p1=p2=(struct student *) malloc(LEN); scanf(“%ld,%f”,num score,next,next,num score,p1,p2,head,struct student * crea

36、t(void) struct student *head,*p1,*p2; n=0; p1=p2=(struct student *) malloc(LEN); scanf(“%ld,%f”,num score,next,next,next,num score,num score,p2,p1,head,struct student * creat(void) struct student *head,*p1,*p2; n=0; p1=p2=(struct student *) malloc(LEN); scanf(“%ld,%f”,num score,next,next,next,num sc

37、ore,num score,p1,head,p2,2、输出链表 void print(struct student *head) struct student * p; p=head; if(head!=NULL) do printf(“%ld %5.1f”, p-num, p-score); p=p-next; while(p!=NULL); ,num score,next,next,next,num score,num score,head,p,2、输出链表 void print(struct student *head) struct student * p; p=head; if(he

38、ad!=NULL) do printf(“%ld %5.1f”, p-num, p-score); p=p-next; while(p!=NULL); ,num score,next,next,next,num score,num score,head,p,3、对链表的删除 struct student *del(struct student *head,long num) struct student *p1,*p2; if(head=NULL) printf(“list null!n”);goto end; p1=head; while(num!=p1 -num ,num score,ne

39、xt,next,next,num score,num score,head,p2,p1,4、对链表的插入,struct student *insert(struct student *head,struct student *stud) struct student *p0,*p1,*p2; p1=head; p0=stud; if(head=NULL) head=p0;p0 -next=NULL; else while(p0 -nump1 -num),1、有以下结构类型说明和变量定义,且如下图所示,其中指针p指向变量a,指针q指向变量b,不能把节点b连接到节点a之后的语句是_. struct

40、 node char data; struct node *next; a,b,*p=,a,b,data,next,data,next,p,q,2、若有以下定义: struct link int data; struct link *next; a,b,c,*p,*q; 且变量a和b之间已有如上图所示的链表结构。指针p指向变量a,指针q指向变量c,则能够把c插入a和b之间形成新的链表的语句组是_. A) a.next=c; c.next=b; B) p.next=q; q.next=p.next; C) p -next=,a,b,data,next,data,next,p,q,data,nex

41、t,c,3、若已建立如下图所示的单向链表结构,并且该链表结构中,指针p和s分别指向图中所示节点,则不能将s所指的节点插入到链表末尾来构成单向链表的语句是_. A) p=p-next; s-next=p; p-next=s; B) p=p-next; s-next=p-next; p-next=s; C) s-next=NULL; p=p-next; p-next=s; D) p=(*p).next; (*s).next=(*p).next; (*p).next=s;,p,data,next,E,F,0,G,s,4、有如下结构说明和变量定义,指针p、q、r分别指向一个链表中的三个连续结点,如下图

42、所示: struct node int data; struct node *next; 现要将q和r所指结点的先后位置交换,同时要保持链表的连续,以下错误的程序是_. A) r-next=q; q-next=r-next; p-next=r; B) q-next=r-next; p-next=r; r-next=q; C) p-next=r; q-next=r-next; r-next=q; D) q-next=r-next;r-next=q;p-next=r;,data,next,data,next,data,next,p,q,r,5、设有以下定义 struct ss int info; struct ss *link;x,y,z; 且已建立如下图所示的链表结构: 请写出删除结点y的赋值语句_。,x.link=&z,x,data,next,data,next,data,next,y,z,head,data,next,data,next,data,next,6、现有如上图所示的存储结构,其中每个节点含有两个域:data是指向字符串的指针域,next是指向节点的指针域。请填空完成此结构的类型定义和说明。 struct link _; _; * head;,char *data;,struct link *next;,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1