结构体、共用体与枚举类型.ppt

上传人:max****ui 文档编号:12554056 上传时间:2020-05-11 格式:PPT 页数:87 大小:818KB
返回 下载 相关 举报
结构体、共用体与枚举类型.ppt_第1页
第1页 / 共87页
结构体、共用体与枚举类型.ppt_第2页
第2页 / 共87页
结构体、共用体与枚举类型.ppt_第3页
第3页 / 共87页
点击查看更多>>
资源描述
第9章结构体、共用体与枚举类型,本章要求为什么要引入结构体,结构体与数组有什么本质不同?如何定义结构体,有几种定义形式?结构体变量与结构体指针变量有何区别,它们如何各自引用结构体成员?结构体数据如何作为函数的参数?为什么要引入链表,如何利用链表对内存进行动态管理?本章重点结构体变量的定义和使用链表的概念本章难点动态链表的常见操作,第9章结构体、共用体与枚举类型,9.1问题的提出与示例9.2结构体类型的说明与变量定义9.3结构体指针变量9.4结构体数组9.5结构体与函数9.6链表与动态内存管理9.7结构体综合应用举例,9.1问题的提出与示例,9.1.1结构体概述,例如,描述一个学生的数据实体包含学号、姓名、性别、出生年月、课程成绩、家庭住址、联系电话等数据项。各个数据项的类型是不同的,学号可为整型或字符串形式;性别为字符型;出生年月又分为年,月,日,它们可以分别为整型表示;课程成绩可以是整型或实型;家庭住址应为字符串;电话号码可以是整型或字符串形式。对于这样一个实体,不能统一用数组来描述,因为数组中各元素的类型、长度必须一致。如果用独立的简单数据项或数组分别表示它们,就不能体现一个实体数据的整体性和相互关联性,也难以操作。对于这种由多种不同类型的数据组成的数据实体,C语言专门用结构体数据类型来描述,结构体中所包含的数据项称为结构体的成员,结构体由用户根据实际来定义。,9.1问题的提出与示例,下表是一张100个学生成绩管理表,要求计算并打印出每个学生的平均成绩。,9.1问题的提出与示例,如果按照以前学过的数组方法,可以定义如下的多个数组并赋初值如下:intstu_id100=84773801,84773802,84773803,84773804,84773805,84773806;/*定义一维数组存放每个学生的学号*/charstu_name1008=“陈云”,“沈栋栋”,“易婷婷”,“谢浩杰”,“郑强”;/*定义字符串数组存放每个学生的姓名*/charstu_sex100=m,m,fm,m;/*定义字符数组存放每个学生的性别*/intstu_year100=1989,1989,1990,1988,1988;/*定义一维数组存放每个学生的出生年份*/.,这些数组的数据在内存中的存储顺序是:先存储所有学生的学号、再接着存储所有学生的姓名、接着性别、出生年份、出生月份、联系电话、课程成绩、平均成绩。也就是把所有学生的同一个类别(上表中某一列)以定义某一个数组的形式单独放在一起,相当于所有学号放在一个数组里里,所有姓名放在另一个数组里,依次类推,要处理某一个学生的信息如计算平均值并打印某个学生的信息,要分别查询所有不同的数组,很容易出错且效率不高。这样为每一项内容分别定义变量或数组的方法导致存储结构零乱,处理过程非常繁琐,一般不采用这种方法。,未了解决这个问题,C语言定义了一种可由用户自定义的数据类型,根据实际问题,将不同数据类型集中一起,把内在有联系的不同类型的数据统一成一个整体,设计符合要求的新的数据类型,称为结构体类型。这样利用结构体的特性可以把某一个学生的所有相关的不同类型的数据项都顺序存储在一起,便于一个个学生的处理。,如针对上述要求,可以定义为如下的学生的结构体:structstudentintstu_id;/*学生的学号*/charstu_name8;/*学生的姓名*/charstu_sex;/*学生的性别*/structintyear;/*学生的出生年份*/intmonth;/*学生的出生月份*/birthday;intstu_phone;/*学生的联系电话*/charstu_address30;/*学生的家庭地址*/intstu_course3;/*学生的三门课成绩*/floatstu_average;/*学生的平均成绩*/;,声明了一种新的数据类型structstudent。这个数据类型仅相当于一种结构模式,与int,float,char等类型具有同等地位,也就是用户自定义了一种新的数据类型,但并没有为structstudent分配相应的存储空间,就像系统并没有为int分配存储空间一样,而是需要定义一个整型变量,为这个整型变量分配存储空间。同样的,也需要一个结构体变量,为这个结构体变量分配存储空间。,【例9-1】按表9-1的形式从键盘依次输入每个学生的学号,姓名,出生年月,三门课的成绩,计算并打印出每个学生的平均成绩。分析:这里首先要定义一个描述学生学号,姓名,出生年月,三门课,平均成绩的结构体类型,再定义一个结构体变量,通过循环语句对这个结构体变量的各个成员的引用,读入某一个学生的各个数据项,再计算出某一个学生的平均成绩并打印某个学生的各个数据项。接着读下一个学生的数据项,再计算和打印各个数据项。,#include#defineM10structstudent/*定义一个学生的结构体*/intstu_id;charstu_name8;structdate/*定义一个内嵌的结构体*/intyear;intmonth;birthday;floatstu_course3;floatstu_ave;,voidmain()inti;structstudentp;/*定义一个结构体变量,具有structstudent类型*/for(i=0;i成员名(指针引用)(*结构指针).成员名,9.3结构体指针变量,例使用指向结构变量的指针来访问输出结构变量的各个成员的值。#include#includevoidmain()structstudentintnum;charname20;charsex;intage;floatscore;stu1=10001,zhang,M,19,88;structstudent*p=,【例9-2】输入某个职工的姓名,工资,奖金和扣款,在原来工资的基础上增加%5,计算该职工的实发工资并输出每个职工的工资条。分析:首先要定义一个描述职工具体信息的结构体,然后定义一个结构体变量和指针变量,通过指针变量引用结构体成员读入该职工的信息,计算该职工新的工资和实发工资,最后输出该职工的工资情况。,#includestructworkercharname12;floatsalary;floatbonus;floatdeduction;floatincome;,voidmain()structworkerstaff,*pwork;/*定义指针变量*/inti;pwork=/*输出工资条*/,9.4结构体数组,一个结构体变量中可以存放一组数据(如一个学生的学号、姓名、成绩等数据)如果有多个学生的数据需要参加运算和处理,就要使用结构体数组。数组是相同数据类型的集合,结构体数组与以前介绍过的数值型数组不同之处在于数组元素都是结构体类型的数据。9.4.1结构体数组的定义structstudentintnum;charname20;charsex;intage;floatscore;structstudentstu10;,9.4结构体数组,9.4.2结构体数组的初始化struct结构体名结构体数组名=第0个元素各成员第1个元素各成员,;例如:structstudentintnum;charname20;charsex;intage;floatscore;stu4=10001,Zhang,M,19,88,10002,Li,M,18,90,10003,He,F,20,92,10004,Cheng,F,18,70;,9.4结构体数组,9.4.3结构体数组与指针可以用一个指针指向结构体数组,指向结构体数组的指针的值是该结构体数组所分配的存储区域的首地址。structstudentintnum;charname20;charsex;intage;floatscore;structstudent*p;structstudentstu10;p=stu;,9.4结构体数组,p-num;/*引用stu0.num*/p+;/*p+1后指向stu1起始地址*/p-num;/*引用stu1.num*/,9.4.4结构体数组应用实例,例9-4建立10名学生的信息表,每个学生的数据包括学号、姓名、及三门课的成绩。要求从键盘输入这10名学生的信息,并按照每一行显示一名学生信息的形式将10名学生的信息显示出来。#defineN10/*N代表学生人数*/#include#includestructstudent/*定义student结构体类型*/intnum;charname20;floatscore3;,9.4.4结构体数组应用实例,voidmain()inti,j;structstudentstuN;for(i=0;iname);printf(%6.1f,%6.1f,%6.1fn,p-score0,p-score1,p-score2);,9.5结构体与函数,9.5.1结构体变量作为函数参数例9-6在例8-4中,10名学生的信息输出改为通过调用print函数完成。voidmain()inti,j;structstudentstuN;voidprint(structstudentstu);for(i=0;iN;i+)scanf(%d%s,9.5结构体与函数,9.5.2结构体数组作函数参数例9-7将例9-5中的结构体数组的输入与输出都写成函数,在main函数中调用这些函数实现10名学生的信息输入及输出。voidmain()inti,j;structstudentstuN;voidmyscan(structstudentstu,intn);/*函数声明*/voidmyprint(structstudentstu,intn);/*函数声明*/myscan(stu,N);myprint(stu,N);getch();,9.5结构体与函数,voidmyscan(structstudentstu,intn)/*输入n个学生记录函数*/inti,j;for(i=0;in;i+)scanf(%d%s,9.5结构体与函数,voidmyprint(structstudentstu,intn)/*输出n个学生记录函数*/inti,j;for(i=0;iscore0,p-score1,p-score2,p-sum);,9.5结构体与函数,/*查找最高分学生的记录函数,返回值为指向该记录的指针*/structstudent*search_max(structstudent*x,intn)inti,k=0;for(i=1;isum-(x+k)sum)k=i;/*与if(xi.sumxk.sum)k=i;等价*/returnx+k;/*返回最高分记录的指针*/,【书上台阶例9-4】用结构体类型描述复数,编写程序,计算并输出复数的加、减运算结果,要求复数加、减和输出都用函数完成。分析:首先用一个结构体的二个成员定义一个复数的实部和虚部,再定义二个具有这个结构体变量x,y。在主函数中,输入二个复数的虚实部,通过调用函数add和sub,把结构体变量x,y作为实参传递给形参,也就是把从键盘得到的二个复数的虚实部的值传给形参x,y,在函数内部作二个复数的加减运算后,返回到主函数,通过调用打印函数print_out,把复数的加减运算结果输出。,#includetypedefstructcomplex/*定义复数类型*/floatre;floatim;comp;compadd(comp,comp);compsub(comp,comp);voidprint_out(comp);,voidmain()compx,y,z;printf(Inputtwocomplexnumberplease:n);printf(第一个复数a+bi:);scanf(%f+%fi,compadd(compx,compy)/*复数的加法运算*/compz;z.re=x.re+y.re;z.im=x.im+y.im;returnz;compsub(compx,compy)/*复数的减法运算*/compz;z.re=x.re-y.re;z.im=x.im-y.im;returnz;,voidprint_out(compz)/*复数的输出*/printf(%.2f,z.re);if(z.im0)printf(+%.2fin,z.im);elseprintf(-%.2fin,-z.im);,9.6链表与动态内存管理,【例9-7】一个简单的链表。#includestdio.hstructnodeintdata;structnode*next;voidmain()structnodea,b,c,*h,*p;a.data=70;b.data=80;c.data=90;h=,9.6链表与动态内存管理,9.6链表与动态内存管理,1、malloc函数void*malloc(unsignedintsize);在内存的动态存储区中分配一个长度为size的连续空间,函数的返回值为指向该区域起始地址的指针(基类型为void);若分配不成功则返回NULL。例如语句:structnode*p;p=(structnode*)malloc(sizeof(structnode);表示分配一个structnode类型的内存空间,将函数的返回值强制转换为指向structnode类型的指针,且把该指针赋予指针变量p。,9.6链表与动态内存管理,2、calloc函数void*calloc(unsignedn,unsignedsize);在内存的动态存储取中分配n个长度为size的连续空间,函数的返回值为指向该区域起始地址的指针(基类型为void);若分配不成功则返回NULL。3、free函数voidfree(void*p);释放由p指向的内存区,使这部分内存区能被其他变量使用。p是调用malloc或calloc函数时的返回值。free()函数无返回值。,9.6链表与动态内存管理,创建一个链表一般需要以下几个步骤:(1)定义链表的数据结构。(2)读取数据。(3)生成新结点,即利用malloc()函数向系统申请分配一个结点。如:structnode*head;head=(structnode*)malloc(sizeof(structnode);(4)将数据存入结点的成员变量中。(5)将新结点插入到链表中。(6)判断是否有后续结点要接入链表,若有转到(3),否则结束。,9.6链表与动态内存管理,【例9-8】编写函数cerat,创建一个存放正整数的单链表,结点数据域中的数值从键盘输入,以-1作为输入结束标志。#includestdio.h#includestdlib.hstructnode/*定义链表结构*/intnum;structnode*next;typedefstructnodeSNODE;/*说明新的类型标识符SNODE*/,9.6链表与动态内存管理,SNODE*creat()/*用于创建链表的函数*/intdata;SNODE*h,*s,*r;h=(SNODE*)malloc(sizeof(SNODE);/*生成头结点*/r=h;scanf(%d,9.6链表与动态内存管理,9.6链表与动态内存管理,【例9-9】编写函数print,顺序输出存放正整数的单向链表各结点数据域中的内容。,voidprint(SNODE*head)/*用于输出链表的函数*/SNODE*p;p=head-next;/*p指向头结点后的第一个结点*/if(p=0)printf(nLinkListisNULL!n);/*链表为空,只有头结点*/elseprintf(head);doprintf(-%d,p-num);/*输出当前结点数据域中的值*/p=p-next;/*p指向下一结点*/while(p!=NULL);printf(-endn);,9.6链表与动态内存管理,intmain()SNODE*head;/*定义头指针*/head=creat();/*调用建立链表的函数*/print(head);/*调用输出链表的函数*/return0;,9.6链表与动态内存管理,9.6链表与动态内存管理,【例9-10】编写函数del,在单向链表中删除一个结点。SNODE*del(SNODE*head,intnumber)/*用于删除结点的函数*/SNODE*p1,*p2;if(head=NULL)printf(nListisNULL!n);return(head);p1=head;while(number!=p1-num,9.6链表与动态内存管理,intmain()SNODE*head,*head2;intdel_num;/*要删除的结点的数据*/printf(输入若干整型数据建立链表,以-1结束:);head=creat();/*调用建立链表的函数*/printf(原链表内容为:n);print(head);/*调用输出链表的函数*/printf(n输入要删除的数据:);scanf(%d,9.6链表与动态内存管理,9.6链表与动态内存管理,【例9-11】编写函数insert,在单向链表中插入一个结点。具体功能为:在值为x的结点前,插入值为y的结点;若值为x的结点不存在,则插在表尾。,9.6链表与动态内存管理,SNODE*insert_node(SNODE*head,intx,inty)/*用于插入结点的函数*/SNODE*s,*p,*q;s=(SNODE*)malloc(sizeof(SNODE);/*生成新结点*/s-num=y;/*新结点中存入y*/q=head;p=head-next;/*p指向第一个结点,q为p的前趋*/while(p!=0),9.7结构体综合应用举例,【例9-12】编写一个程序实现对学生数据的操作,每个学生结点包括学号和一门课程的成绩,要求:(1)输入若干学生的学号和成绩建立链表;(2)能对链表进行输出;(3)能根据学号删除指定的学生结点;(4)能插入给定的学生结点。,9.7结构体综合应用举例,structnodelongnumber;floatscore;structnode*next;typedefstructnodeSNODE;,9.7结构体综合应用举例,SNODE*insert_node(SNODE*head,longx,longy,floatz)/*用于插入结点的函数*/SNODE*s,*p,*q;s=(SNODE*)malloc(sizeof(SNODE);/*生成新结点*/s-number=y;s-score=z;/*新结点中存入学号和分数*/q=head;p=head-next;/*p指向第一个结点,q为p的前趋*/while(p!=0),9.7结构体综合应用举例,SNODE*del_node(SNODE*head,longx)/*用于删除结点的函数*/SNODE*p1,*p2;if(head=NULL)printf(nListisNULL!n);return(head);p1=head;while(x!=p1-number,9.7结构体综合应用举例,voidprint(SNODE*head)/*用于输出链表的函数*/SNODE*p;p=head-next;if(p=0)printf(nLinkListisNULL!n);elseprintf(head);doprintf(-%ld,%.0f,p-number,p-score);p=p-next;while(p!=NULL);printf(-endn);,9.7结构体综合应用举例,SNODE*creat()/*用于创建链表的函数*/longnum;floatsco;SNODE*h,*s,*r;h=(SNODE*)malloc(sizeof(SNODE);r=h;printf(n请输入学号(-1结束):);scanf(%ld,9.7结构体综合应用举例,intmain()SNODE*head,*head2,*head3;longins_num;/*要插入的学号*/floatins_score;/*要插入的分数*/longx;/*插入位置*/longdel_num;/*要删除的学号*/head=creat();/*调用建立链表的函数*/printf(原链表内容为:n);print(head);/*调用输出链表的函数*/printf(n输入要插入的位置(学号):);scanf(%ld,*9.8共用体与枚举类型,union共用体名成员表列;变量表列;如:uniondatainti;charch;num1,num2;,*9.8共用体与枚举类型,【例9-13】结构体和共用体结合,描述客车和货车。structvehicleintwheel;/*车轮*/unionfloatload;/*货车载重量*/intpassengers;/*客车载客数*/;bus,truck;intmain()bus.wheel=4;bus.passengers=40;truck.wheel=6;truck.load=15000;printf(Thebuscarriespassengers:%dn,bus.passengers);printf(Thetruckcarriesgoods:%.0fn,truck.load);/*以下为不正确的使用方式*/printf(-n);bus.load=4000;printf(Thebusload=%.0f,passengers=%dn,bus.load,bus.passengers);return0;,*9.8共用体与枚举类型,【例9-14】设有若干人员的数据,其中有教师和学生。教师数据中包括:教师号,姓名,性别,职业,职务。学生数据中包括:学号,姓名,性别,职业,班级。见图9-12。要求编写程序输入人员的数据,然后再输出。,*9.8共用体与枚举类型,structP/*人员结构体*/intnum;charname10;chargender;charjob;union/*表示第5项的共用体*/ints_class;charposition10;category;person20;,*9.8共用体与枚举类型,main()inti=0,j;printf(n输入号码(-1结束):);scanf(%d,*9.8共用体与枚举类型,/*以下为输出部分*/printf(nNO.Namegenderjobclass/positionn);for(j=0;ji;j+)if(personj.job=s)printf(%-6d%-12s%-8c%-8c%-10dn,personj.num,personj.name,personj.gender,personj.job,personj.category.s_class);elseprintf(%-6d%-12s%-8c%-8c%-10sn,personj.num,personj.name,personj.gender,personj.job,personj.category.position);return0;,*9.8共用体与枚举类型,enum枚举名标识符,标识符标识符枚举变量;例如:enumdate1Monday,Tuesday,Wednesday,Thursday,Fridayworkday;,*9.8共用体与枚举类型,【例9-15】设某月的第一天是星期一,编程实现输入该月的任意一天,由程序给出这一天是星期几。main()enumweeksun,mon,tue,wed,thu,fri,satday32;inti,j,num;j=1;/*某月的第一天为星期一,枚举元素mon对应1*/for(i=1;i32;i+)/*给每一天赋上对应的星期几*/dayi=(enumweek)j;/*将整数强制转换为枚举类型后再赋值*/if(j=6)j=0;elsej=j+1;printf(nInputday:);scanf(%d,*9.8共用体与枚举类型,switch(daynum)case0:printf(%disSundayn,num);break;case1:printf(%disMondayn,num);break;case2:printf(%disTuesdayn,num);break;case3:printf(%disWednesdayn,num);break;case4:printf(%disThursdayn,num);break;case5:printf(%disFridayn,num);break;case6:printf(%disSaturdayn,num);break;return0;,
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 课件教案


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!