第8章结构体结构体共用体2思考一个问题在程序里表示一个人的信息(姓名、年龄、性别、……),怎么表示?表示多个人呢?如何用计算机程序实现下述表格的管理?表8-1某学校学生成绩管理表学号姓名性别入学时间计算机原理英语数学音乐1令狐冲男1999908372822林平之男1999789288783岳灵珊女1999897298664任莹莹女1999789587905……6……3数组的解决方法intstudentId[30];/*最多可以管理30个学生,每个学生的学号用数组的下标表示*/charstudentName[30][10];charstudentSex[30][2];inttimeOfEnter[30];/*入学时间用int表示*/intscoreComputer[30];/*计算机原理课的成绩*/intscoreEnglish[30];/*英语课的成绩*/intscoreMath[30];/*数学课的成绩*/intscoreMusic[30];/*音乐课的成绩*/4数组的解决方法intstudentId[30]={1,2,3,4,5,6};charstudentName[30][10]={{令狐冲},{林平之},{岳灵珊},{任莹莹}};charstudentSex[30][2]={{男},{男},{女},{女}};inttimeOfEnter[30]={1999,1999,1999,1999};intscoreComputer[30]={90,78,89,78};intscoreEnglish[30]={83,92,72,95};intscoreMath[30]={72,88,98,87};intscoreMusic[30]={82,78,66,90};5数组的解决方法数据的内存管理方式90788978……83927295……72889887……82786690……1234……令狐冲林平之岳灵珊任莹莹……男男女女……1999199919991999……6数组的解决方法分配内存不集中,寻址效率不高对数组进行赋初值时,容易发生错位结构显得比较零散,不容易管理7希望的内存分配图1令狐冲男1999908372822林平之男1999789288783岳灵珊女1999897298664任莹莹女1999789587908结构体的解决方法structSTUDENT{intstudentID;/*每个学生的序号*/charstudentName[10];/*每个学生的姓名*/charstudentSex[4];/*每个学生的性别*/inttimeOfEnter;/*每个学生的入学时间*/intscoreComputer;/*每个学生的计算机原理成绩*/intscoreEnglish;/*每个学生的英语成绩*/intscoreMath;/*每个学生的数学成绩*/intscoreMusic;/*每个学生的音乐成绩*/};structSTUDENT是一个类型structSTUDENTstudents[4];students[0].studentNamestudents[0].Sex它们都是变量,一般称为结构的成员变量9§8.1结构体的定义•结构体类型的定义•结构体类型变量的引用•结构体变量的初始化10structstudent{intnum;charname[20];charsex;intage;charaddr[30];};是数据类型,不是变量名对各成员都要进行类型说明;成员名定名规则与变量名同。一、结构体类型的定义一般形式为:struct结构体名{成员表列};11方法一:先定义结构体类型再定义变量名structstudent{intnum;charname[20];charsex;intage;charaddr[30];};structstudentstudent1,student2;定义studet1和sudent2为structstudent类型变量结构体类型变量的定义12•有时,可用符号常量代表一个结构体类型,如:#defineSTUDENTstructstudentSTUDENT{intnum;charname[20];charsex;intage;charaddr[30];};这样,可直接用STUDENT定义变量,如:STUDENTstudent1,student2;此时,不必再写关键字struct13方法二:在定义类型的同时定义变量structstudent{intnum;charname[20];charsex;intage;charaddr[30];}student1,student2;一般形式是:struct结构体名{成员列表}变量名列表;14方法三:直接定义结构类型变量。其一般形式是:struct{成员表列}变量名表列;此时,不出现结构体名15typedef的用法功能:定义新类型,即为C语言中已有的数据类型名定义一个新名字。定义格式:typedef标识符1标识符216structstudent{intnum;charname[20];charsex;intage;floatscore;charaddr[30];};typedefstructstudentSTUD;STUDstudent1,student2;用typedef为已存在的类型定义新名字用STUD代替structstudent类型;17几点说明:1.类型与变量是不同概念,不要混淆;2.结构体中的成员,可以单独使用,其作用与地位相当于普通变量;3.成员名可以与程序中的变量名相同,二者不代表同一对象。18structdate{intmonth;intday;intyear;};Structstudent{intnum;charname[20];intage;structdatebirthday;}student1,student2;4.成员也可以是一个结构体变量;例如:19规则:1.不能将一个结构体变量作为一个整体进行赋值和输出;只能对其各个成员分别输出printf(“………..”,student1);printf(“%d”,student1.num);错!正确!引用形式为:结构体变量名.成员名二、结构体类型变量的引用203.对成员变量可以象普通变量一样进行各种运算,如:sumage=student1.age+student2.age;4.可以引用成员的地址,也可以引用结构体变量的地址,如scanf(“%d”,&student1.num);printf(“%x”,&student1);scanf(“%d,%s,%c,%d,%s”,&student1);错!输入student1.num的值输出student1的首地址2.若成员本身又属一个结构体类型,只能对最低级的成员进行赋值或存取以及运算。如:student1.birthday.year21(一)对外部存储类型的结构体变量初始化:structstudent{longintnum;charname[20];charsex;charaddr[20];}a={9801,”Wanghong”,’W’,”2LinggongRoad”};main(){printf(“No.:%ld\nname:%s\nsex:%c\naddress:%s\n”,a.num,a.name,a.sex,a.addr);}运行结果为:No.:9801name:Wanghongsex:Waddress:2LinggongRoad三、结构体变量的初始化22main(){staticstructstudent{longintnum;charname[20];charsex;charaddr[20];}a={9801,”Wanghong”,’W’,”2LinggongRoad”};printf(“No.:%ld\nname:%s\nsex:%c\naddress:%s\n”,a.num,a.name,a.sex,a.addr);}(二)对静态存储类型的结构体变量初始化23(一)结构体数组的定义structstudent{intnum;charname[20];charsex;intage;charaddr[30];};structstudntstu[3];也可直接定义,如structstudent{intnum;…}stu[3];或struct{intnum;…}stu[3];§8.2结构体数组(每个数组元素都是一个结构体类型的数据)24structstudent{intnum;charname[20];charsex;intage;charaddr[30];}stu[3]={{111,”Li”,’M’,18,”Dalian”},{…},{…}};结构体数组初始化的一般形式是在定义数组后面加上:={初值表列};也可采用:structstudent{intnum;…};structstudentstu[]={{…},{…},{…}};(二)结构体数组的初始化(只能对全局的或静态存储类别的数组初始化)25structperson{charname[20];intcount;}leader[3]={{“Li”,0},{”zhang”,0},{”Liu”,0}};main(){inti,j;charleader_name[20];for(i=1;i=10;i++){scanf(“%s”,leader_name);for(j=0;j3;j++)if(strcmp(leader_name,leader[j].name)==0)leader[j].count++;}for(i=0;i3;i++)printf(“%5s:%d\n”,leader[i].name,leader[i].count);}例题:设有三个候选人,每次输入一个得票的候选人的名字,要求最后输出各人得票结果。26例如:main(){structstudent{longintnum;charname[20];charsex;};structstudentstu_1;structstudent*p;p=&stu_1;Stu_1.num=9901;strcpy(stu_1.name,“LiMin”);stu_1.sex=‘W’;printf(“No.:%ld\nname%s\nsex:%c\n”,stu_1.num,stu_1.name,stu_1.sex);printf(“\nNo.:%ld\nname%s\nsex:%c\n”,(*p).num,(*p).name,(*p).sex);}结构体变量的指针:是该结构体变量所占居的内存段的起始地址。§8.3指向结构体类型数据的指针27引用结构体成员的三种形式:结构体变量名.成员名(*p).成员名p-成员名指向运算符。其优先级高于自增、自减运算符试分析以下运算:成员运算符得到p指向的结构体变量中的成员n的值使其先加1++(p-n)得到p指向的结构体变量中的成员n的值,用完后使它加1;(p-n)++得到p指向的结构体变量中的成员n的值p-n28for(pt=stu;ptstu+30;pt++){sum[0]=sum[0]+pt-scoreComputer;sum[1]=sum[1]+pt-scoreEnglish;sum[2]=sum[2]+pt-scoreMath;sum[3]=sum[3]+pt-scoreMusic;}for(i=0;i4;i++){average[i]=sum[i]/4;printf(%20s:%4.2f\n,name[i],*(average+i));}例8.2:利用指向结构体数组的指针计算学生各科的平均成绩(教材310页)学号姓名性别入学时间计算机原理年月日英语数学音乐29例8.2main(){structSTUDENT*pt;floatsum[4]={0.0},average[4]={0.0};inti;char*name[]={scoreofComputer,scoreofE