第09章复杂数据类型.ppt

上传人:本田雅阁 文档编号:3417879 上传时间:2019-08-23 格式:PPT 页数:57 大小:1.33MB
返回 下载 相关 举报
第09章复杂数据类型.ppt_第1页
第1页 / 共57页
第09章复杂数据类型.ppt_第2页
第2页 / 共57页
第09章复杂数据类型.ppt_第3页
第3页 / 共57页
第09章复杂数据类型.ppt_第4页
第4页 / 共57页
第09章复杂数据类型.ppt_第5页
第5页 / 共57页
点击查看更多>>
资源描述

《第09章复杂数据类型.ppt》由会员分享,可在线阅读,更多相关《第09章复杂数据类型.ppt(57页珍藏版)》请在三一文库上搜索。

1、,只能定义单一的数据类型,反映事物单一属性,第9章:复杂数据类型,学习的意义,如定义学生成绩: float score;,能定义复杂的数据类型,反映事物多个属性,如定义学生信息: struct STU char no9; /学号 char name12; /姓名 char sex; /性别 float score; /成绩 student;,复杂数据类型丰富了C语言对数据信息的处理能力。 离开了复杂数据类型,很多信息的描述是无法进行定义,更无法进行处理的。 计算机中的信息表示更多是由复杂数据类型来定义的,象数据结构课程中的链表、树、图等 可以更好地理解数据库中的记录的含义, 为C+语言中类的概

2、念的理解提供了帮助。,9.1 结构体,结构体是一种构造数据类型 用途:把不同类型的数据组合成一个整体-自定义数据类型 引入结构体的好处:加强数据项之间的联系,如学生的基本信息,包括学号、姓名、性别、年龄、班级、成绩等数据项。这些数据项描述了一个学生的几个不同侧面。,独立的变量表示:,结构体变量表示:,char no9; /学号 char name20; /姓名 char sex; /性别 unsigned int age; /年龄 unsigned int classno; /班级 float grade; /成绩,1、结构体类型的定义,struct 结构体类型名 数据类型名1 成员名1; 数

3、据类型名2 成员名2; 数据类型名n 成员名n; ;,struct是关键字, 不能省略,合法标识符 可省:无名结构体,成员类型可以是 基本型或构造型,以分号;结尾,例1: struct Student_Info char no9; /学号 char name20; /姓名 char sex; /性别 unsigned int age; /年龄 unsigned int classno; /班级 float grade; /成绩 ;,例2: struct Date int year; /年 int month; /月 int day; /日 ;,在结构体中数据类型相同的成员,既可逐个、逐行分别定

4、义,也可合并成一行定义,就象一次定义多个变量一样。,struct Student_Info char no9; /学号 char name20; /姓名 char sex; /性别 unsigned int age; /年龄 unsigned int classno; /班级 float grade; /成绩 ;,struct Student_Info char no9, name20, sex; unsigned int age, classno; float grade; ;,struct Date int year; /年 int month; /月 int day; /日 ;,stru

5、ct Date int year, month, day; ;,注意:结构类型只是用户自定义的一种数据类型,用来定义描述结构的组织形式,不分配内存,只有用它来定义某个变量时,才会为该变量分配结构类型所需要大小的内存单元。所占内存的大小是它所包含的成员所占内存大小之和。,2、结构体变量的定义和引用,struct 结构体类型名 数据类型名1 成员名1; 数据类型名n 成员名n; ; struct 结构体类型名 变量名列表;,结构体变量的定义,间接定义法:先定义结构类型,再定义结构变量,struct student;,struct Student_Info student1, student2;,一

6、次定义多个结构体类型变量,定义指向结构体类型的指针变量,struct Student_Info *pstu;,间接定义法中几种错误的结构体变量的定义方法,没有结构体类型名,Student_Info student;,缺省struct关键字,struct Point p; struct Point int x, y; ;,结构类型Point定义在后,2、结构体变量的定义和引用,struct 结构体类型名 数据类型名1 成员名1; 数据类型名n 成员名n; 变量名列表;,结构体变量的定义,直接定义法:定义结构体类型的同时定义结构体变量,struct Student_Info char no9; /

