版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C语言程序设计第9章结构体与共用体引言C语言的数据类型分为基本数据类型和构造数据类型,我们在前面章节中学过的int、float、double等数据类型都属于“基本数据类型”,都是C语言事先规定好的数据类型,我们编程时直接使用即可。同时C语言还允许用户自定义数据类型,这称之为“构造数据类型”,如前面说过的数组。本章要学习的结构体与共用体数据类型都属于“构造数据类型”结构体结构体(structure)是不同数据类型的数据所组成的集合体,是构造类型数据。与前面我们所讲的构造类型数据数组的区别在于其中的成员可以不是同一个数据类型的。每一个结构体有一个名字,称为结构体名。所有成员都组织在该名字之下。一个结构体由若干成员组成。它是组成结构体的要素,每个成员的数据类型可以不同,也可以相同。每个成员有自己的名字,称为结构体成员名。结构体的应用为处理复杂的数据结构提供了有利的手段。特别是对处理那些数据结构比较复杂的程序提供了方便。结构体类型的定义声明一个结构体类型的一般形式为:struct结构体名{数据类型成员1的名字; 数据类型成员2的名字; 数据类型成员3的名字; ……};
表9-1某班学生成绩管理表学号性别高数英语C语言程序设计1F9085782M8976903M7643694M589276…………………………例:针对表9-1中的每个学生的信息,我们可以定义如下的结构体类型:structstudent{intsID; //学号charsSex; //性别intsMath; //高数成绩intsEng; //英语成绩intsC; //C语言程序设计成绩};
结构体变量的定义(1)先声明结构体类型再定义变量名如例9-2中,我们已经定义了一个structstudent的结构体数据类型,可以用该数据类型来定义变量,如: structstudentS1;结构体变量的定义(2)在声明结构体类型的同时定义结构体变量其定义形式为:struct结构体名{ 数据类型成员1的名字; 数据类型成员2的名字; 数据类型成员3的名字; ……}结构体变量名表;结构体变量的定义(3)直接定义结构体变量,不出现结构体名其定义形式为:struct{数据类型成员1的名字; 数据类型成员2的名字; 数据类型成员3的名字; ……}结构体变量名表;用typedef定义数据类型关键字typedef用于为系统固有的或自定义数据类型定义一个别名。数据类型的别名通常使用大写字母,但这不是强制性的,只是为了与已有数据类型相区分。如:typedefintINTEGER;为int数据类型定义了一个新名字INTEGER,则若程序中出现INTEGERa;即表示定义了一个int型的变量。也可以利用typedef为结构体数据类型定义一个别名。注意,typedef只是为一种已存在的类型定义一个新的名字而已,并未定义一种新的数据类型。结构体变量的引用定义了结构体变量后,可以引用该变量。但需注意:(1)不能将一个结构体变量作为一个整体进行输入和输出,只能对每个具体的成员进行输入、输出操作。如对已定义的结构体变量S1,不能按如下方式引用:printf(“%d%c%d%d%d”,S1);访问结构体变量的成员,需使用“成员运算符”(也称“圆点运算符”)。其访问格式如下:结构体变量名.成员名如,可用下面的语句为结构体变量S1的sC成员进行赋值。S1.sC=90;S1.sC为结构体成员,与其他类型变量的使用方法是一样的。注意:结构体变量不能作为整体进行输入和输出,但允许对具有相同结构体类型的变量进行整体赋值。结构体变量的引用(2)如果成员本身又属一个结构体类型,则要用若干个成员运算符,一级一级的找到最低一级的成员。例:structdate{intyear;intmonth;};structstudent{intsID; charsSex; structdatebirth; intsMath; intsEng; intsC;}s,s1,s2;则要引用结构体变量s的birth成员的year成员,则需如此引用:s.birth.year。结构体变量的引用(3)对结构体成员的操作与其它变量一样,可进行各种运算,如:赋值运算:s.birth.year=1990;算术运算:ave=(s.sMath+s.sEng+s.sC)/3;自加减运算:s.sC++;--s.sC;关系运算:s1.sC>s2.sC;结构体变量的初始化和其他数据类型的变量一样,对结构体变量可以初始化,即在定义结构体变量的同时,对其成员指定初始值。结构体变量初始化的格式:struct结构体名结构体变量名={初始数据};对结构体变量初始化应注意几点:(1)初始化数据与数据之间用逗号隔开;(2)初始化数据的个数要与被赋值的结构体成员的个数相等。(3)初始化数据的类型要与相应的结构体成员的数据类型一致。(4)不能直接在结构体成员表中对成员赋初值。结构体数组一个结构体变量中可存放一组数据(如例9-1的学生成绩管理表中的一行信息)。若该班有30个学生,则这30个学生的信息都可以用结构体变量来表示,它们具有相同的数据类型,可以用数组来表示,这就是结构体数组。结构体数组中每个数组元素都是一个结构体类型的数据,它们都分别包括各个成员项。结构体数组的定义结构体数组必须先定义,后引用。其定义形式与定义结构体变量的方法差不多,只需说明其为数组即可。如:structstudents[30];结构体数组的初始化结构体数组也可在定义的同时进行赋值,即对其进行初始化。如对结构体数组s[30]的前3个元素进行初始化,其他数组元素被系统自动赋值为0:structstudents[30]={{1,’F’,90,80,70},{2,’M’,78,89,98},{3,’M’,76,81,90}};结构体数组的引用例9-4:利用结构体数组计算上面3位同学的“英语成绩”的平均分。(1)首先分析该程序要求,结构体数组的每个元素是一位同学的信息,其中每位同学的sEng成员表示“英语成绩”,要求平均成绩,只要将每位同学的sEng成员的值加起来除以3即可。(2)流程图如图9-1所示:结构体指针变量结构体指针变量是指向结构体变量的指针,该指针变量的值就是结构体变量的起始地址,其目标变量是一个结构体变量。指向结构体变量的指针定义一个指向该结构类型的指针变量的方法为:STU*p; 这里只是定义了一个指向STU结构体类型的指针变量p,但此时的p并没有指向一个确定的存储单元,其值是一个随机值。为使p指向一个确定的存储单元,需要对指针变量进行初始化。例:pt=&S1;使指针pt指向结构体变量S1所占内存空间的首地址,即pt是指向结构体变量S1的指针。当然也可对定义指针变量初始化,例:STU*p=&S1;指向结构体变量的指针C语言规定了两种用于访问结构体成员的运算符,一种是成员运算符,也称圆点运算符(前面介绍过);另一种是指向运算符,也成箭头运算符,其访问形式为:指向结构体的指针变量名->成员名如要给结构体指针变量p指向的结构体的sEng成员赋值90,需使用语句:p->sEng=90;它与语句(*p).sEng=90;是等价的,因为()的优先级比成员运算符的优先级高,所以先将(*p)作为一个整体,取出p指向的结构体的内容,将其看成一个结构体变量,利用成员选择运算符访问它的成员。指向结构体数组的指针定义一个结构体数组STUs[30];则定义结构体指针变量p,并将其指向结构体数组s有以下三种方法:(1)STU*p=s; (2)STU*p=&s[0]; (3)STU*p; p=s; 这三种方法是等价的,指针变量p中存放的是数组s的首元素s[0]的地址。结构体变量和结构体指针变量作为函数参数将一个结构体变量的值传递给另一个函数,有3种方法:
(1)用结构体的单个成员作为函数参数,向函数传递结构体的单个成员。(2)用结构体变量作函数参数,向函数传递结构体的完整结构。(3)用结构体指针或结构体数组作函数参数,向函数传递结构体的地址。
链表链表是动态进行内存分配的一种结构,链表根据需要开辟内存单元。动态内存分配是指在程序执行的过程中根据需要动态地分配或者回收存储空间的内存分配方法。动态内存分配不像数组等静态内存分配方法那样需要预先分配存储空间,而是由系统根据程序的需要即时分配,且分配的大小就是程序要求的大小。链表数据集合中的每个数据存储在称为结点的结构体中,一个结点通过该结点中存储的另一个结点的存储地址(指针)访问另一个结点,如果按照这种方法把所有结点依次串接起来,就称为链表。链表的类型及定义链表是用一组任意的存储单元存储线性表元素的一种数据结构。链表又分为单链表、双向链表和循环链表等。链表一般采用图形方式来形象直观地描述结点之间的连接关系。这种描述链表逻辑结构的图形称为链表图。单链表单链表是最简单的一种链表,其数据元素是单向排列的单链表链表的数据结构可以用“结构体”来实现。一个结构体变量可包含若干成员,这些成员可以是数值类型、字符类型、数组类型,也可以是指针类型。利用指针类型成员存放下一个结点的指针。例如:structnode{intdata;structnode*next;};循环单链表循环单链表如图9-4所示,它的特点是最后一个结点的指针域存放着第一个结点的地址,这样一来,链表中的所有结点构成一个环,每个结点都有直接前驱和直接后继结点。循环单链表的优点是从任何一个结点出发,能到达其他任何结点。双向链表如果为每个结点增加一个指向直接前驱结点的指针域,就可以构成双向链表。双向链表可以沿着求前驱和求后继两个方向搜索结点。双向链表的结点数据结构实现如下:structnode{intdata; structnode*next,*previous;//next是后继结点指针,previous是前驱结点指针};处理动态链表的函数链表结构是动态分配存储空间的,即在需要时才开辟一个结点的存储单元。动态分配和释放存储空间需要用到以下几个库函数:(1)malloc函数函数原型为:void*malloc(unsignedintsize);(2)calloc函数函数原型为:void*calloc(unsignedn,unsignedsize);(3)free函数函数原型为:voidfree(void*p);动态链表的基本操作——单链表的建立建立单链表是在程序执行过程中从无到有的建立起一个链表,即一个一个的开辟结点和输入各结点数据,并建立起前后相连的关系。单链表的建立参考例9-6写动态内存分配的程序应注意,请尽量对分配是否成功进行检测。单链表的查找运算对单链表进行查找的思路为:对单链表的结点依次扫描,检测其数据域是否是我们所要查找的值,若是返回该结点的指针,否则返回NULL。因为在单链表的链域中包含了后继结点的存储地址,所以当我们实现的时候,只要知道该单链表的头指针,即可依次对每个结点的数据域进行检测。查找实现算法见例9-7单链表的插入操作假设例9-6中建立的链表为一个班级中的10名同学的成绩,现在如果该班又进入了一名同学,则需要将该新同学的成绩加入到单链表中,即要对单链表进行插入操作。设在一个单链表中存在两个个连续结点p、q(其中p为q的直接前驱),若我们需要在p、q之间插入一个新结点s,那么我们必须先为s分配存储空间并赋值,然后使p的链域存储s的地址,s的链域存储q的地址,这样就完成了插入操作。见图9-6。单链表的插入操作完成插入操作的主要语句为:s->next=q;p->next=s;单链表的删除操作有时我们需要使用单链表的删除操作,例如某班级调走了一名同学,则需要在成绩管理系统中将该名同学的成绩删除。假如我们已经知道了要删除的结点q的位置,那么要删除q结点时只要令q结点的前驱结点的链域由存储q结点的地址改为存储q的后继结点的地址,并回收q结点即可。如图9-7所示:单链表的删除操作删除操作的主要语句为:p->next=q->next;free(q);单链表的删除操作单链表的删除操作需注意以下几点:①要删除q结点还需要找到q的前驱结点,改变q的前驱结点的指针域,使其直接指向q的后继结点,达到删除q结点的目的,所以在单链表的删除操作中需要用到指向q结点的前驱结点的指针,例9-9中用p指向q结点的前驱结点。②删除结点的函数del中用到了free函数来释放删除结点占用的内存空间。栈和队列栈、队列和链表都属于线性结构,线性结构的特点是:在数据元素的非空有限集中,(1)存在唯一的一个被称为“第一个”的数据元素;(2)存在唯一的一个被称为“最后一个”的数据元素;(3)除第一个之外,集合中的每个数据元素均只有一个前驱;(4)除最后一个之外,集合中每个数据元素均只有一个后继。栈和队列都是操作受限制的特殊的线性表。栈是一种只允许在表头进行插入和删除操作的特殊的线性表,其操作的原则是后进先出(或先进后出)。栈又称为后进先出表,简称LIFO(LastInFirstOut)表。队列是删除操作只在表头进行,插入操作只在表尾进行的特殊的线性表,其操作的原则是先进先出。队列又称为先进先出表,简称FIFO(FirstInFirstOut)表。共用体共用体,有的也称为联合(Union),是将不同类型的数据组织在一起共同占用同一段内存的一种构造数据类型。同样都是将不同类型的数据组织在一起,但与结构体不同的是,共用体是从同一起始地址开始存放成员的值,即让所有成员共享同一段内存单元。共用体与结构体的类型定义方法相似,只是关键字变为union。共用体声明一个共用体类型的一般形式为:union共用体名{数据类型成员1的名字; 数据类型成员2的名字; 数据类型成员3的名字; ……};例:unionsample{ inti; charc; floatf;};共用体共用体数据类型和结构体数据类型都属于构造数据类型,都可以由程序员根据实际需要来定义的,其不同之处在于共用体的所有成员共同占用一段内存,共用体变量所占内存空间大小取决于其成员中占内存空间最多的那个成员变量;而结构体的每个成员自己占用一段内存,结构体变量所占内存空间大小取决于所有成员中占内存空间的大小。枚举类型枚举,即“一一列举”之意,当某些量仅由有限个数据值组成时,通常用枚举类型表示。枚举数据类型描述的是一组整型值的集合。声明枚举类型需用关键字enum,如: enumweekday{sun,mon,tue,wed,thu,fri,sat};声明了一个枚举数据类型enumweekday,程序中可以用此数据类型来定义枚举类型的变量,如:enumweekdaya;则枚举变量a的取值只有7种,即sun,mo
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 大学生骨干培训结业
- 医疗培训课件
- 中班科学活动有趣的脚印
- MODS护理个案比赛
- 医疗核心制度竞赛
- 2024部门发展规划
- 万能年终总结
- 《合理发展交通运输》课件
- 《汽缸结合面泄漏》课件
- 国土业务知识培训
- 2024秋期国家开放大学《公共政策概论》一平台在线形考(形考任务1至4)试题及答案
- DL∕T 516-2017 电力调度自动化运行管理规程
- 摇滚音乐课程教案
- 2024年烟叶分级工(高级)职业技能鉴定考试题库-下多选、判断题汇
- 电气工程师生涯人物访谈报告
- 中国儿童严重过敏反应诊断与治疗建议(2022年)解读
- 【PPT】初中英语课件:情景交际
- 港口国检查表PSC CHECKLIST
- 隧道管片外观缺陷修补施工方案(完整版)
- 纳米二氧化钛生产建设项目可行性研究报告
- ALT+数字输入特殊字符大全版
评论
0/150
提交评论