第8章用户自定义数据类型.ppt
第八章 用户自定义数据类型,8.1 结构体 结构体是一种构造数据类型。用途:把相关的不同类型的数据组织成一个整体用户根据需要自定义数据类型。结构体类型定义:,struct 结构体名 类型标识符 成员名;类型标识符 成员名;.;,成员类型可以是基本型或构造型,struct是关键字,不能省略,合法标识符可省:无名结构体,此处分号;不能少,例 struct point double x;double y;struct point A;,结构体变量的定义:常用形式:先定义结构体类型,再定义结构体变量一般形式:,struct 结构体名 类型标识符 成员名;类型标识符 成员名;.;struct 结构体名 变量名列表;,说明结构体类型与结构体变量概念不同类型:不分配内存;变量:分配内存类型:不能赋值、存取、运算;变量:可以结构体类型可嵌套定义。结构体成员名与程序中变量名可相同,不会混淆结构体类型及变量的作用域与生存期,例 struct point double x;double y;struct triangle struct point A;struct point B;struct point C;float cir;,例 struct student int num;char name20;int score3;s1=1,”Zhang San”,80,90,100,s2;,2字节,1字节,结构体类型定义描述结构的组织形式,不分配内存,num,s1,name0,2字节,2字节,2字节,score1,score0,score2,.,.,name19,低地址,高地址,图 8-1 结构体变量s1的存储结构,结构体变量的引用引用规则 结构体变量不能整体引用,只能引用变量成员,可以将一个结构体变量赋值给另一个结构体变量结构体嵌套时逐级引用,成员(分量)运算符优先级:1结合性:从左向右,引用方式:结构体变量名.成员名,结构体变量的初始化常用形式:,struct 结构体名 类型标识符 成员名;类型标识符 成员名;.;struct 结构体名 结构体变量=初始数据;,结构体变量的引用,例/*参考程序 8-2.c*/#include struct student int num;char name20;int score3;void main()sturct student s1;int i,average;printf(“Input number:n”);scanf(“%d”,定义变量后,可引用成员变量的值或地址。,结构体数组结构体数组的定义三种形式:,结构体数组应用举例,例/*参考程序 8-3.c*/#include#define N 3 struct stu int num;char name20;int score4;void main()int i,k,max;struct stu sN;printf(“Input data:n”);for(i=0;iN;i+)scanf(“%d%s%d%d%d”,结构体数组应用举例,si.score3=(si.score0+si.score1+si.score2)/3;printf(“nAverage:”);for(i=0;imax)k=i;max=si.score3;printf(“n The top student:”);printf(“%d,%s,%d,%d,%d,average:%dn”,sk.name,sk.score0,sk.score1,sk.score2,sk.score3);,结构体和指针指向结构体变量的指针定义形式:struct 结构体名*结构体指针名;例 struct student*p;,使用结构体指针变量引用成员形式,存放结构体变量在内存的起始地址,参考源程序8-4.c,#include#define N 3 struct stu int num;char name20;int score4;void main()int i,k,max;struct stu sN,*p;printf(“Input data:n”);for(p=s;pnum,p-name,p-score3=(p-score0+p-score1+p-score2)/3;printf(“nAverage:”);for(p=s;pscore3);P=s;max=p-score3;k=0;for(p=s+1;pscore3max)k=p-s;max=p-score3;p=s+k;printf(“n The top student:”);printf(“%d,%s,%d,%d,%d,average:%dn”,p-num,p-name,p-score0,p-score1,p-score2);,struct data/*定义结构体*/int a,b,c;void main()void func(struct data);struct data arg;/*定义结构体变量,即实参*/arg.a=27;arg.b=3;arg.c=arg.a+arg.b;printf(arg.a=%d arg.b=%d arg.c=%dn,arg.a,arg.b,arg.c);printf(Call Func().n);func(arg);/*将实参传给函数func,传变量名*/printf(arg.a=%d arg.b=%d arg.c=%dn,arg.a,arg.b,arg.c);void func(struct data parm)/*通过形参 parm 能改变实参 arg 吗?*/parm.a=18;parm.b=5;parm.c=parm.a*parm.b;printf(parm.a=%d parm.b=%d parm.c=%dn,parm.a,parm.b,parm.c);printf(Return.n);,copy,【例】用结构体变量(变量名)作函数参数,struct data/*定义结构体*/int a,b,c;void main()void func(struct data*);struct data arg;/*定义结构体变量,即实参*/arg.a=27;arg.b=3;arg.c=arg.a+arg.b;printf(arg.a=%d arg.b=%d arg.c=%dn,arg.a,arg.b,arg.c);printf(Call Func().n);func(,【例】用结构体指针变量(变量地址)作函数参数,8.2 共用体构造数据类型,有的书上翻译为联合(体)用途:允许几个不同类型的变量共占一段内存(起始地址相同且共用部分或全部内存单元)共用体类型定义定义形式:,union 共用体名 类型标识符 成员名;类型标识符 成员名;.;,例 union data int i;char ch;float f;,类型定义不分配内存,最终占用4个字节,形式一:union data int i;char ch;float f;a,b;,形式二:(最常用)union data int i;char ch;float f;union data a,b,c,*p,d3;,形式三:(无名)union int i;char ch;float f;a,b,c;,共用体变量的定义,共用体变量定义分配内存,长度=最长成员所占字节数,共用体变量任何时刻只有一个成员存在,共用体变量引用引用方式:(同结构体),引用规则不能引用共用体变量,只能引用其成员,共用体变量中起作用的成员是最后一次存放的成员,不能在定义共用体变量时初始化,可以用一个共用体变量为另一个变量赋值,【例】将一个整数按字节输出,运行结果:i=24897ch0=A,ch1=a,void main()union int_char int i;char ch2;x;x.i=24897;printf(i=%dn,x.i);printf(ch0=%c,ch1=%cn,x.ch0,x.ch1);,例8-6:体会共用体各成员变量的存储方式(分析共用体最好画出各成员的存储示意图),8.3 枚举特点:该类型数据的取值范围有限,且所有可能的值均由用户在定义类型时一一列举出来。枚举类型定义,enum weekday sun,mon,tue,wed,thu,fri,sat;,enum weekday workday,week_end;,枚举变量定义,workday=mon;week_end=sun;,enum sun,mon,tue,wed,thu,fri,sat workday,week_end;,枚举元素,sun=0;mon=1;(),说明:1.在C编译中,对枚举元素作为常量来处理。,2.枚举元素是有值的,按定义时的顺序使它们为enum weekday sun,mon,tue,wed,thu,fri,sat;sun sat 依次为:0,1,2,3,4,5,6enum weekday sun,mon=8,tue,wed,thu=100,fri,sat;sun sat 依次为:0,8,9,10,100,101,102,3.枚举值可以用来作判断比较。,if(workday=mon),原因:常量不能再被赋值,参考源程序8-7.c,#include void main()enum monJan=1,Feb,Mar,Apr,May mon1,mon2,mon3;enum mon*pm;pm=,用typedef定义类型功能:用自定义名字为已有数据类型命名类型定义简单形式:typedef type my_name;,类型定义语句关键字,已有数据类型名,用户定义的类型名,说明:1.typedef 没有创造新数据类型2.typedef 是定义类型,不能定义变量3.typedef 与 define 不同,define typedef预编译时处理 编译时处理简单字符置换 为已有类型命名,typedef定义类型步骤按定义变量或数组的方法先定义变量或数组,如:int i;将变量名换成新类型名 如 int INTEGER;最前面加typedef 如 typedef int INTEGER;用新类型名定义变量 如 INTEGER i,j;,类型定义可嵌套,例 typedef struct club char name20;int size;int year;GROUP;typedef GROUP*PG;PG pclub;,GROUP*pclub;struct club*pclub;,GROUP为结构体类型PG为指向GROUP的指针类型,8.4 结构体应用链表处理单向链表存放数据元素的结点包括两个域用途:数据域(data)和指针域或链域(next)单向链表表示(表示NULL),定义:Struct Ai int a;struct Ai*next;,建立动态链表创建结点:malloc 与 calloc 函数,malloc 函数原型:int*malloc(unsigned int size)功能:在内存中动态分配size个连续空间 返值:正常,返回空间地址;出错,为NULLcallcc 函数原型:int*calloc(unsigned n,unsigned int size)功能:在内存分配N个连续长度为size的空间返值:正常,返回空间地址;出错,为NULL,节点链接到链表,新节点链接到链表末尾,链表的插入,插入节点到头节点之前,插入节点到链表中间,链表的删除(1),BEGIN IF(待删除节点为头节点)head=head-next;ELSE找到目标节点,并让prev指向待删除节点的前导节点;if(prve!=NULL)pdel=prev-next;prev-next=pdel-next;free(pdel);else print 没有找到要删除的节点;ENDIF return(head);END,链表的删除(2),/*参考源程序8-10*/#include”8-8-1.c”#include struct Ai*findprev(struct Ai*head,int a)/*从第2个开始查找*/struct Ai*prev,*pdel;prev=head;pdel=head-next;while(pdel-a!=a,链表的删除(3),/*参考源程序8-10*/struct Ai*delete(struct Ai*head,int a)struct Ai*prev,*pdel;if(head-a=a)head=head-next;printf(“The first node is deleted.n”);else if(prev=findprev(head,a)!=NULL)pdel-next=pdel-next;free(p);printf(“Node(which number is%d)is deleted.n”,a);else printf(“Node(which number is%d)is not found.n”,a);return(head);,链表的删除(4),/*参考源程序7-9*/void main()struct Ai*head,*new,*p;int n=0;int a;head=create();printf(“Input data for the node to be deleted:n”);scanf(“%d”,8.5 为已有数据类型创建新类型名(*)功能:用自定义名字为已有数据类型命名类型定义简单形式:typedef type my_name;,类型定义语句关键字,已有数据类型名,用户定义的类型名,说明:1.typedef 没有创造新数据类型2.typedef 是定义类型,不能定义变量3.typedef 与 define 不同,define typedef预编译时处理 编译时处理简单字符置换 为已有类型命名,typedef定义类型步骤 按定义变量或数组的方法先定义变量或数组,如:int i;将变量名换成新类型名 如 int INTEGER;最前面加typedef 如 typedef int INTEGER;用新类型名定义变量 如 INTEGER i,j;,类型定义可嵌套,例 typedef struct club char name20;int size;int year;GROUP;typedef GROUP*PG;PG pclub;,GROUP*pclub;struct club*pclub;,GROUP为结构体类型PG为指向GROUP的指针类型,The End,