7、学号 char name20; /姓名 char sex; /性别 unsigned int age; /年龄 unsigned int classno; /班级 float grade; /成绩 student1, student2;,struct char no9; /学号 char name20; /姓名 char sex; /性别 unsigned int age; /年龄 unsigned int classno; /班级 float grade; /成绩 student1, student2;,或,无名结构体定义,变量只能一次,几点说明:,(1) 结构体类型与结构体变量概念不同 类

8、型: 不分配内存; 变量: 分配内存 类型: 不能赋值、存取、运算; 变量: 可以,(2) 结构体可以嵌套,struct Point int x, y; ; struct Img int tag; struct Img *pimg; /正确,可以包含自身类型的指针 struct Img img; /错误,不能包含自身类型的变量 ;,(3) 结构类型中的成员名,可以与程序中的变量同名,它们代表不同的对象,互不干扰,struct Student_Info student; char name20;,(4) 结构体类型及变量的作用域和生存期与基本类型变量相同,结构体变量的引用,引用规则,结构体变量不

9、能整体引用,只能引用变量成员,引用方式:,结构体变量名.成员名 /非指针型结构体变量的引用,可以将一个结构体变量赋值给另一个结构体变量,结构体嵌套时逐级引用,结构体指针-成员名 或 (*结构体指针).成员名 /指针型结构体变量的引用,成员(分量)运算符 结合性:从左向右,成员(分量)运算符 结合性:从左向右,结构体变量名.成员名.子成员名最低级子成员名,注意:在利用指针引用结构体成员时,-和之间不能有空格。,3、结构体变量的赋值,结构体变量初始化赋值,先定义结构体类型,再定义结构体变量时赋初值,注意:赋初值时, 中间的数据顺序必须与结构体成员的定义顺序一致,否则就会出现混乱。,struct S

10、tudent_Info stu = “20020306“, “ZhangMing“, M, 18, 1, 90;,struct Student_Info stu = 18, “ZhangMing“, M, “20020306“, 1, 90;,3、结构体变量的赋值,结构体变量初始化赋值,定义结构体类型的同时,定义结构体变量并赋初值,struct Date int year, month, day; birthday = 1986, 12, 10;,struct int year, month, day; birthday = 1986, 12, 10;,或,struct Student_Inf

11、o char no9; /学号 char name20; /姓名 char sex; /性别 unsigned int age; /年龄 unsigned int classno; /班级 float grade; /成绩 student = “20020306“, “ZhangMing“, M, 18, 1, 90;,strcpy (stu1.no, stu.no); strcpy (stu1.name, stu.name); stu1.sex = stu.sex; stu1.age = stu.age; stu1.classno = stu.classno; stu1.grade = st

12、u.grade;,struct Student_Info stu; strcpy (stu.no, “20020306“); strcpy (stu.name, “ZhangMing“); stu.sex = M; stu.age = 18; stu.classno = 1; stu.grade = 90; struct Student_Info stu1; stu1 = stu;,3、结构体变量的赋值,结构体变量在程序中赋值,如果在定义结构体变量时并未对其赋初始值,那么在程序中要对它赋值的话,就只能一个一个地对其成员逐一赋值,或者用已赋值的同类型的结构体变量对它赋值,memcpy (,【例】

13、 计算学生5门课的平均成绩,最高分和最低分。,#include struct score float grade5; float avegrade, maxgrade, mingrade; ; void main ( ) int i; struct score m; printf (“input the grade of five course:n“); for (i = 0; i 5; i+) /输入5门课的成绩 scanf (“%f“, ,m.avegrade = 0; m.maxgrade = m.grade0; m.mingrade = m.grade0; for (i = 0; i

14、m.maxgrade) ? m.gradei : m.maxgrade; m.mingrade = (m.gradei m.mingrade) ? m.gradei : m.mingrade; m.avegrade /= 5; printf (“avegrade = %5.1f maxgrade = %5.1f mingrade = %5.1fn“, m.avegrade, m.maxgrade, m.mingrade); ,运行结果(设5门课的成绩为:75 80 86 90 68 ): avegrade = 79.8 maxgrade = 90.0 mingrade = 68.0,&m.gr

