《C++程序设计第8章枚举型和结构体.ppt》由会员分享,可在线阅读,更多相关《C++程序设计第8章枚举型和结构体.ppt(73页珍藏版)》请在三一办公上搜索。
1、第8章 枚举型和结构体,目的与要求8.1 枚举类型的定义及应用8.2 结构体的定义及应用8.3 链表本章小结,目的与要求,通过本章学习,应了解枚举型与结构体两种导出数据类型的概念,掌握枚举型与结构体两种数据类型的定义格式与方法,会用枚举型与结构体数据类型定义枚举型变量与结构体变量。会用结构体与枚举型解决实际问题。了解链表的概念,初步学会链表的简单操作,如:链表的建立、增加、删除、查询等方法。,8.1 枚举类型的定义及应用,枚举类型:是某类数据可能取值的集合;枚举变量:用枚举类型定义的变量。8.1.1 枚举类型的定义1.枚举类型的定义格式 enum;例如:enum weekdays Sun,Mo
2、n,Tue,Wed,Thu,Fri,Sat;,2.枚举类型元素的序号,枚举类型元素序号:是元素对应的整型常量值。(1)默认序号值 若枚举类型定义中没有指定元素的序号值,则默认序号值从0开始依次递增。(2)指定序号值 全指定,所谓全指定是给枚举类型的每一个元素指定一个序号值。例如:enum boolean TRUE=1,FALSE=0;部分指定,所谓部分指定是给枚举类型的部分元素指定序号值。例如:enum colors red=5,blue=1,green,black,white,yellow;。,8.1.2 枚举类型变量的定义,1.先定义类型后定义变量格式:,;例如:enum weekdays
3、 Sun,Mon,Tue,Wed,Thu,Fri,Sat;weekdays day1,day2;2.定义类型的同时定义变量格式:enum,;例如:enum weekdays Sun,Mon,Tue,Wed,Thu,Fri,Sat day1,day2;,枚举类型变量的定义,3.直接定义枚举变量格式:enum,;例如:enum Sun,Mon,Tue,Wed,Thu,Fri,Sat day1=Sun,day2=Mon;定义枚举变量时,可对变量进行初始化赋值。,8.1.3 枚举类型变量的引用,1.赋值运算 枚举类型的元素可直接赋给枚举变量,且同类型枚举变量之间可以相互赋值。即:(1)枚举变量=枚举元
4、素;如,day1=Sun;(2)枚举变量1=枚举变量2;如,day2=day1;2.枚举变量的输入输出(1)不能用键盘通过“cin”向枚举变量输入元素值。(2)可用“cout”输出枚举变量,但输出的是元素对应的序号值,而不是元素值。,枚举类型变量的关系运算,3.关系运算 枚举变量可与元素常量进行关系比较运算,同类枚举变量之间也可以进行关系比较运算,但枚举变量之间的关系运算比较是对其序号值进行的。例如:day1=Sun;/day1中元素Sun的序号值为0 day2=Mon;/day2中元素Mon的序号值为1 if(day2day1)day2=day1;/day2day1的比较就是序号值关系式:1
5、0的比较 if(day1Sat)da1=Sat;/day1Sat的比较就是序号值关系式:06的比较,枚举型举例,【例8.1】先定义描述6种颜色的枚举类型colors,然后再用该枚举类型定义枚举数组,任意输入6个颜色号,转换成对应的颜色枚举量后输入到枚举数组中,最后输出枚举数组中对应的颜色。例程【例8.2】定义一个描述三种颜色的枚举类型red、blue、green,输出这三种颜色的全部排列结果。,例程,8.2 结构体的定义及应用,学生成绩情况表,学生成绩信息必须用不同数据类型的数据项来描述的情况,如:学号:no-int 姓名:name-char8 成绩:eng、phi、math、ave-floa
6、t,8.2.1 结构体的概念,结构体的概念,结构体:将不同类型数据作为一个整体来处理的数据结构称为结构体。结构体类型:是导出型数据类型,必须先定义结构体类型,后定义结构体变量。,8.2.2 结构体类型的定义,结构体类型的定义格式为:struct;说明:(1)关键词struct说明定义的是结构体类型;(2)结构体类型名必须符合标识符命名规则;(3)结构体由若干个数据成员组成,每个数据成员可以有不同的数据类型。数据类型可以是基本类型,也可以是导出类型。,结构体类型的定义举例,【例8.3】定义一个学生成绩的结构体数据类型如下:struct student int no;/学号 char name8;
7、/姓名 float eng,phy,math,ave;/英语、物理、数学与平均成绩;,8.2.3 结构体变量的定义,1.结构变量的定义(1)先定义类型后定义变量格式:存储类型,;例如:student stu1,stu23;(2)定义结构体的同时定义结构体变量 格式:struct,;,结构体变量的定义,例如:struct student int no;char name8;float eng,phy,math,ave;stu1,stu23;(3)直接定义结构体变量 struct,;例如:struct int no;char name8;float eng,phy,math,ave;stu1,st
8、u23;,2.结构体变量的初始化,定义结构体变量时可进行初始化。结构体变量的初始化格式:=初始化值;例如:student stu1=1001,Zhou,90,85,80;student stu23=1001,Zhou,90,85,80,1001,Li,75,80,85,1001,Wang,95,85,90;,结构体变量的引用,1.结构体变量数据成员的引用格式.其中“.”称为成员运算符。例如::stu1.no 表示引用学生结构体变量stu1中的数据成员no。stu20.no 表示引用学生结构体数组元素stu20的数据成员no。,2.结构体变量数据成员的输入/输出,C+规定,用cin、cout只能
9、对数据成员进行输入输出,不能对结构体变量输入输出。输入输出格式如下。(1)输入:cin.;例如:cinstu1.nostu1.namestu1.engstu1.phistu1.math;(2)输出:cout.;例如:coutstu1;与coutstu1 是错误的。,3.结构变量的赋值运算,允许两个同类型结构变量之间的赋值运算:结构体变量1=结构体变量2;例如:student stu1=1001,Zhou,90,85,80,stu2;stu2=stu1;此时,stu2将具有与stu1相同的数据内容。【例8.4】定义全班学生学习成绩的结构体数组,学生结构体类型的数据成员为:姓名、学号、英语、物理、
10、数学和这三门功课的平均成绩。先输入全班成绩,再计算每个学生的平均成绩,最后输出全班成绩表。例程,8.2.5 结构体变量与数组作为函数参数(习题课),1.函数定义格式(1)结构体变量作为函数参数(,)函数体(2)结构体数组作为函数参数(,)函数体,结构体变量与数组作为函数参数,2.函数调用格式(1)结构体变量作为实参:函数名(结构体变量名,)(2)结构体数组作为实参:函数名(结构体数组名,)3.参数的传送方式 用结构体变量作为函数参数时,实参值传送给形参属于值传送,因此,函数调用后实参值仍保持不变。用结构体数组作为函数参数时,实参值传送给形参属于传地址,因此,函数调用后实参数组值随形参数组而变动
11、。,结构体变量与数组作为函数参数举例,【例8.5】定义全班学生学习成绩的结构体数组,学生结构体类型的数据成员为:姓名、学号、英语、物理、数学和这三门功课的平均成绩(通过计算得到)。设计四个函数:全班成绩输入,求出每个学生的平均成绩,按平均成绩的升序排序,输出全班成绩表。在主函数调用这四函数完成学生成绩的输入、计算、排序与输出工作。【例8.6】建立学生档案的结构体数组,描述一个学生的信息:姓名、性别、年龄、出生日期。输出已建立的学生档案。【例8.7】定义一个复数结构体,以复数的实部r、虚部i作为结构体成员,编写能实现两复数加法的函数,用结构体变量作为其形参。在主函数内定义两个复数,并赋初值。调用
12、复数加法函数,完成两复数相加的操作。,例程,例程,例程,8.3 链表,8.3.1链表的概念 1.链表的概念 链表是由若干同类型结点用指针链接而成的数据结构。链表由表头、结点与链尾三部组成。,链表的概念,(1)表头head是指向链表的头指针;(2)结点是用含有指针的结构体类型node定义的结构体变量。如描述学生信息结点类型node可定义为:struct node int no;char name8;float eng,phy,math,ave;node*next;(3)链尾是链表中指针值为0的结点,用于表示链表的结束。类似于字符串中以0作为结束标志。,2.链表的基本操作,链表的主要操作有链表的建
13、立、查询、输出、插入、删除等。为方便后面的讨论,将结点内数据成员简化为学号、成绩与指针三项,简化后的链表结点类型node定义为:struct node int no;int score;node*next;;,8.3.2 链表的基本操作,链表的主要操作有建立链表、输出链表、删除链表、查询指定结点、删除指定结点、插入结点、建立有序链表等。链表的基本操作可以用自定义函数来实现:(1)建立链表函数 node*Create(void)(2)输出链表函数 void Print(node*head)(3)删除链表 函数 void Delchain(node*head)(4)删除指定结点函数 node*De
14、lete(node*head,int no)(5)插入结点函数 node*Insert(node*head,node*pn)(6)建立有序链表函数 node*Create_order()在主函数中调 用上述函数,可完成建立链表、输出链表、删除链表、删除结点、插入结点、建立有序链表等操作。,1.建立无序链表函数Create(),建立无序链的步骤为:(1)先定义三个node类型的指针变量:node*head,*pn,*pt;(2)新建结点,输入学号和成绩。用new运算符动态分配新结点空间,将pn指向该新结点,给新结点输入学号和成绩。(3)将新结点加入到链尾,新结点加入到链尾有链表为空与非空二种情况
15、:链表为空 链表非空,链表为空时加入新结点,链表非空时插入新结点,建立无序链表函数,(4)重复(2)、(3)两步,通过循环不断向链表添加新结点直到学号为“-1”为止。(5)将链尾结点指针赋0。(6)返回链表头指针head。,例程,2.输出链表函数Print(),例程,输出链表中各结点成绩应用函数void Print(void)实现。建立输出链表函数的步骤如下。(1)函数必须用形参node*head接收来自主函数的链表头指针head。(2)定义指针变量node*p=head;将p指向链表首结点。(3)用循环语句依次输出每个结点的学号与成绩,直到链尾(p=0)为止。,3.删除链表函数Delchai
16、n(),例程,删除链表是指删除链表全部结点,并回收结点所占用的全部内存空间。删除链表用函数Delchain(node*head)实现,主要操作步骤如下。(1)用形参node*head接受来自于主函数的链表头指针;(2)定义指针变量node*p=head;并使指针变量p 指向链首,如图所示;(3)用循环语句依次删除链表的各结点。,返回,4.删除链表上指定结点函数Delete(),删除链表上指定值结点用函数Delete(node*head,int no)实现。函数形参应有两个,第一个为链表头指针head,第二个为要删除结点的学生学号no。要删除链表上指定学号的结点,首先要找到要删除的结点,然后才能
17、删除该结点。删除结点可能会遇到三种情况:(1)若链表为空,即head为0,则返回空指针。(2)若要删除的结点为链表首结点,则将该结点的指针值赋给链表头指针head,然后删除该结点即可。如前页图所示。,删除链表上指定结点,(3)要删除的结点不是链表首结点。定义指针变量pc、pa分别指向当前正查找的结点与其后一个结点。图示 用下列循环语句找到要删除结点。while(pc-no!=no)pa=pc;pc=pc-next;查找后有两种情况:链表中无要删除的结点,则输出无此结点的信息。链表中有要删除的结点,如要删除结点学号为“1002”。图示,例程,查找指定结点,返回,删除指定结点,返回,5.插入结点函
18、数Insert(),链表各结点按成绩score降序排列,插入结点后,仍要求按成绩score降序排列。在插入函数Insert(node*head,node*pn)的形参中,head为头指针,pn为指向插入结点的指针。在插入函数体中:pc为指向插入点前一个结点的指针,pa为指向插入点后一个结点的指针。插入结点有两种情况:(1)链表为空 将新结点插入到链表首,并将尾指针赋0。实现语句为:if(head=NULL)head=pn;pn-next=0;,图示,插入结点(续),(2)链表非空 首先判断新结点的成绩是否大于或等于链表首结点的成绩,若大于或等于首结点成绩,则将新结点插入到链首位置,若小于首结点
19、成绩,则要根据新结点的成绩,将指针变量pc移动到插入点前,指针变量pa移动到插入点后。实现语句为:while(pc-next!=0,图示,插入结点(续),当pc与pa移到插入点位置处时,又有两种情况:新结点插入到链尾 当新结点成绩最小时,按降序排列该结点应插入到链表尾。插入到链表尾的条件是新结点成绩小于链表尾结点成绩,即:pn-scorescore。实现语句为:if(pn-score score)pc-next=pn;pn-next=0;,插入结点(续),新结点插入到链表中间 除上面所述情况外,新结点应插入链表中间,实现语句为:pn-next=pc;pa-next=pn;第一条语句使新结点指向
20、pc所指结点,第二条语句使pa所指结点指向新结点,从而实现将新结点插入到pc与pa所指两结点之间。,图示,例程,插入结点,返回,6.建立有序链表函数Create_Order(),向一个空链表中不断地插入新建立的结点,并使新结点按序排列,就产生一条有序链。建立一条有序链表的过程可分为两步:首先建立一个新结点,其次将新结点插入到链表中。例程,7.完成链表处理的主程序,#include#include struct node char no;int score;node*next;node*Create(void)/建立无序链表的函数 void Print(const node*head)/输出链表
21、的函数void Delchain(node*head)/删除整个链表的函数node*Delete(node*head,int no)/删除指定结点的函数node*Insert(node*head,node*pn)/插入结点的函数node*Create_Order(void)/建立有序链表的函数,完成链表处理的主程序,void main(void)/主函数 node*head;int no;head=Create();/产生无序链表 Print(head);/输出无序链表 coutno;/输入要删除结点的学生学号 head=Delete(head,no);/删除指定学号的结点 Print(hea
22、d);/输出显示删除后的链表。Delchain(head);/删除整个链表 head=Create_sort();/产生一个有序链表 Print(head);/输出显示有序链表 Delchain(head);/删除整个链表,本章小结,1.枚举型 枚举型是某种数据可能取值的集合,定义格式为:enum;枚举元素表中的各元素为数据可能取值的集合;每元素均有一个序号值与之对应。用枚举类型可定义枚举变量或枚举数组。枚举变量可进行赋值运算与比较运算。不能用cin输入枚举元素值或序号值,只能用赋值运算符将枚举元素值赋给枚举变量。用cout可以输出枚举变量,但输出的是其序号而不是元素值。枚举变量可进行比较运算
23、,枚举变量之间的比较运算是对其序号进行的。,2.结构体,结构体是由若干数据成员组成的导出数据类型,其定义格式为:struct 成员1;成员n;结构体中成员的数据类型可以是基本类型,也可以是导出类型。用结构体数据类型可定义结构体变量或结构体数组。数据成员的引用格式为:结构体变量名.成员名。不能对结构体变量直接进行输入、输出,只能对结构体变量的数据成员进行输入、输出。,3.链表的基本操作,链表由若干个结构类型的结点用指针链接而成,每个结点由数据与指针两部分组成,其中指针用于链接下一个结点。链表的首结点地址存放在头指针中,尾结点指针必须为0。链表的主要操作有链表的建立、插入、删除、输出等。,建立和删
24、除链表的主要操作,(1)建立无序链表的主要操作 先用new动态分配一个结点空间,并用指针变量pn指向新结点,输入数据到结点内,然后将新结点加入到链尾,依次循环直到输入结束标志为止。若用pt指向链尾结点,则将新结点加到链尾的主要操作是:pt-next=pn;/新结点加入到链尾 pt=pn;/使pt指向新的链尾(2)删除整个链表的主要操作 先用指针变量p指向链表首结点(p=head),再将首结点从链表分离出来(head=p-next),最后删除首结点(delete p),依次循环直到删完(head=0)为止。,删除指定结点的主要操作,(3)删除指定结点的主要操作 先用循环语句找到要删除的结点,如:
25、while(pc-no!=no)pa=pc;pc=pc-next;用pc指向要删除的结点,pa指向删除结点的后一个结点,只要执行下面两条语句:pa-next=pc-next;/要删除结点前一个结点的地址赋给其后一个结点的指针 delete pc;/动态回收结点占用空间 则指定结点被删除。,插入结点的主要操作,(4)插入结点的主要操作 先用循环语句找到插入点的位置,用pc指向插入点前一个结点,pa指向插入点后一个结点,用pn指向新结点,只要执行下面两条语句:pn-next=pc;/将插入点前一个结点的地址赋给新结点的指针 pa-next=pn;/将新结点的地址赋给插入点后一个结点的指针 则新结点
26、被插入到指定位置。,例8.1(1),#include#include/使用exit(0)函数时必须包含stdlib.h头文件enum colors/定义有6种颜色元素的枚举类型colors red,blue,green,black,white,yellow;void main(void)colors color6;/定义枚举类型数组 int j,n;cout0:red,1:blue,2:green,3:black,4:white,5:yellowendl;cout”请输入6个颜色号:”;,例8.1(2),for(j=0;j n;/输入颜色号 if(n5)cout 输入颜色值出错,请重新输入!;
27、exit(0);else switch(n)/将颜色号转换成元素存入数组 case 0:colorj=red;break;case 1:colorj=blue;break;case 2:colorj=green;break;case 3:colorj=black;break;case 4:colorj=white;break;case 5:colorj=yellow;break;,例8.1(3),for(j=0;j6;j+)/循环6次,输出数组元素对应的颜色 switch(colorj)case red:cout red;break;case blue:coutblue;break;case
28、green:cout green;break;case black:coutblack;break;case white:cout white;break;case yellow:cout yellow;break;coutt;coutn;,返回,例8.2(1),#include enum colorsred,blue,green;void show(colors color)switch(color)case red:coutred;break;case blue:coutblue;break;case green:coutgreen;break;coutt;,例8.2(2),void ma
29、in(void)colors col1,col2,col3;for(col1=red;col1=green;col1=colors(int(col1)+1)for(col2=red;col2=green;col2=colors(int(col2)+1)for(col3=red;col3=green;col3=colors(int(col3)+1)show(col1);show(col2);show(col3);coutn;,返回,例8.4(1),#include#define N 3struct student/定义学生成绩结构体类型 int no;char name8;float eng,p
30、hy,math,ave;void main(void)student s3;/定义结构体数组 cout si.no si.namesi.engsi.physi.math;,例8.4(2),for(i=0;iN;i+)si.ave=(si.eng+si.phy+si.math)/3;cout“学号”t“姓名”t 英语 t 物理 t 数学 t 平均成绩 n;for(i=0;iN;i+)coutsi.not si.name tsi.engt si.phyt si.matht si.aven;,返回,例8.5(1),#include struct student/定义学生成绩结构体类型 int no;
31、char name8;float eng,phy,math,ave;void Input(student s,int n)/输入函数 int i;cout si.no si.namesi.engsi.physi.math;,例8.5(2),void Ave(student s,int n)/求平均成绩函数 int i;for(i=0;isj.ave)k=j;if(ki)temp=sk;sk=si;si=temp;,例8.5(3),void Print(student s,int n)/输出函数 int i;cout“学号”t“姓名”t“英语”t 物理 t 数学 t 平均成绩 n;for(i=0
32、;in;i+)coutsi.notsi.nametsi.engt si.phyt si.matht si.aven;,例8.5(4),void main(void)student stu3;/定义结构体数组 Input(stu,3);/输入学生成绩 Ave(stu,3);/计算学生平均成绩 Sort(stu,3);/按平均成绩排序 Print(stu,3);/输出学生成绩,返回,例8.6(1),#include struct date/定义出生日期结构体类型 int year,month,day;/定义出生年、月、日 数据成员;struct student/定义学生档案结构体类型 int no
33、;/学号 char name10;/姓名 char sex2;/性别 int age;/年龄 date birthday;/出生日期(结构体类型);,例8.6(2),void output(student x)/定义输出函数 cout x.no tx.namet x.sex t x.age t x.birthday.yeartx.birthday.monthtx.birthday.dayendl;void main(void)cout notnametsextaget yeart monthtdayendl;student s2=100,zhou,m,22,1980,12,1,101,Li,w
34、,24,1978,1,1;for(int j=0;j2;j+)output(sj);,返回,例8.7(1),#include struct Complex/定义一个复数结构体 float r;/复数的实部 float i;/复数的虚部;Complex add(Complex c1,Complex c2)/复数加法函数 Complex c;/定义复数结构体变量c c.r=c1.r+c2.r;/两复数实部相加赋给c的实部 c.i=c1.i+c2.i;/两复数虚部相加赋给c的虚部 return c;/返回相加后的复数c,例8.7(2),void main(void)Complex x1=10,25,
35、x2=20,35,x;/定义三个复数x1、x2、x x=add(x1,x2);/调用复数加法函数 coutx1=x1.r+x1.iiendl;coutx2=x2.r+x2.iiendl;coutx=x.r+x.iiendl;执行程序后输出 x1=10+25i x2=20+35i x=30+60i,返回,建立无序链表函数Create(),node*Create(void)/定义输入学生学号的临时变量no int no;/定义链表头指针、新结点指针、尾指针node*head,*pn,*pt;head=0;/链表头指针赋0,表示链表为空。coutno;/输入学生学号 while(no!=-1)/成绩
36、为-1时结束输入/动态分配新结点内存空间,并将结点地址赋给pn。pn=new node;pn-no=no;/将学生学号输入新结点cinpn-score;/学生成绩输入新结点,if(head=0)/若链表为空 head=pn;/则将新结点地址由pn赋给头指针head与尾指针pt pt=pn;/使新结点加入到链首 else/否则链表非空 pt-next=pn;/将新结点地址由pn赋给链尾的next指针与尾指针pt pt=pn;/使新结点加入到链尾 cin no;/输入学生成绩 pt-next=0;/链尾指针变量赋0 return(head);/返回链表的头指针,返回,输出链表函数Print(),v
37、oid Print(node*head)node*p=head;coutnoscorenext;,返回,删除链表函数Delchain(),void Delchain(node*head)node*p;p=head;/链表头指针赋给p while(head)/当链表非空时删除结点 head=p-next;/将链表下一个结点指针赋给head delete p;/删除链表第一个结点 p=head;/再将头指针赋给p,返回,删除链表上指定结点函数Delete()(1),node*Delete(node*head,int no)node*pc,*pa;pc=pa=head;/链表为空的情况 if(hea
38、d=NULL)cout 链表为空,无结点可删!t;return NULL;,/第一个结点为要删除结点的情况else if(pc-no=no)/将第二个结点的地址赋给head/使首结点从链表中分离出来 head=pc-next;/删除首结点 delete pc;cout删除了一个结点!n;,删除链表上指定结点函数Delete()(2),else/第一个结点不是要删除的结点 while(pc-no!=no)/查找要删除的结点 pa=pc;/当前结点地址由pc赋给pa pc=pc-next;/pc指向下一个结点 if(pc=NULL)/若pc为空表示链表中无要删除的结点 cout next=pc-n
39、ext;/将下结点地址赋给上结点指针,/使删除结点从链表分离出来 delete pc;/删除指定结点 cout删除一个结点!n;return head;/返回链表头指针,返回,插入结点函数Insert()(1),node*Insert(node*head,node*pn)/定义指向插入点前、后的指针pc与panode*pc,*pa;/若链表为空,则新结点插入到链表首 pc=pa=head;if(head=0)head=pn;pn-next=0;return head;,/若新结点成绩首结点成绩则新结点插在链首 if(pn-score=head-score)pn-next=head;head=p
40、n;return head;,插入结点函数Insert()(2),/若链表非空,则按成绩查找插入点while(pc-next!=0,/新结点插入到链尾if(pn-score score)pc-next=pn;pn-next=0;else/新结点插入到链表中间 pn-next=pc;pa-next=pn;return head;/返回链表头指针,返回,建立有序链表函数Creat_Order(),返回,node*Create_Order(void)node*pn,*head=0;/定义指向新结点的指针变量pn及链表头指针head int no;/定义输入学生成绩的临时变量score coutno;while(no!=-1)/学号不等于-1则循环 pn=new node;/动态分配node类型结点空间,并将其地址赋给pn pn-no=no;/给新结点输入学号与成绩 cinpn-score;head=Insert(head,pn);/调用结点插入函数,将新结点按成绩降序插入链表 cinno;/输入学号 return head;/返回链表头指针,