1、第10章 结构体,结构体变量结构体数组结构体指针用指针处理链表共用体和枚举型自定义类型重点: 1. 掌握结构体的概念和结构体成员的三种用法: 结构变量.成员 (*结构指针变量).成员 结构指针变量-成员 2. 了解共用体和枚举的概念和特点,第10章 结构体,组合的数据类型结构体类型。在实际问题中,经常需要将一组不同类型的数据作为一个整体来处理。例:学生学籍管理。学生的学号、姓名、年龄、住址、考试成绩等数据与某一学生紧密联系,不应分开处理。但它们数据类型不同,用已学习过的数据类型不能处理。结构体类型用来处理联系紧密但数据类型不一致的一组数据。,11.1 结构体变量,一、结构体类型的定义 stru
2、ct 结构体名 struct 结构体名 类型标识符 成员1; 成员表列; 类型标识符 成员2; 类型标识符 成员n; ;其中: struct结构类型关键字 结构类型名标识符。,例:反映学生基本情况的结构类型 struct student int num; char name20; char sex6; int age; char addr40; float score; ; /*分号不能省略*/ 结构体类型是一种新的数据类型,新类型名为: struct 结构体名称 例: struct student结构体类型的地位和作用与int、float等相同,可用它定义变量。,定义了一个名为student
3、的结构体类型,其中包含六个成员,分别是:学号、姓名、性别、年龄、住址和一门课的考试成绩。,二、结构体变量的定义和使用,1. 结构体变量的定义先定义结构类型、再定义结构变量 如:用结构类型struct student定义结构体变量 struct student stu1,stu2;定义结构类型的同时,定义结构变量 如:struct date int year; int month; int day; d1, d2, d3;,注意:结构类型与结构变量是两个不同的概念,如同int类型与int型变量的区别一样。 结构类型是用户定义的数据类型,可以有多种。P228页,定义结构变量的第三种方法不要使用。2
4、. 结构变量的引用 结构变量包含若干个不同类型的成员,只能引用结构变量的成员,不能引用整个结构变量。访问结构成员的一般形式: 结构变量名.成员名 例如: stu1. num、stu1.name, d1.year、 d1.day,“.”为结构成员运算符,优先级最高。可以把 “结构变量.成员 ” 看作一个整体,与普通变量一样使用。如: stu1. num=1; gets(stu.name); scanf(“%f”, ,结构体类型嵌套 结构体类型中可包含已定义的结构体类型。例:职工信息 struct clerk int num; char name20; struct date bd; ;变量定义:
5、如: struct clerk p1, p2;成员引用:p1.num, p1.name, p1.bd.year, p1.bd.month, p1.bd.day初始化:struct clerk p=12, “Li Si”, 1980, 6, 15;,特别注意:结构体类型和变量也有全局和局部之分 (1). 定义在所有函数之外的结构体类型(变量)称为全局(或外部)结构体类型(变量)。 (2). 定义在函数内部的结构体类型(变量)称为局部(或内部)结构体类型(变量)。 (3). 结构体类型一般定义为全局的, 定义位置一般在主函数之前。 (4).结构体变量初始化时,初值类型应与对应成员的数据类型一致,否
6、则会出错。,11.2 结构体数组,结构数组的每一个元素,都是结构类型数据,均包含结构类型中的所有成员。一、结构体数组的定义 和结构体变量的定义方法相同,把变量换成数组即可。例: 定义结构体类型的同时,定义结构体数组: struct clerk int num; char name20; struct date bd; a50; struct clerk b30;,结构体数组相当于一列具有相同类型的结构体变量。,二、结构体数组的初始化 对结构体数组每个元素的每个成员赋初值。按元素赋值。如: struct clerk b3= 101,“张三”,1980,9,20, 102,“李四”,1980,8,
7、15, 103,“王五”,1980,3,10 ;三、结构体数组的引用 结构体数组元素引用的一般方法: 结构体数组名下标.成员名例: struct clerk a5; gets(a0.name); a0.bd.day=25; scanf(“%d”,11.3 结构体指针,一、指向结构体变量的指针 结构体变量所占内存的首地址称为结构变量的指针结构体指针变量的定义 struct 结构体名称 *结构体指针变量名;例1:struct clerk int num; char name20; struct date bd; a, *pa;例2: struct clerk b, *pb;注意:结构体指针变量必须
8、先赋值后使用。,结构体指针变量赋初值 将结构体变量的首地址赋给指针变量,如: struct clerk a, *pa=,结构体成员的三种用法,结构体变量.成员(*结构体指针变量).成员结构体变量-成员本章的重点就是结构体成员的三种用法,熟练掌握这三种用法,就掌握了本章的主要内容!,二、指向结构体数组的指针,结构体数组的首地址,称为结构体数组的指针。例: struct clerk int num; char name20; struct date bd; a3, *p; 或: struct clerk a3, *p; p=a;则:pa0; p+1a1; p+2a2.通过指针访问数组元素的成员:
9、p-num=10; a0.num=10; scanf(“%s”,p-name); scanf(“%s”,a0.name); 如果: p+; 则 pa1; p-num=10; a1.num=10;,应用举例:利用指向结构体数组的指针输出结构体数组。,struct clerk int num; char name20; int age; char addr40;main()struct clerk *p, a3= 101,“张三”,26,“Beijing”, 102,“李四”,25,“Taiyuan”, 103,“王五”,27,“Shanghai” ; int i; for(i=0, p=a; i
10、num, p-name, p-age, p-addr);,三、结构体数据作函数参数,结构体变量作函数参数struct clerk int num; char name20; int age; char addr40;void f(struct clerk a);main()struct clerk a= 101,“张三”,26,“Beijing”; f(a);void f(struct clerk b) printf(%d,%s,%d,%sn, b.num, b.name, b.age,b.addr);,结构体变量作函数参数数据传递方式是赋值传递(单向值传递),实参把它每一个的成员的值依次传给
11、形参,运行时间与存贮空间的开销很大,程序运行效率很低。实际应用中,一般使用结构体指针作函数参数。,结构体指针作函数参数:赋地址传递。struct clerk int num; char name20; int age; char addr40;void output(struct clerk *p);main()struct clerk *p, a3= 101,“张三”,26,“Beijing”, 102,“李四”,25,“Taiyuan”, 103,“王五”,27,“Shanghai” ; p=a; output(p);,void output(struct clerk *p) int i;
12、 for(i=0; inum,p-name,p-age,p-addr); return; 输出结果: 101,张三,26,Beijing 102,李四,25,Taiyuan 103,王五,27,Shanghai,11.4 用指针处理链表,C 语言中,数组长度是固定的,数据的插入和删除操作比较复杂。实际问题中需要处理可变长度的数据,用数组不能处理。链表是一种动态存贮的数据结构,存储空间是在程序运行过程中根据需要向系统动态申请的,其存储单元也不连续。数据的数量及顺度关系可根据需要动态改变,数据的插入和删除操作比较简单。,链表的存贮结构 链表的每个元素称为一个“结点”。链表的存贮单元不连续,需要知道
13、每个结点的地址。 (1)每个结点由2个域组成:1)数据域存储本结点的数据信息。2)指针域指向下一个结点的地址。 (2)头指针变量head指向链表的首结点。 (3)尾结点的指针域为“NULL(空)”,表示链表结束。 链表的实现,必须用到结构体指针。,链表结构的定义,struct student int num; char name20; struct student *next; ; next为struct student类型指针变量,指向下一个结点。结点变量或指针变量的定义:struct student node,*head;指针head可以存放学生结点的地址。,动态内存处理函数,(1). v
14、oid *malloc(unsigned int size); malloc在内存的动态存储区中分配一个长度为size的连续存储空间。分配成功时,返回值为指向所分配内存空间的首地址的指针(类型为void);若未成功,则返回空指针(NULL).例如: int *p; p=(int *)malloc(8); 在内存的动态存储区中分配长度为8字节的存贮空间,并把返回的指针类型强制转化为整型(可存贮4个整型数)。,(2). void *calloc(unsigned n,unsigned size);在内存的动态存储区中分配n个长度为size 的连续存贮空间。若分配成功,返回值为指向所分配空间起始地址
15、的指针;不成功返回NULL。 (3). void free(void *p); 释放由指针变量p所指示的内存区域。例: free(p); free函数将用malloc和calloc分配的内存空间交还系统。,对链表的基本操作,建立:从无到有地建立起一个链表。查找:按给定的检索条件,查找某个结点。插入:在结点ki-1与ki之间插入一个新的结点k。 删除:删除结点ki,使链表的长度减1。输出:全部或部分地输出链表中结点的数据项。链表是数据结构中的一种重要算法。以下简单介绍链表插入和删除的基本思路。,插入元素在第i个元素之前插入,先找到第i-1个结点,Status ListInsert_L(LinkL
16、ist ,e,s,p-next=s,(2),(3),p,s-next=p-next,a,(1),b,删除元素,Status ListDelete_L(LinkList ,11.5 共用体和枚举型简介,一、 共用体 使几个不同的变量占用同一段内存空间的结构称为共用体,也叫联合体,是一种构造的数据类型。特点:几个不同类型的变量共用同一段内存,相互覆盖。共用体类型定义 union 共用体名 类型标识符 成员1; 类型标识符 成员2; . 类型标识符 成员n; ;,union 共用体名 成员列 ;,共用体变量的定义:与结构体类似。,例 union data int i; char ch; float
17、f; ;,方法一: 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 data int i; char ch; float f; ; union data a,*p=,共用体的特点,共用体变量任何时刻都只有一个
18、成员存在,它的长度=最长成员所占字节数系统采用覆盖技术,使共用体成员共享内存。在某一时刻,起作用的总是最后一次存入的成员值。 例如: 执行 a.i=1; a.ch=c; a.f=3.14; a.f是有效的成员。由于所有成员共享同一内存空间,故共用体变量与其成员的地址相同。例如: aa.ia.cha.f。,二、枚举类型,有时候,变量的值被限定在一定的范围内,如一周7天,人的性别等。1枚举类型的定义 enum 枚举类型名 取值表;例:enum week Sun,Mon,Tue,Wed,Thu,Fri,Sat;枚举变量的定义与结构变量类似(1)间接定义 例:enum week w1;(2)直接定义
19、例:enum week Sun,Mon,Tue,Wed,Thu,Fri,Sat w1,w2;3枚举变量的使用 上例中,变量w1和w2只能在Sun,Mon,Tue,Wed,Thu,Fri,Sat中取值。例如: w1=Sun; w2=Sat;,4说明(1) 枚举型仅适应于取值有限的数据。 例:上例中周天,有7个值。(2) 枚举元素的值为整型常量,其值为定义时的顺序号。 例:上例中的Sun=0、Mon=1、Sat=6(3) 枚举元素的值可以在定义时由程序指定。 例:enum week Sun=, Mon,Tue, Wed, Thu, Fri, Sat; 则Sun=,Mon=,从Tue=2开始,依次增
20、。(4) 枚举型变量的输出按“%d”型格式。如: printf(“%d,%dn”, w1,w2); /*输出结果:0, 6*/,11.7 自定义类型,语言可以使用typedef定义已有类型的别名。该别名与标准类型名一样,可用来定义变量。定义已有类型别名的方法如下: typedef 类型说明符 新类型名;例: typedef int INTEGER; /*给int定义别名 INTEGER;*/ typedef float REAL; /*给float定义别名REAL;*/可以用新的别名定义变量: INTEGER a,b,c; int a,b,c; REAL f1,f2; float f1,f2;
21、,在程序设计中,利用自定义类型可以把一个较复杂的数据类型定义为一个新的较简单的类型,使程序更加简洁。例: struct date int year; int month; int day; ; typedef struct date DATE; DATE d1,d2,d3;特别说明:1. typedef 没有创造新数据类型,只是给已有类型取了别名。2. typedef 可以给类型定义别名,不能定义变量。,结构体小结,一、结构体类型的定义。二、结构体变量的定义和使用。三、结构体数组的定义和使用。四、结构体指针变量的定义和使用。五、结构体指针处理链表。六、共用体和枚举类型。七、自定义类型。重点:1. 掌握结构体的概念和结构体成员的三种用法: 结构变量.成员 (*结构指针变量).成员 结构指针变量-成员 2. 了解共用体和枚举的概念和特点。,例题和作业,例:P235 11.3, P241 11.6作业 P263:11.1 11.2 11.3 11.4 11.6,