15、adei,注: .和 同优先级,具有左结合性,高于&的优先级,4、简化结构体类型名,利用typedef语句为结构体类型起别名,这样可使定义结构体类型的变量显得更为简洁,同时也增加程序的易读性。,typedef语句的格式为:,typedef 类型名 类型名的别名;,必须是已经定义的数据类型名或C语言提供的基本类型名,必须是合法的标识符,通常用大写字母来表示,必须以分号结尾,typedef int INTEGER; /INTEGER是别名 typedef char * STRING /STRING是别名 struct teacher_info char name20, char sex, unit

16、30; unsigned int age, workyears; float salary; ; typedef struct teacher_info TEACHER; /TEACHER是别名 INTEGER a; /相当于int a; STRING str; /相当于char *str; TEACHER t; /相当于struct teacher_info t;,typedef char ARRAY81; /ARRAY是别名 ARRAY str; /相当于char str81;,5、结构体数组,结构体数组的每一个元素都是具有相同结构体类型的下标结构变量。,结构体数组的定义,三种形式:,形式

17、一: struct Student_Info char no9, name20, sex; unsigned int age, classno; float grade; ; struct Student_Info stu10;,形式二: struct Student_Info char no9, name20, sex; unsigned int age, classno; float grade; stu10;,形式三: struct char no9, name20, sex; unsigned int age, classno; float grade; stu10;,结构体数组与二维

18、表的对应关系,结构体数组就相当于一张二维表,一个表的框架对应的就是某种结构体类型,表中的每一列对应该结构体的成员,表中每一行信息对应该结构体数组元素各成员的具体值,表中的行数对应结构体数组的大小。,结构体类型Student_Info,struct Student_Info char no9; char name20; char sex; unsigned int age; unsigned int classno; float grade; stu10;,结构体数组的初始化,初始化的格式为:,struct 结构体类型名 ; struct 结构体类型名 结构体数组size = 初值表1, , 初

19、值表n;,struct 结构体类型名 结构体数组size = 初值表1,初值表2, , 初值表n;,或,结构体数组的引用,引用格式为:,结构体数组名下标.成员名;,struct Student_Info char no9; char name20; char sex; unsigned int age; unsigned int classno; float grade; stu10;,strcpy (stu0.name, “WangFei“);,stu1.grade+;,printf (“%s“, stu0.name);,【例】统计侯选人选票。,#include #include struc

20、t person char name20; /候选人姓名 int count; /得票数 leader3 = “Li“, 0, “Zhang“, 0, “Wang“, 0 ;,void main ( ) int i, j; char leader_name20; while (1) /统计候选人得票数 scanf (“%s“, leader_name); /输入候选人姓名 if (strcmp(leader_name, “0“) = 0) /输入为“0“结束 break; for (j = 0; j 3; j+) /比较是否为合法候选人 if (strcmp(leader_name,leade

21、rj.name) = 0) /合法 leaderj.count+; /得票数加1 for (i = 0; i 3; i+) /显示后选人得票数 printf (“%5s : %dn“, leaderi.name, leaderi.count); ,9.3 线性链表,1、线性链表概述及其结构,线性表:当一组数据元素形成了“前后”关系时,我们称之为线性表,线性表在内存中的两种形式,顺序表:以数组的形式存放,元素在内存中是连续存放的,线性链表:数据元素在内存中不需要连续存放,而是通过指针将各数据单元链接起来,就象一条“链子”一样将数据单元前后元素链接起来,特点:插入或删除一个数据元素时,需要移动其它

22、数据元素,特点:插入或删除一个数据元素时,不需要移动其它数据元素,节点,实际数据链表,头节点,表示NULL,数据域,指针域,线性链表中的节点可以用一个结构体类型来定义,其形式为:,struct 节点结构体类型名 数据成员定义; struct 节点结构体类型名 *指针变量名; ;,例: struct Grade_Info int score; struct Grade_Info *next; ; typedef struct Grade_Info NODE;,2、线性链表的基本操作,基本操作有:创建、插入、删除、输出和销毁等。,链表的创建操作,含义:从无到有地建立起一个链表,即往空链表中依次插入

