第九章结构体、共用体、枚举类型1/289.1结构体的定义及引用9.2结构体数组9.3结构体与指针9.5共用体的概念9.6枚举类型9.7类型标识符的自定义9.9本章要点小结2/28§9.1结构体的定义及引用9.1.1概述有时候需要将不同类型的数据组合成一个有机的整体,这些组合在一个整体中的数据是互相联系的。如一个学生的信息包括学号、姓名、性别、年龄、成绩、地址等。numnamesexagescoreaddr5001LiMingM1996.5Chengduintnum;charname[20];charsex;intage;floatscore;charaddr[30];应当把它们组织成一个组合项,在一个组合项内包含若干个类型不同(或相同)的数据项。C语言提供了这种数据结构:允许用户将不同类型的数据组合成一个有机的整体,这些数据互相联系;这种数据结构称为结构体(structure)。3/289.1.2结构体类型标识符的定义所谓结构体的定义,是指定义相应的数据结构及相应的变量。步骤:①、先定义一个结构体类型标识符;②、用该标识符去定义相应的变量。structstudent{intnum;charname[20];charsex;intage;floatscore;charaddr[30];};说明:①、struct是关键字,不能省略:表示将要进行结构体的定义;②、student是用户自己定义的结构体类型标识符,即该结构体名;③、结构体中具体每项的定义,由{和}括起来。C语言中把用户自己定义的数据项称为成员(或称为域),即每个成员也叫结构体中的一个域。4/28定义一个结构体类型的一般形式:struct结构体类型标识符{类型标识符1成员名1;类型标识符2成员名2;…………类型标识符n成员名n;};结构体名成员表列说明:①、“结构体名”用作结构体类型的标志;②、大括弧内是该结构体中的各个成员,由它们组成一个结构体;在结构体内对各成员都应进行类型声明;③、“成员表列”也称为域表。每个成员也称为结构体中的一个域,成员名命名规则与变量名一样;④、每个成员名前的类型标识符可以为已经定义了的任意类型,当然可以是结构体类型标识符,即结构体成员也可以是另一个结构体变量。⑤、此处只是构造出一个新的类型,并没有定义该类型的变量,因此在内存中并没有开辟任何存储空间;⑥、在程序中可以定义多个结构体类型,不同结构体类型用不同的结构体名来区分。5/289.1.3结构体变量的定义1、定义形式:struct结构体类型标识符变量名列表;注意:结构体类型标识符要和关键字struct一起使用。2、定义结构体变量的三种方法:①、先定义结构体类型再定义变量名structstudent{intnum;charname[20];floatscore;};structstudentstu1,stu2;结构体类型名结构体变量名10001Zhang9210002Li97stu1stu2在定义了结构体变量后,系统会为之分配内存单元。sizeof(stu1)=2+20+4=266/28②、在定义结构体类型的同时定义变量struct结构体类型标识符{类型标识符1成员名1;类型标识符2成员名2;…………类型标识符n成员名n;}变量名列表;structstudent{intnum;charname[20];floatscore;}stu1,stu2;③、直接定义结构体类型变量struct{类型标识符1成员名1;类型标识符2成员名2;…………类型标识符n成员名n;}变量名列表;(不出现结构体类型名)struct{intnum;charname[20];floatscore;}stu1,stu2;7/284、关于结构体类型的几点说明:①、类型与变量是不同的概念,不要混淆:a、只能对变量赋值、存取或运算,而不能对一个类型赋值、存取或运算;b、在编译时,对类型不分配内存空间,只对变量分配空间。②、只有在定义变量后,才为该变量开辟存储单元。结构体变量所占的内存长度等于每个成员长度之和;structstudent{intnum;charname[20];floatscore;};sizeof(structstudent)=26③、对结构体中的成员(“域”),可以单独使用,它的作用与地位相当于普通变量;8/28④、成员也可以是一个已定义的结构体类型变量:structdate{intyear;intmonth;intday;};structstudent{intnum;charname[20];charsex;structdatebirthday;charaddr[30];};sizeof(structstudent)=?⑤、成员也可以是指向本结构体类型的指针变量;structstudent{intnum;charname[20];floatscore;structstudent*next;};⑥、成员名可以与程序中的变量名相同,二者不代表同一对象。9/289.1.4结构体变量的引用1、引用形式:结构体变量名.成员名“.”是成员运算符,在所有的运算符中优先级最高。structstudent{intnum;charname[20];floatscore;}stu1,stu2;stu1.num=10001;stu1.score=95;stu1.name=LiMing;strcpy(stu1.name,LiMing);2、不能将一个结构体变量作为一个整体进体输入输出:printf(%d%s%f,stu1);scanf(%d%s%f,&stu1);只能对结构体中的各个成员分别进行输入输出。printf(%d%s%f,stu1.num,stu1.name,stu1.score);scanf(%d,&stu1.num);gets(stu1.name);Eg901.cpp10/28成员名也是一个变量(称为成员变量),具有自己的数据类型,使用与同类型的变量相同。3、只有在对结构体变量赋值或作为函数参数时才可以对一个结构体变量进行整体操作;(赋值时要求具有相同结构)stu2=stu1;stu2.num=stu1.num;strcpy(stu2,name,stu1.name);stu2.score=stu1.score;voidfun(structstudentpx);fun(stu1);4、如果成员本身又属于一个结构体类型,则要用若干个成员运算符,一级一级的找到最低一级的成员。只能对最低一级的成员进行赋值、存取或运算;stu1.birthday.year=2002;5、对成员变量可以像普通变量一样进行各种运算(根据其类型决定可以进行的运算)sum=stu1.score+stu2.score;stu1.age++;11/286、可以引用结构体变量成员的地址,也可以引用结构体变量的地址;scanf(%d,&stu1.num);printf(%x,&stu1);结构体变量的地址主要用于作函数参数,传递结构体变量的地址;7、在定义结构体变量的同时,可以进行初始化。structstudent{intnum;charname[20];charsex;charaddr[30];}stu={15001,宋红,'M',123RoadBeijing};注意:结构体变量的各个初值用大括号{、}括起来,大括号内各个成员变量的值之间用逗号分隔,其值必须与成员变量一一对应,且数据类型应与成员变量一致。Eg902.cpp例9.1:输入5名学生的学号及成绩,求成绩最好的学生的学号及成绩。12/28§9.2结构体数组数组的每个元素都是结构体类型的数据,它们分别包含各个成员项。9.2.1结构体数组的定义1、先定义结构体类型,再定义结构体数组structstudent{intnum;floatscore;};structstudentstu[30];2、定义结构体类型的同时定义结构体数组structstudent{intnum;floatscore;}stu[30];3、直接定义结构体数组struct{intnum;floatscore;}stu[30];13/289.2.2结构体数组的初始化一般形式:struct结构体类型标识符{类型标识符1成员名1;类型标识符2成员名2;…………类型标识符n成员名n;}结构体数组={{数组元素0的各个初值},{数组元素1的各个初值},……};例:structstudent{intnum;charname[20];floatscore;}stu[3]={{10101,LiMing,88},{10102,ZhangJin,92},{10103,WangLin,98.5}};14/28说明:1、初始化时,数组元素的个数可以不指定,系统会根据初值的结构体常量的个数来确定数组元素的个数;structstudent{intnum;charname[20];floatscore;}stu[]={{10101,LiMing,88},{10102,ZhangJin,92},{10103,WangLin,98.5}};structstudent{intnum;charname[20];floatscore;};stu[]={{10101,LiMing,88},{10102,ZhangJin,92},{10103,WangLin,98.5}};2、数组中各个元素的初值用大括号{、}括起来,同一数组元素的各个成员变量的初值用逗号分隔。15/289.2.3结构体数组应用举例1、若有如下定义:structaa{longnum;charname[20];};structbb{intage;structaafirst;}stu[2];①、要给stu[1]输入18、990001、zhanghuabin,写出所用到的语句;②、要把'z'、'h'、‘b'变成大写,如何实现?③、如何将stu[1]中的名字复制到stu[0]中的相应位置上?2、设李红、王建、赵明三名同学某学年考了8门课,要求分别统计出这3名同学该学年的总成绩,并按8门课总成绩的高低排序输出。Eg903.cpp16/28§9.3结构体与指针结构体变量的指针就是该变量所占据的内存段的起始地址。9.3.1指向结构体变量的指针1、指向结构体变量指针的定义:structstudent{intnum;charname[20];floatscore;};structstudentstu,*p;p=&stu;p中存放着结构体变量stu在内存中的首地址注意:不能用指向结构体变量的指针指向该结构体变量的某个成员。p=&stu.num;int*ip;ip=&stu.num;17/28①、stu.num、stu.name、stu.score②、(*p).num、(*p).name、(*p).score③、p-num、p-name、p-score2、访问结构体成员变量的三种方法:3、说明:①、“-”为指向运算符,是优先级最高的运算符;②、成员运算符“.”的优先级高于指针运算符“*”,因此采用“(*p).成员名”形式时,括号不能省略;③、注意以下几种运算:p-num得到p指向的结构体变量中的成员num的值p-num++得到p指向的结构体变量中的成员num的值,用完后该值加1++p-num使p指向的结构体变量中的成员num的值加14、例:指向结构体变量的指针的应用Eg904.cpp18/289.3.2指向结构体数组的指针指向结构体变量的指针变量,可以指向结构体变量,也可以指向同类型的结构体数组的元素。structstudent{intnum;charname[30];floatscore;}stu[30],*p;p=stu;p=&stu[3];p=&stu[2].num;p只能指向一个structstudent类型的数据(某个元素的的起始地址),不能指向一个成员变量。注意:①、若p的初值为stu,p+1后指向下一元素的起始地址;(++p)-num先使p自加1,然后得到它指向元素的num成员值++p-