第11章结构体、共用体和枚举 引言: 设计程序量最重要的一个步骤是选择一个表示数据的好方法。在多数情况下,使用简单 的变量甚至数组都是不够的。C使用结构体变量进一步增强了表示数据的能力。结构体是 可能具有不同值的集合:联合体和结构体很类似,不同之处在于联合体的成员共享一段存 储空间。这样的结果是,联合体可以每次存储一个成员,但无法同时存储全部的成员。枚 举是一种整数类型,它的值由程序员米命名。 结构体是最重要的一种类型,所以本章主要介绍结构体类型以及结构体变量的定义、 初始化、引用以及其他应用,最后简单介绍共用体、枚举以及typedefine等相关知识。 11.1示例问题:学生成绩管理的例子 实际生活中我们经常碰到信息统计的题目。比如学生成绩管理题目:要求输入学生的 学号、姓名、五门课的成绩,并计算每个学生五门课的平均分,并按平均分计算名次,若 平均分相同则名次并列。最后输出统计结果。 题目中计算平均分和排序我们前面的章节中分析过此类题目,所以单就每个学生的平 均成绩或者根据成绩排出名次我们都应该比较熟悉。根据前面学习的知识,我们可以定义 一个整型数组保存学生的学号,然后再定义一个二维的字符数组保存学生的姓名,最后我 们定义一个数值型的二维数组保存每个学生五门课的成绩。可最好的方式不是将数据分割 存储,而是作为一个整体存放。那就需要一种新的结构形式,其中既可以包括字符串,又 可以包括数值型数据,还可以保存这些信息。C语言的结构体就满足了这种需要。 为了了解C语言如何构造结构体并使用它,我们将问题简化为只要求输入一个学生的 信息并输出。后面我们再将内容慢慢扩展。示例程序如下: Winclude <stdio.h> struct student int num; /成员变量学号 char name[30】: //成员变量姓名 float score[5l: //成员变量分数 /结构体类型的定义 int main() struct student stu;/定义stu为studentent类型的变量 int i, printf("Please input the information of studentents:\n")
第 11 章 结构体、共用体和枚举 引言: 设计程序最重要的一个步骤是选择一个表示数据的好方法。在多数情况下,使用简单 的变量甚至数组都是不够的。C 使用结构体变量进一步增强了表示数据的能力。结构体是 可能具有不同值的集合;联合体和结构体很类似,不同之处在于联合体的成员共享一段存 储空间。这样的结果是,联合体可以每次存储一个成员,但无法同时存储全部的成员。枚 举是一种整数类型,它的值由程序员来命名。 结构体是最重要的一种类型,所以本章主要介绍结构体类型以及结构体变量的定义、 初始化、引用以及其他应用,最后简单介绍共用体、枚举以及 typedefine 等相关知识。 11.1 示例问题:学生成绩管理的例子 实际生活中我们经常碰到信息统计的题目。比如学生成绩管理题目:要求输入学生的 学号、姓名、五门课的成绩,并计算每个学生五门课的平均分,并按平均分计算名次,若 平均分相同则名次并列。最后输出统计结果。 题目中计算平均分和排序我们前面的章节中分析过此类题目,所以单就每个学生的平 均成绩或者根据成绩排出名次我们都应该比较熟悉。根据前面学习的知识,我们可以定义 一个整型数组保存学生的学号,然后再定义一个二维的字符数组保存学生的姓名,最后我 们定义一个数值型的二维数组保存每个学生五门课的成绩。可最好的方式不是将数据分割 存储,而是作为一个整体存放。那就需要一种新的结构形式,其中既可以包括字符串,又 可以包括数值型数据,还可以保存这些信息。C 语言的结构体就满足了这种需要。 为了了解 C 语言如何构造结构体并使用它,我们将问题简化为只要求输入一个学生的 信息并输出。后面我们再将内容慢慢扩展。示例程序如下: #include <stdio.h> struct student { int num; //成员变量学号 char name[30]; //成员变量姓名 float score[5]; //成员变量分数 }; //结构体类型的定义 int main() { struct student stu; //定义 stu 为 studentent 类型的变量 int i,j; printf("Please input the information of studentents:\n");
scanf("多d路s",stu.num,stu.name):/结构体成员变量的引用 for(j=0:j<5:j++) //输入该学生5门课的成绩 scanf("&f",&stu.score【i】); printf("The information of studentents are:\n") printf("学号\t姓名\t科目一\t科目二\t科目三\t科目四\t科目五\n"): printf("&d\tss\ts.2f\t8.2f\t8.2f\t8,2f\ts.2f\n",stu.num,stu.name, stu.score[0],stu.score[1],stu.score[2],stu.score[3],stu.score[4]) return 0; 1 程序运行结果; Please input the information of studentents: 1101Mi11v/ 10099898685/ The information of studentents are: 学号姓名科日一科目三科目三科目四科目五 1101Mi11y100.0099.00 89.00 86.00 85.00 在上面的参考程序中,结构体student包括了三个成员变量:num、namc和score,分 别表示学生的学号、姓名和五门课的成绩。结构体student类型定义了一个变量stu,程序 通过su来获得对三个成员变量的引用。 由此得知,我们在使用结构体表示数据的时候,要先定义结构体类型,再定义该结构 体类型的变量,最后才能引用结构体变量的各成员变量, 11.2结构体 11.2.1结构体类型的定义 分析清楚一个对象信息各个组成部分就形成一个完整的结构体。结构体类型定义的 般形式如下: struct结构体类型名 数据类型成员名表1: 数据类型成员名表2: 数据类型成员名表n: 1: 成员名表中每个成员都是该结构体的一个组成部分,成员的数据类型必须是已经存在
2 scanf("%d%s",&stu.num,stu.name); //结构体成员变量的引用 for( j=0;j<5;j++) //输入该学生 5 门课的成绩 scanf("%f",&stu.score[j]); printf("The information of studentents are:\n"); printf("学号\t 姓名\t 科目一\t 科目二\t 科目三\t 科目四\t 科目五\n"); printf("%d\t%s\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\n",stu.num,stu.name, stu.score[0],stu.score[1],stu.score[2],stu.score[3],stu.score[4]); return 0; } 程序运行结果: Please input the information of studentents: 1101 Milly ↙ 100 99 89 86 85↙ The information of studentents are: 学号 姓名 科目一 科目二 科目三 科目四 科目五 1101 Milly 100.00 99.00 89.00 86.00 85.00 在上面的参考程序中,结构体 student 包括了三个成员变量:num、name 和 score,分 别表示学生的学号、姓名和五门课的成绩。结构体 student 类型定义了一个变量 stu,程序 通过 stu 来获得对三个成员变量的引用。 由此得知,我们在使用结构体表示数据的时候,要先定义结构体类型,再定义该结构 体类型的变量,最后才能引用结构体变量的各成员变量。 11.2 结构体 11.2.1 结构体类型的定义 分析清楚一个对象信息各个组成部分就形成一个完整的结构体。结构体类型定义的一 般形式如下: struct 结构体类型名 { 数据类型 成员名表 1; 数据类型 成员名表 2; . 数据类型 成员名表 n; }; 成员名表中每个成员都是该结构体的一个组成部分,成员的数据类型必须是已经存在
的类型。成员名的命名要符合标识符的命名规定。例如对于一个学生成绩登记表,其结构 体类型如下: struct student int num; /1学生的学号 char name[301;/学生的姓名 float score[5] /学生的五门课的成绩 }; 说明:struct是结构体类型的标识,是C语言关键字。结构体类型名是student,该结 构由5个成员组成。第1个成员num是整型变量,第2个成员name是长度为30的字符数 组,第3个成员scor©是长度为5的浮点型数组。括号“0”后的分号表示类型定义结束, 是不可少的。 注意:结构体类型定义后,与其他系统定义的数据类型一样,并不占有内存存储空间。 11.2.2结构体类型变量的定义 定义结构体变量有以下三种方法。 1.先定义结构体类型,再定义结构体变量 例如,利用前面的结构体类型student定义结构体变量: struct student stul,stu2; 说明:定义两个变量stul和stu2是student结构体类型 2.在定义结构体类型时,定义结构体变量 例如: struct student int num; char name[30]; float score[5]; Istul.stu2: 这种定义形式的一般形式为: struct结构体类型名 数据类型成员名表1: 数据类型成员名表n: )变量名表列: 3.不写结构体类型名,直接定义结构体类型变量
3 的类型。成员名的命名要符合标识符的命名规定。例如对于一个学生成绩登记表,其结构 体类型如下: struct student { int num; //学生的学号 char name[30]; //学生的姓名 float score[5]; //学生的五门课的成绩 }; 说明:struct 是结构体类型的标识,是 C 语言关键字。结构体类型名是 student,该结 构由 5 个成员组成。第 1 个成员 num 是整型变量,第 2 个成员 name 是长度为 30 的字符数 组,第 3 个成员 score 是长度为 5 的浮点型数组。括号“{}”后的分号表示类型定义结束, 是不可少的。 注意:结构体类型定义后,与其他系统定义的数据类型一样,并不占有内存存储空间。 11.2.2 结构体类型变量的定义 定义结构体变量有以下三种方法。 1.先定义结构体类型,再定义结构体变量 例如,利用前面的结构体类型 student 定义结构体变量: struct student stu1,stu2; 说明:定义两个变量 stu1 和 stu2 是 student 结构体类型。 2.在定义结构体类型时,定义结构体变量 例如: struct student { int num; char name[30]; float score[5]; }stu1,stu2; 这种定义形式的一般形式为: struct 结构体类型名 { 数据类型 成员名表 1; . 数据类型 成员名表 n; }变量名表列; 3.不写结构体类型名,直接定义结构体类型变量
例如: struct int num; char name30] float score[5] )stul,stu2 这种定义形式的一般形式为: struct 数据类型成员名表1: 数据类型成员名表n: 变量名表列 第三种方法与第二种方法的区别在于第三种方法中省略了结构体类型名,而是直接给 出结构体类型变量。 在上述student结构体类型定义中,所有的成员都是基本数据类型或数组类型。结构体 成员实际上也可以是已经定义的一个结构体类型。 例如下面的例子: struct date int month,day,year; 1; struct int numa char name [20],sex,tele[12] struct date birthday; f1 oat score:/score此例中不是一个数组 )stul,stu2; 说明:先定义一个结构体类型date,date有month、day、year三个成员,在定义变量 stul和stu2时,其成员birthday被说明为date结构体类型, 注意:定义结构体类型变量后,系统在内存中为该变量分配连续的内存单元。结构体类型 变量的首地址称为该变量的地址,结构体变量占用的内存空间长度并不简单其全部成员占 用的内存空间长度总和,需要根据内存对齐原理来计算。在实际计算时可以直接使用szCo) 得出结构体变量所占的存储空间的大小。 11.2.3结构体类型变量的引用与赋值 4
4 例如: struct { int num; char name[30]; float score[5]; }stu1,stu2; 这种定义形式的一般形式为: struct { 数据类型 成员名表 1; . 数据类型 成员名表 n; }变量名表列; 第三种方法与第二种方法的区别在于第三种方法中省略了结构体类型名,而是直接给 出结构体类型变量。 在上述 student 结构体类型定义中,所有的成员都是基本数据类型或数组类型。结构体 成员实际上也可以是已经定义的一个结构体类型。 例如下面的例子: struct date { int month,day,year; }; struct { int num; char name[20],sex,tele[12]; struct date birthday; float score; //score 此例中不是一个数组 }stu1,stu2; 说明:先定义一个结构体类型 date,date 有 month、day、year 三个成员,在定义变量 stu1 和 stu2 时,其成员 birthday 被说明为 date 结构体类型。 注意:定义结构体类型变量后,系统在内存中为该变量分配连续的内存单元。结构体类型 变量的首地址称为该变量的地址,结构体变量占用的内存空间长度并不简单其全部成员占 用的内存空间长度总和,需要根据内存对齐原理来计算。在实际计算时可以直接使用 sizeof() 得出结构体变量所占的存储空间的大小。 11.2.3 结构体类型变量的引用与赋值
在定义了结构体类型变量以后,可以引用这个变量,并且在引用时也可以对变量进行 赋值。 1。结构体类型变量成员的引用 对结构体类型变量的引用是通过结构体类型变量的成员来实现的。引用结构体类型变 量成员的一般形式为: 结构体类型变量名,成员名 例如:stul.num表示变量stul的num成员,stul.sex表示变量stul的sex成员。 注意:如果结构体成员本身又是一个结构体美型,则必须逐级找到最低级的成员才能 使用。例如:stul,birthday.month表示stul的birthday成员的month成员。 其中,“,”是成员运算符,它在所有运算符中优先级最高,因此可以把stul.birthday.month 作为一个整体来使用。 虽然stu1和su2是一个结构,但对结构体类型变量的成员的使用可以像普通变量一样。 例如: scanf ("f",&stul.score) 2.结构体类型变量的赋值 结构体类型变量的赋值就是给它的成员赋值,赋值方式由结构体类型变量成员的数据 类型决定,相同类型的结构体变量可以相互直接赋值。 【例111】结构体类型变量的使用。 程序如下: #include <stdio.h> struct student int num: char *name; int main() stul.num=102; stul.name="Zhang ping"; printf("input sex and score\n"); scanf("8c 8f",&stul.sex,&stul.score) 8+112=g+111: /将tu1的所有成员的值整体赋予tu2 printf ("\",stu2.u,stu2.name): ex=8c\nScore-8f\n sex,stu2.score) return 0; 5
5 在定义了结构体类型变量以后,可以引用这个变量,并且在引用时也可以对变量进行 赋值。 1.结构体类型变量成员的引用 对结构体类型变量的引用是通过结构体类型变量的成员来实现的。引用结构体类型变 量成员的一般形式为: 结构体类型变量名.成员名 例如:stu1.num 表示变量 stu1 的 num 成员,stu1.sex 表示变量 stu1 的 sex 成员。 注意:如果结构体成员本身又是一个结构体类型,则必须逐级找到最低级的成员才能 使用。例如:stu1.birthday.month 表示 stu1 的 birthday 成员的 month 成员。 其中,“.”是成员运算符,它在所有运算符中优先级最高,因此可以把 stu1.birthday.month 作为一个整体来使用。 虽然stu1和stu2是一个结构,但对结构体类型变量的成员的使用可以像普通变量一样。 例如: scanf(“%f”,& stu1.score); stu1.score=stu2.score; x=stu1.score+stu2.score; 2.结构体类型变量的赋值 结构体类型变量的赋值就是给它的成员赋值,赋值方式由结构体类型变量成员的数据 类型决定,相同类型的结构体变量可以相互直接赋值。 【例 11.1】 结构体类型变量的使用。 程序如下: #include <stdio.h> struct student { int num; char *name; char sex; float score; } stu1,stu2; int main() { stu1.num=102; stu1.name="Zhang ping"; printf("input sex and score\n"); scanf("%c %f",&stu1.sex,&stu1.score); stu2=stu1; // 将 stu1 的所有成员的值整体赋予 stu2 printf("Number=%d\nName=%s\n",stu2.num,stu2.name); printf("Sex=%c\nScore=%f\n",stu2.sex,stu2.score); return 0; }