23、若干结点,并保持结点之间的前驱和后继关系。,基本思想:首先创建一个头节点,让头指针head和尾指针tail都指向该节点,并设置该节点的指针域为NULL(链尾标志);然后为实际数据创建一个节点,用指针pnew指向它,并将实际数据放在该节点的数据域,其指针域置为NULL;最后将该节点插入到tail所指向节点的后面,同时使tail指向pnew所指向的节点。,【例】 链表创建操作函数Create_LinkList。,NODE *Create_LinkList ( ) /创建链表 NODE *head, *tail, *pnew; int scor; head = (NODE *)malloc (siz

24、eof(NODE); /创建头节点 if (head = NULL) /创建失败,则返回 printf (“no enough memory!n“); return (NULL); head-next = NULL; /头节点的指针域置NULL tail = head; /开始时尾指针指向头节点,pnew-score = score; pnew-next = NULL; tail-next = pnew; tail = pnew; return (head); ,【例】 链表创建操作函数Create_LinkList。,input the score of students:,70,70,65

25、,65,78,78,90,95,-1,printf (“input the score of students:n“); while (1) /创建学生成绩线性链表 scanf (“%d“, ,2、线性链表的基本操作,链表的插入操作,含义:在第i个结点Ni与第i+1节点Ni+1之间插入一个新的结点N,使线性表的长度增1,且Ni与Ni+1的逻辑关系发生如下变化:插入前,Ni是Ni+1的前驱,Ni+1是Ni的后继;插入后,新插入的结点N成为Ni的后继、Ni+1的前驱,基本思想:通过单链表的头指针head,首先找到链表的第一个结点;然后顺着结点的指针域找到第i个结点,最后将pnew指向的新结点插入到

26、第i个结点之后。插入时首先将新节点的指针域指向第i个结点的后继节点,然后再将第i个结点的指针域指向新节点。注意顺序不可颠倒。当i=0时,表示头节点。,【例】 链表插入操作函数Insert_LinkList 。,void Insert_LinkList(NODE *head, NODE *pnew, int i) NODE *p; int j; p = head; for (j = 0; j next; if (p = NULL) /表明链表中第i个节点不存在 printf (“the %d node not foundt!n“, i); return; pnew-next = p-next ;

27、 /将插入节点的指针域指向第i个节点的后继节点 p-next = pnew; /将第i个节点的指针域指向插入节点 ,假设i = 2,2、线性链表的基本操作,链表的删除操作,含义:删除链表中的第i个结点Ni,使线性表的长度减1。删除前,节点Ni-1是Ni的前驱,Ni+1是Ni的后继;删除后,结点Ni+1成为Ni-1的后继。,基本思想:通过单链表的头指针head,首先找到链表中指向第i个结点的前驱节点的指针p和指向第i个节点的指针q;然后删除第i个结点。删除时只需执行p-next = q-next即可,当然不要忘了释放节点i的内存单元。注意当i=0时,表示头节点,是不可删除的。,【例】链表删除操作

28、函数Delete_LinkList 。,void Delete_LinkList(NODE *head, int i) NODE *p,*q; int j; if (i = 0) return; /删除的是头指针,则返回 p = head; /将p指向要删除的第i个节点的前驱节点 for (j = 1; j next != NULL; j+) p = p-next; if (p-next = NULL) /表明链表中第i个节点不存在 printf (“the %d node not foundt!n“, i); return; ,假设i = 2,q = p-next; /q指向待删除的节点i

29、p-next = q-next ; /删除节点i free(q); /释放节点i的内存单元 ,2、线性链表的基本操作,链表的输出操作,含义:将链表中节点的数据域的值显示出来。如果在输出过程中,对数据进行相应的比较,则可实现对链表的检索操作。,基本思想:通过单链表的头指针head,使指针p指向实际数据链表的第一个节点,输出其数据值,接着p又指向下一个节点,输出其数据值,如此进行下去,直到尾节点的数据项输出完为止,即p为NULL为止。,void Display_LinkList(NODE *head) NODE *p; for (p = head-next; p != NULL; p = p-ne

30、xt) printf (“%d “, p-score); printf (“n“); ,【例】链表输出操作函数Display_LinkList 。,2、线性链表的基本操作,链表的销毁操作,含义:将创建的链表从内存中释放掉,达到销毁的目的,基本思想:每次删除头节点的后继节点,最后删除头节点。注意,不要以为只要删除了头节点就可以删除整个链表,要知道链表是一个节点一个节点建立起来的,所以销毁它也必须一个一个节点的删除才行。,void Free_LinkList(NODE *head) NODE *p, *q; p = head; while (p-next != NULL) q = p-next;

31、p-next = q-next; free (q); free (head); ,【例】链表销毁操作函数Free_LinkList 。,3、线性链表应用举例,【例】 建立一个学生成绩的线性链表,然后对其进行插入、删除、显示,最后销毁该链表。,#include #include struct Grade_Info int score; struct Grade_Info *next; typedef struct Grade_Info NODE; NODE *Create_LinkList ( ); void Insert_LinkList (NODE *head, NODE *pnew, in

32、t i); void Delete_LinkList (NODE *head, int i); void Display_LinkList (NODE *head); void Free_LinkList (NODE *head);,void main ( ) NODE *head, *pnew; head = Create_LinkList ( ); /创建链表 if (head = NULL) /创建失败 return; printf (“after create: “); Display_LinkList (head); /输出链表中的值 /新建一插入的节点 pnew = (NODE *

33、)malloc (sizeof(NODE); if (pnew = NULL) /创建失败,则返回 printf (“no enough memory!n“); return; pnew-score = 88; /将新节点插入节点3的后面 Insert_LinkList (head, pnew, 3);,printf (“after insert: “); Display_LinkList (head); /输出链表中的值 Delete_LinkList (head, 3); /删除链表中节点3 printf (“after delete: “); Display_LinkList (head

34、); /输出链表中的值 Free_LinkList (head); /销毁链表 ,运行结果(假设输入为:70 65 78 90 95 85 -1 ): after create:70 65 78 90 95 85 after insert:70 65 78 88 90 95 85 after delete:70 65 88 90 95 85,9.4 联合体,构造数据类型,也叫共用体 用途:使几个不同类型的变量共占一段内存(相互覆盖),1、联合体类型的定义,union 联合体类型名 数据类型名1 成员名1; 数据类型名2 成员名2; 数据类型名n 成员名n; ;,类型定义不分配内存,共占4字节

35、sizeof(union UData) = sizeof(f),联合体的大小是成员中占内存最大的成员的大小,union UData short i; char ch; float f; ;,2、联合体变量的定义和引用,联合体变量的定义,形式一: union data short i; char ch; float f; a, b;,形式二: union data short i; char ch; float f; ; union data a, b, *p, d3;,形式三: union short i; char ch; float f; a,b,c;,共用体变量任何时刻 只有一个成员存在

36、,共用体变量定义分配内存, 长度=最长成员所占字节数,联合体变量的引用,联合体变量名.成员名,联合体指针名-成员名 或 (*联合体指针名).成员名,3、联合体变量的赋值,联合体变量的初始化赋值,定义联合体变量时可以对变量赋初值,但只能对变量的第一个成员赋初值,不可象结构体变量那样对所有的成员赋初值。,union UData short i; char ch; float f; ; union UData data = 10; /10赋给成员i union UData data = A; /A赋给成员i,即i的值为65(A的ASCII码) union UData data = 10, A, 12

37、.5; /错误, 中只能有一个值 union UData data = 10; /错误,初值必须用 括起来,3、联合体变量的赋值,联合体变量在程序中赋值,定义了联合体变量以后,如果要对其赋值,则只能通过对其成员赋值,不可对其整体赋值。,具有相同联合体类型的变量之间也可以相互赋值。,union UData short i; char ch; float f; ; union UData data, *p, d10; data = 10; /错误 data = 10; /错误 data.i = 10; /正确,将10赋给data的成员i p = /正确,将12.5赋给data的成员f d0.ch

38、= A /正确,将A 赋给d0的成员ch,union UData data1 = 10, data2; data2 = data1; /正确,几点说明:,由于联合体变量的各成员共享同一地址的内存单元,所以在对其成员赋值的某一时刻,存放的和起作用的将是最后一次存入的成员值,对联合体变量的某个成员赋值时,也改变了其它成员的值,因为它们共享一个内存地址。,由于联合体变量所有成员共享同一内存空间,因此联合体变量与其各成员的地址相同。,union UData data; data.i = 10; data.ch = A; data.f = 12.5; 则data.f的值才是有效的成员的值。,union

39、UData data; data.i = 10; data.ch = A; 则data的成员i的值将变为65(A的ASCII码值)。,union UData data; 则&data与&data.i、&data.ch、&data.f均相同,【例1】 共用体成员间的相互影响。,#include void main ( ) union long L; short a; char ch; d = 0xFFF11241; printf (“d.ch = %c d.a = %X d.L = %Xn“, d.ch, d.a, d.L); d.a+; printf (“d.ch = %c d.a = %X

40、d.L = %Xn“, d.ch, d.a, d.L); ,0XFF,0XF1,0X12,0X41,运行结果: d.ch = A d.a = 1241 d.L = FFF11241,d.ch = B d.a = 1242 d.L = FFF11242,【例2】设有一个教师与学生通用的表格,教师数据有姓名、年龄、职业,教研室四项。学生有姓名、年龄、职业、班级四项。编程输入人员数据, 再以表格输出。,#include struct Stu_Tea char name10; /姓名 int age; /年龄 char job; /工作s-表示学生,t-表示教师 union int classno;

41、/学生班级号 char office10; /教师教研室名 depart; ;,void main ( ) struct Stu_Tea body2; int i; for (i = 0; i 2; i+) /输入学生或教师信息 printf (“input name,age,job and departmentn“); scanf (“%s %d %c“, bodyi.name, ,/显示输入的学生、教师信息 printf (“nametage job class/officen“); for (i = 0; i 2; i+) if (bodyi.job = s) printf (“%st%

42、3d%3c%dn“, bodyi.name, bodyi.age, bodyi.job, bodyi.depart.classno); else printf (“%st%3d %3c %sn“, bodyi.name, bodyi.age, bodyi.job, bodyi.depart.office); ,9.5 位域,对结构体或联合体中的成员访问:只能是该成员所对应的整个内存单元,如果要访问结构体或联合体中的成员所对应内存单元的若干位,则必须要将结构体或联合体中的成员定义成位域成员。,位域成员:只占有有限几位的结构体或联合体成员。位域成员是特殊的成员,它必须是整型或字符型变量(char、

43、short、int,在VC下可为long),但它可以只占有一个整型数据的某几位。,定义位域成员的方法:在定义结构体或联合体类型时,只要在成员后面加上“:位数”,,struct BitStruct char a : 4; short b : 4; unsigned long c : 7; short d : 1; word;,struct BitStruct char a : 4; short : 4; unsigned long c : 7; short d : 1; word;,匿名位域,对位域成员的引用方法与结构体或联合体成员引用方法一样,用“.”或“-”来引用这些成员。,注意:不能对位域

44、成员取地址。 例如:&word.a是错误的。,【例】位域的应用。,#include struct MyStruct unsigned char a : 1; unsigned char b : 5; unsigned short c : 10; ; union MyUnion unsigned short x; struct MyStruct y; ; void main ( ) union MyUnion m = (unsigned short)0XFFF1; printf (“m.y.a = %un“, m.y.a); printf (“m.y.b = %un“, m.y.b); prin

45、tf (“m.y.c = %un“, m.y.c); m.y.b = 0; printf (“%Xn“, m.x); ,运行结果(BC或TC下): m.y.a = 1 m.y.b = 24 m.y.c = 1023 m.x = FFC1,运行结果(VC下): m.y.a = 1 m.y.b = 24 m.y.c = 0 m.x = FFC1,注意: 在VC下,利用y.c不可读取x的高10位数据,如果对y.c的作了改变,也不会影响x的值,就好象y.c与x无关一样。 为了避免在不同编译环境下程序运行结果的不一致性,一般将位域成员的数据类型定义为同一数据类型。例如,将程序中的a和b的数据类型如果改为unsigned short,则程序在VC下运行的结果与BC或TC下都是相同的。,9.6 枚举类型变量的定义和引用,如果一个变量只有几种可能的值,可以把它定义成枚举类型。所谓“枚举”,顾名思义,就是把这种类型数据可取的值一一列举出来。一个枚举型变量取值仅限于列出值的范围。枚举数据类型通常的定义形式为:,enum 枚举类型名 枚举元素表 ;,由多个标识符组成,标识符之间用逗号分开,定义枚举类型:enum weekday sun, mon, tue, wed, thu, fri, sat;,定义枚举类型变量:enum weekday

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

当前位置:首页 > 其他


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