10高级程序语言.ppt
第十讲结构类型1结构类型及其变量定义&结构类型是一种构造数据类型&用途:把不同类型的数据组合成一个整体-自定义数据类型结构类型定义struct结构名类型标识符成员名;类型标识符成员名;.;成员类型可以是基本型或构造型(数组、指针或其他结构类型)struct是关键字,不能省略合法标识符可省:无名结构类型例structstudentlongintorder;charname20;charsex;shortintage;intscore10;charaddr30;结构类型定义描述结构的组织形式,不分配内存结构类型定义的作用域nameordersexagescoreaddr4字节2字节20字节1字节20字节30字节.例structid_card charname30;charsex;charnationality20;structdateintyear,month,day;birthday;char*p_addr;structdatesigned_date;longnumber;char*office;同一结构类型各成员不能同名,不同结构类型成员可以同名结构类型可以嵌套定义例structwrong charname30;intcount;structwronga;结构类型不能递归定义例structstudentlongintorder;charname20;charsex;shortintage;intscore10;charaddr30;structstudentstu1,stu2;结构变量的定义v先定义结构类型,再定义结构变量v一般形式:struct结构名类型标识符成员名;类型标识符成员名;.;struct结构名变量名表列;例#defineSTUDENTstructstudentSTUDENTlongintorder;charname20;charsex;shortintage;intscore10;charaddr30;STUDENTstu1,stu2;例structcoordfloatx;floaty;/*struct coord表示屏幕上一个点的坐标表示屏幕上一个点的坐标*/structcoordfirst,second;定义结构类型的同时定义结构变量一般形式:struct结构名类型标识符成员名;类型标识符成员名;.变量名表列;例structstudentlongintorder;charname20;charsex;shortintage;intscore10;charaddr30;stu1,stu2;例structcoordfloatx;floaty;first,second;/*struct coord表示屏幕上一个点的坐标表示屏幕上一个点的坐标*/直接定义结构类型变量一般形式:struct类型标识符成员名;类型标识符成员名;.变量名表列;例structlongintorder;charname20;charsex;shortintage;intscore10;charaddr30;stu1,stu2;用无名结构类型直接定义变量只能一次例structfloatx;floaty;first,second;/*struct coord表示屏幕上一个点的坐标表示屏幕上一个点的坐标*/说明v结构类型与结构类型变量概念不同l类型:不分配内存;变量:分配内存l类型:不能赋值、存取、运算;变量:可以v结构类型可嵌套v结构类型成员名与程序中变量名可相同,不会混淆v结构类型及变量的作用域与生存期例structdateintmonth;intday;intyear;structstudentintnum;charname20;structdatebirthday;stu;numnamebirthdaymonthdayyear例structstudentintnum;charname20;structdateintmonth;intday;intyear;birthday;stu;numnamebirthdaymonthdayyear2结构类型变量的引用引用规则v结构类型变量不能整体引用,只能引用变量成员v可以将一个结构类型变量赋值给另一个结构类型变量v结构类型嵌套时逐级引用成员(分量)运算符优先级:1结合性:从左向右引用方式:结构类型变量名.成员名例structstudentintnum;charname20;charsex;intage;floatscore;charaddr30;stu1,stu2;stu1.num=10;stu1.score=85.5;stu1.score+=stu2.score;stu1.age+;例structstudentintnum;charname20;charsex;intage;floatscore;charaddr30;stu1,stu2;printf(“%d,%s,%c,%d,%f,%sn”,stu1);()stu1=101,“WanLin”,M,19,87.5,“DaLian”;()例structstudentintnum;charname20;charsex;intage;floatscore;charaddr30;stu1,stu2;stu2=stu1;()例structstudentintnum;charname20;structdateintmonth;intday;intyear;birthday;stu1,stu2;numnamebirthdaymonthdayyearstu1.birthday.month=12;例structstudentintnum;charname20;charsex;intage;floatscore;charaddr30;stu1,stu2;if(stu1=stu2).()例例 1 计算某个同学计算某个同学5门课程成绩的平均分。门课程成绩的平均分。#include void main()struct studentchar*name;/*姓名姓名*/long order;/*学号学号*/int score5;/*成绩成绩*/float average;/*平均分平均分*/who;int sum=0,n;printf(“input name,order and 5 scoresn”);scanf(“%s%ld”,who.name,&who.order);for(n=0;n5;n+)scanf(“%d”,&who.scoren);who.average=0.0;for(n=0;n5;n+)sum+=who.scoren;who.average=(float)sum/5;printf(“nname=%storder=%ldn”,who.name,who.order);printf(“average=%fn”,who.average);char name20;例例 2 输入矩形左上角和右下角坐标,计算该矩形长和宽及面积。输入矩形左上角和右下角坐标,计算该矩形长和宽及面积。#include#include void main()float length,width,area;struct coordfloat x,y;struct rectangle struct coord topleft,bottomrt;mybox;printf(“enter the top left x,y coordinate:n”);scanf(“%f%f”,&mybox.topleft.x,&mybox.topleft.y);printf(“enter the bottom right x,y coordinate:n”);scanf(“%f%f”,&mybox.bottomrt.x,&mybox.bottomrt.y);length=fabs(double)(mybox.bottomrt.x-mybox.topleft.x);width=fabs(double)(mybox.topleft.y-mybox.bottomrt.y);area=length*width;printf(“nlength=%ftwidth=%fn”,length,width);printf(“area=%fn”,area);例structstudentintnum;charname20;charsex;intage;charaddr30;structstudentstu1=112,“WangLin”,M,19,“200BeijingRoad”;3结构变量的初始化形式一:struct结构类型名类型标识符成员名;类型标识符成员名;.;struct结构类型名结构类型变量=初始数据;例structstudentcharname20;longorder;intscore5;floataverage;structstudentwho=“WangLin”,031112,92,91,89,87,94,0.0;例structcoordfloatx,y;structrectanglestructcoordtopleft;structcoordbottomrt;structrectanglemybox=1.8,8.3,12.4,1.29;聚合成员聚合成员初始化初始化例structstudentintnum;charname20;charsex;intage;charaddr30;stu1=112,“WangLin”,M,19,“200BeijingRoad”;初值表中初值的个数初值表中初值的个数成员名成员名结构类型变量名结构类型变量名.成员名成员名4结构类型和指针指向结构类型变量的指针v定义形式:struct结构类型名*结构类型指针名;例structstudent*p;v使用结构类型指针变量引用成员形式存放结构类型变量在内存的起始地址numnamesexagestupstructstudentintnum;charname20;charsex;intage;stu;structstudent*p=&stu;指向运算符优先级:1结合方向:从左向右例指向结构类型的指针变量例intn;int*p=&n;*p=10;n=10structstudentstu1;structstudent*p=&stu1;stu1.num=101;(*p).num=101main()structstudentlongintnum;charname20;charsex;floatscore;stu_1,*p;p=&stu_1;stu_1.num=89101;strcpy(stu_1.name,LiLin);p-sex=M;p-score=89.5;printf(nNo:%ldnname:%snsex:%cnscore:%fn,(*p).num,p-name,stu_1.sex,p-score);structstudentintnum;charname20;charsex;intage;stu3=10101,LiLin,M,18,10102,ZhangFun,M,19,10104,WangMin,F,20;main()structstudent*p;for(p=stu;pnum,p-name,p-sex,p-age);指向结构数组的指针例指向结构类型数组的指针numnamesexagestu0pstu1stu2p+1例6.2分析下面程序的运行结果#includevoidmain(void)structintx;inty;a2=1,2,3,4,*p=a;printf(“%d,”,+p-x);printf(“%dn”,(+p)-x);指向结构数组的指针pa0a1p123422,35结构数组结构数组的定义三种形式:形式一:structstudentintnum;charname20;charsex;intage;structstudentstu2;形式二:structstudentintnum;charname20;charsex;intage;stu2;形式三:structintnum;charname20;charsex;intage;stu2;numnamesexagenumnamesexagestu0stu125B结构数组初始化例structintnum;charname20;charsex;intage;stu=,;顺序初始化:structstudentintnum;charname20;charsex;intage;structstudentstu=100,“WangLin”,M,20,101,“LiGang”,M,19,110,“LiuYan”,F,19;例structstudentintnum;charname20;charsex;intage;stu=,;分行初始化:structstudentintnum;charname20;charsex;intage;structstudentstu=100,“WangLin”,M,20,101,“LiGang”,M,19,110,“LiuYan”,F,19;全部初始化时维数可省结构数组引用引用方式:结构数组名下标.成员名structstudentintnum;charname20;charsex;intage;str3;stu1.age+;strcpy(stu0.name,”ZhaoDa”);例统计后选人选票structpersoncharname20;intcount;leader3=“Li”,0,“Zhang”,0,”Wang“,0;main()inti,j;charleader_name20;for(i=1;i=10;i+)scanf(%s,leader_name);for(j=0;j3;j+)if(strcmp(leader_name,leaderj.name)=0)leaderj.count+;for(i=0;i3;i+)printf(%5s:%dn,leaderi.name,leaderi.count);namecountLiZhangWang000例例6.3 6.3 编程,输入编程,输入1010个学生的姓名和数学、英语和语文三门功个学生的姓名和数学、英语和语文三门功课的成绩,计算每个学生的平均成绩,并输出学生姓名和平均课的成绩,计算每个学生的平均成绩,并输出学生姓名和平均成绩。成绩。#include#define N 30struct studentchar name20;/*学生姓名学生姓名*/float math;/*数学成绩数学成绩*/float eng;/*英语成绩英语成绩*/float cuit;/*语文成绩语文成绩*/float aver;/*平均成绩平均成绩*/;void main(void)struct student sN;int i;for(i=0;iN;i+)printf(“请输入第请输入第%d学生的数据学生的数据n”,i+1);printf(“姓名:姓名:”);gets(si.name);printf(“数学、英语、语文成绩:数学、英语、语文成绩:”);scanf(“%f,%f,%f”,&si.math,&si.eng,&si.cuit);si.aver=(si.math+si.eng+si.cuit)/3.0;printf(“姓名姓名 平均成绩平均成绩n”);for(i=0;iN;i+)printf(“%s%6.1fn”,si.name,si.aver);例例6.4 6.4 输输入入N N个个整整数数,记记录录输输入入的的数数和和序序号号,按按从从小小到到大大的的顺顺序序排排列列(如如果果两两个个整整数数相相同同,按按输输入入的的先先后后次次序序排排列列)。输输出出排序以后的每个整数和它原来的序号。排序以后的每个整数和它原来的序号。#include#define N 10struct dataint no;int num;void main(void)struct data xN,temp;int i,j;/*输入输入10个整数个整数*/printf(“输入输入10个整数:个整数:”);for(i=0;iN;i+)scanf(“%d”,&xi.num);xi.no=i+1;/*排序排序*/for(i=0;iN-1;i+)for(j=0;jN-i-1;j+)if(xj.numxj+1.num)temp=xj+1;xj+1=xj;xj=temp;/*输出结果输出结果*/printf(“值值原来序号原来序号”);for(i=0;i=s,则第,则第k个人出列,转(个人出列,转(5),否则转(),否则转(4)(4)k更新为下一个小孩编号更新为下一个小孩编号 klinkk.next,转(转(2)(5)输出第)输出第k个小孩编号个小孩编号linkk.ino (6)linkk.ino0表示已经出列表示已经出列 (7)已经出列人数加)已经出列人数加1count (8)如果如果count等于总人数等于总人数n,则转(,则转(9),否则转(,否则转(2)(9)算法结束)算法结束#include#define N 100 /*程序能够处理的人数上限程序能够处理的人数上限*/void main()struct child int ino,next;linkN+1;int I,n_child,which,com_out,k,count;/*输入已知数据:小孩实际人数、初始报数小孩编号、出列的编号输入已知数据:小孩实际人数、初始报数小孩编号、出列的编号*/scanf(“%d%d%d”,&n_child,&which,&come_out);if(n_childN)printf(“too many to holdn”);else/*初始化队列初始化队列*/for(I=1;I=come_out)break;k=linkk.next;printf(“%dt”,linkk.ino);/*输出出队小孩编号输出出队小孩编号*/linkk.ino=0;/*第第k个小孩出队个小孩出队*/count+;/*出队人数加出队人数加1*/if(count%10=0)printf(“n”);printf(“bye!n”);例例6.5 编程实现两个复数的乘法运算。编程实现两个复数的乘法运算。分析:分析:一个复数由实部和虚部组成,可以用含有两个浮点数类型的成员的结构类型一个复数由实部和虚部组成,可以用含有两个浮点数类型的成员的结构类型来表示:来表示:struct complex float re;/*实部实部*/float im;/*虚部虚部*/;struct complex x,y;x*y的结果的实部为的结果的实部为x.re*y.re-x.im*y.im x*y的结果的虚部为的结果的虚部为x.re*y.im+x.im*y.re#include struct complex float re;float im;void main(void)struct complex x,y,z;printf(“请输入第请输入第1个复数个复数n”);printf(“实部:实部:”);scanf(“%f”,&x.re);printf(“虚部虚部”);scanf(“%f”,&x.im);printf(“请输入第请输入第2个复数个复数n”);printf(“实部:实部:”);scanf(“%f”,&y.re);printf(“虚部虚部”);scanf(“%f”,&y.im);z.re=x.re*y.re-x.im*y.im;z.im=x.re*y.im+x.im*y.re;printf(“两个复数相乘,结果:两个复数相乘,结果:”);if(z.im0)printf(“%8.2f%8.2fin”,z.re,z.im);else printf(“%8.2f+%8.2fin”,z.re,z.im);例例6.6 编程计算当前时间的下一秒的时间。编程计算当前时间的下一秒的时间。分析:分析:时间由时、分、秒构成,采用一个结构类型来表示时间:时间由时、分、秒构成,采用一个结构类型来表示时间:struct time int hour;/*时时*/int minutes;/*分分*/int second;/*秒秒*/;#include struct time int hour;int minutes;int second;void main(void)struct time now,ntime;printf(“请输入当前时间,时间格式:时:分:秒请输入当前时间,时间格式:时:分:秒n”);scanf(“%d:%d:%d”,&now.hour,&now.minutes,&now.second);ntime=now;ntime.second+;if(ntime.second=60)ntime.second=0;ntime.minutes+;if(ntime.minutes=60)ntime.minutes=0;ntime.hour+;if(ntime.hour=24)ntime.hour=0;printf(“下一秒时间:下一秒时间:%d:%d:%dn”,ntime.hour,ntime.minutes,ntime.second);引用自身的结构引用自身的结构例如,例如,struct tnodechar word20;int count;struct tnode*left;struct tnode*right;结构成员:指向自身所属的结结构成员:指向自身所属的结构类型的对象构类型的对象常用于构造各种数据结构:队列、链表、树、图等。常用于构造各种数据结构:队列、链表、树、图等。6 链表链表什么是链表?什么是链表?链接方式存接方式存储的的线性表性表简称称为链表(表(Linked List),是常见的数据结构。,是常见的数据结构。链表的具体存表的具体存储表示表示为:用一用一组任意的存任意的存储单元来存放元来存放线性表的性表的结点(点(这组存存储单元既可以是元既可以是连续的,也可以是不的,也可以是不连续的)的)链表中表中结点的点的逻辑次序和物理次序不一定相同。次序和物理次序不一定相同。为了能正确表示了能正确表示结点点间的的逻辑关系,在存关系,在存储每个每个结点点值的同的同时,还必必须存存储指示其后指示其后继结点的地址点的地址(或位置)信息(称(或位置)信息(称为指指针(pointer)或)或链(link))链表的表的结点点结构构datanext data域域-存放存放结点点值的数据域的数据域next域域-存放存放结点的直接后点的直接后继的地址(位置)的指的地址(位置)的指针域(域(链域)域)例如:例如:struct node int data;struct node*next;链表链表链表分类:链表分类:单链表:单链表:每个每个结点只有一个点只有一个链域的域的链表表。NULLhead链表分类:链表分类:循环链表循环链表headheadhead:链表的头指针:链表的头指针链表链表链表分类:链表分类:双向链表:双向链表:每个每个结点有点有两个两个链域的域的链表表。headNULLheadNULL链表链表静态链表静态链表例:例:#include#include struct nodeint data;struct node*next;void main()struct node a,b,c,*head,*p;a.data=1;b.data=2;c.data=3;head=&a;a.next=&b;b.next=&c;c.next=NULL;p=head;doprintf(“%dt”,p-data);p=p-next;while(p!=NULL);NULLhead123链表中结点都在程序中定链表中结点都在程序中定义,不是临时开辟的,用义,不是临时开辟的,用完后不能释放,并且,链完后不能释放,并且,链表中可以创建的结点数有表中可以创建的结点数有限制。称为限制。称为“静态链表静态链表”链表链表对链表的操作对链表的操作 建立链表、遍历链表、删除链表中的结点、插入结点建立链表、遍历链表、删除链表中的结点、插入结点 以单链表为例进行说明。以单链表为例进行说明。建立链表建立链表(尾插法建表)尾插法建表)结点类型:结点类型:struct child char name20;struct child*next;*new,*head,*tail;(1)头指针置空头指针置空head=NULL;(2)创建新结点创建新结点new=(struct child*)malloc(sizeof(struct child);new-next=NULL;(3)新结点连入链表新结点连入链表 if(head=NULL)head=new;tail=new;else tail-next=new;重复(重复(2)、()、(3)步直到链表创建完成。)步直到链表创建完成。headnewNULL先进先出链表 建立链表建立链表(头插法建表)头插法建表)(1)头指针置空头指针置空head=NULL;(2)创建新结点创建新结点new=(struct child*)malloc(sizeof(struct child);(3)新结点连入链表新结点连入链表 new-next=head;head=new;重复(重复(2)、()、(3)步直到链表创建完成。)步直到链表创建完成。headnewNULLhead后进先出链表 建立链表建立链表(在链表中间插入结点):一般用于建立有序链表在链表中间插入结点):一般用于建立有序链表(1)head=NULL;(2)创建新结点创建新结点new=(struct child*)malloc(sizeof(struct child);(3)找到标记结点找到标记结点marker(新结点插入在标记结点的后面)(新结点插入在标记结点的后面)(4)新结点连入链表新结点连入链表 new-next=marker-next;marker-next=new;重复(重复(2)、()、(3)、()、(4)步直到链表创建完成。)步直到链表创建完成。headnewNULLmarker 遍历链表:将整个链表的数据从头到尾扫描一遍遍历链表:将整个链表的数据从头到尾扫描一遍 p=head;while(p!=NULL)puts(p-name);/*输出当前结点数据输出当前结点数据*/p=p-next;/*p更新为下一个结点地址更新为下一个结点地址*/从链表中删除结点从链表中删除结点(1)找到要删除的结点,)找到要删除的结点,current指向该结点,指向该结点,p指向要删指向要删除结点的前趋结点。除结点的前趋结点。(2)如果要删除的结点为头结点,则)如果要删除的结点为头结点,则 head=current-next;(3)如果要删除的结点不是头结点,则)如果要删除的结点不是头结点,则 p-next=current-next(4)释放已经删除的结点)释放已经删除的结点 free(current);NULLheadcurrent插入结点:插入结点:将一个结点插入一个已经存在的链表中,例如插入在链表尾部、头部或将一个结点插入一个已经存在的链表中,例如插入在链表尾部、头部或者插入在一个有序链表中。者插入在一个有序链表中。向一个有序链表中插入新结点(向一个有序链表中插入新结点(new)。(1)找到要插入结点的位置,插入在)找到要插入结点的位置,插入在r指向的结点前面,指向的结点前面,p指向的结点后面。指向的结点后面。(2)如果要插入在头结点前面,则)如果要插入在头结点前面,则new-next=head;head=new;(3)如果要插入的位置不是头结点前面,则)如果要插入的位置不是头结点前面,则 new-next=r;p-next=new;