2009-7-28 1
第 7章结构体、共同体和枚举类型
2009-7-28 2
结构体类型的说明在实际问题中,一组数据往往具有不同的数据类型
。例如,在学生登记表中,姓名 应为字符型; 学号 可为整型或字符型; 年龄 应为整型; 性别 应为字符型;
成绩 可为整型或实型。 显然不能用一个数组来存放这一组数据。 因为数组中各元素的类型和长度都必须一致,以便于编译系统处理。为了解决这个问题,C ++
中给出了另一种构造数据类型 ——“结构,。 它相当于其它高级语言中的记录。
,结构,是一种构造类型,它是由若干,成员,组成的。 每一个成员可以是一个基本数据类型或者又是一个构造类型。 结构既是一种,构造,而成的数据类型,那么在 使用之前必须先定义它,也就是构造它。
如同在说明和调用函数之前要先定义函数一样。
2009-7-28 3
结构体类型的说明一般格式:
struct 结构类型名 //struct是结构类型关键字
{数据类型 数据项 1;
数据类型 数据项 2;
…… ……
数据类型 数据项n ;
}; //此行分号不能少!
如,struct stu{ //定义学生情况结构体
int num; //学号
char name[20]; //姓名
char sex; //性别
float score; //成绩
};
定义了结构的组成,未分配存储单元
2009-7-28 4
结构定义之后,即可进行变量说明。 凡说明为结构 stu的变量都由上述 4个成员组成。由此可见
,结构 是一种复杂的数据类型,是数目固定、类型不同的若干有序变量的集合。
例 1,定义一个反映学生基本情况的结构类型,用以存储学生的相关信息。
//功能:定义一个反映学生基本情况的结构类型
struct date //日期结构类型:由年、月、日三项组成
{int year;
int month;
int day;
};
2009-7-28 5
struct std_info //学生信息结构类型
{char no[7]; //学号
char name[9]; //姓名
char sex[3]; //性别
struct date birthday; //生日
};
struct score
//成绩结构类型由学号和三门课共 4项组成
{char no[7]; //学号
int score1; //成绩 1
int score2; //成绩 2
int score3; //成绩 3
};
2009-7-28 6
注,( 1)“结构类型名”和“数据项”的命名规则
,与变量名相同。
( 2)数据类型相同的数据项,既可逐个、逐行分别定义,也可合并成一行定义。
如:例 1中 score类型也可改为如下形式:
struct score//成绩结构类型和三门共 4项组成
{char no[7]; //学号
int score1,score2,score3; //三门成绩
};
( 3)结构类型中的数据项,既可以是基本数据类型,也允许是另一个已经定义的结构类型。
如:例 1代码中的结构类型 std_info,其数据项
,birthday”就是一个已经定义的日期结构类型 date。
2009-7-28 7
( 4)定义结构体的成员时,不能指定成员的存储类为 auto,register,extern,这是由于系统不为结构体类型分配任何存储空间,但可以指定成员的存储类型为 static。
如,struct test{
auto int i,j;
//不正确,不能指定自动存储类型
register int x;
//不正确,不能指定为寄存器存储类型
extern int f;
//不正确,不能指定为外部存储类型
static int y;
//正确,可指定为静态存储类型
};
2009-7-28 8
定义结构体类型变量可有三种方法定义结构体类型变量:
1,先定义结构,再说明结构变量。如:
struct stu{
int num;
char name[20];
char sex;
float score;
};
struct stu boy1,boy2; //说明变量 boy1和 boy2为
stu结构类型
2009-7-28 9
也可以用宏定义使一个符号常量来表示一个结构类型。如:
#define STU struct stu
STU{
int num;
char name[20];
char sex;
float score;
};
STU boy1,boy2;
2009-7-28 10
2,在定义结构类型的同时说明结构变量。如:
struct stu{
int num;
char name[20];
char sex;
float score;
}boy1,boy2;
3,直接说明结构变量。如:
struct{
int num;
char name[20];
char sex;
float score;
}boy1,boy2;
2009-7-28 11
注,( 1) 由于第三种定义方法没有定义类型名,
也就无法再定义这种类型的变量。建议使用前两种方法来定义结构体类型的变量。
( 2)在大型程序中,通常将所有定义的结构体类型集中存放在一个或几个头文件中,在程序文件中用到某一种结构体类型的变量时,只需要包含相应的头文件即可。
2009-7-28 12
S1,S2分配存储空间的结构
name 20个字节
id 4个字节
addr 40个字节
tel_num 7个字节
eng 4个字节
phy 4个字节
math 4个字节
ave 4个字节例 2,用三种方法定义结构体类型变量。 71
2009-7-28 13
( 3)结构体类型变量也有作用域问题,与一般变量的作用域相同,即在函数定义外定义的结构体类型变量为 文件作用域 ;在函数体内定义的变量为 块作用域 。同样,结构体名也有作用域,与变量作用域相同。
( 4)定义结构体变量时,可指定其存储类型。如:
static s1 s2;
auto s1 stru2;
extern s1 stru3;
2009-7-28 14
( 5)定义结构体变量时,可进行初始化。方法是用花括号将每个成员的值括起来。如:
s1 a3={“张三”,“南京”,,445681”,23};
特别强调,初始化时,花括号内的值的类型及顺序必须与该结构体类型定义的结构体成员一一对应。 如:
s1 a4={“张三”,“南京”,445681,23} //错误
s1 a5={“张三”,“南京”,,4456819”,23} //
错误
//第三个值超过长度 8
2009-7-28 15
结构体类型变量及其成员的使用对于结构变量,要通过成员运算符,.”,逐个访问其成员,且访问的格式为:
结构变量,成员 //其中的,.”是成员运算符如,student.no表示引用结构变量 student中的 no成员; student.name表示引用结构变量 student中的
name成员,等等。
2009-7-28 16
如果某成员本身又是一个结构类型,则只能通过多级的分量运算,对最低一级的成员进行引用。
此时的引用格式扩展为:
结构变量,成员,子成员,…,最低级子成员如:引用结构变量 student中的 birthday成员的格式分别为:
student.birthday.year,student.birthday.month,
student.birthday.day
2009-7-28 17
注,( 1)对最低一级成员,可像同类型的普通变量一样,进行相应的各种运算。
( 2)既可引用结构变量成员的地址,也可引用结构变量的地址。如:
&student.name,&student 。
( 3)同类型的结构体变量之间可直接赋值。如:
struct test{
int m,n;
char name[20];
};
test s1={45,100,,zhang ming”},s2,s3;
s2=s1;
最后一行等同于:
s2.m=s1.m;
s2.n=s1.n;
strcpy( s2.name,s1.name);
2009-7-28 18
( 4)结构体类型变量不能直接进行输入 /输出,每个成员是否能直接输入 /输出取决于其类型,当是 基本类型 或 字符数组,则可以直接进行输入 /输出。如:
cin>>s3; //错误
cin>>s3.m>>s3.name; //正确
( 5)结构体类型变量可作为函数的参数,函数也可返回结构体的值。当函数的形参与实参为结构体类型的变量时,这种结合方式属于值调用方式,即属于值传递,只能用作输入参数,在函数中能使用结构体成员的值或结构体类型变量的值,但不能用作输出参数,不能将在函数内修改后的结构体成员值作为参数返回。 例 3,结构体类型变量用作函数的参数。
72
2009-7-28 19
执行后输出:
r1.m=100 r1.x=250.5
r2.m=200 r2.x=350.5
sum.m=300 sum.x=601
结构体数组数组的元素也可以是结构类型的。 因此可以构成 结构体数组 。结构体数组的每一个元素都是具有相同结构类型的下标结构变量。
在实际应用中,经常用结构体数组来表示具有相同数据结构的一个群体。如一个班的学生档案,一个车间职工的工资表等。
2009-7-28 20
结构体数组的定义方法和结构变量相似,只需说明它为数组类型即可。如:
struct stu{
int num;
char *name;
char sex;
float score;
}boy[5];
定义了一个结构体数组 boy,共有 5个元素,boy[0]
~ boy[4]。每个数组元素都具有 struct stu的结构形式

2009-7-28 21
对结构体数组可以作初始化赋值,如:
struct stu{
int num;
char *name;
char sex;
float score;
}boy[5]={{101,"Li ping","M",45},
{102,"Zhang ping","M",62.5},
{103,"He fang","F",92.5},
{104,"Cheng ling","F",87},
{105,"Wang ming","M",58};
};
当对全部元素作初始化赋值时,也可不给出数组长度。
2009-7-28 22
例 4,用两种方法初始化结构体数组。
73
执行后输出,15 60 70
10 100 100
0 0 0
1 60 30
4 80 90
两种给结构体变量赋初值的方法:
( 1)如上页例。
( 2)在一个花括号内依次列出各个元素的成员值。
建议使用第一种方法赋值。
2009-7-28 23
例 5,建立一个学生档案的结构体数组,描述一个学生的信息:姓名、性别、年龄和课程 C++的成绩,
并输出已建的学生档案。
74
该方法是利用的值调用方式,效率较低,若将形参改为引用类型的结构体类型变量,程序效率会更高,系统开销会更小。修改后为:
741
2009-7-28 24
结构体类型的静态成员当把结构体类型中的某一个成员的存储类型定义为静态时,表示在这种结构体类型的所有变量中,编译程序为该成员只分配一个存储空间,即所有变量共同使用该成员的存储空间。
例 6,静态成员的初始化及其应用。
75执行后输出,s1.id=50
s2.id=200
s1.id=200
s3.id=400
s2.id=400
s1.id=400
2009-7-28 25
注,( 1)结构体中说明的静态成员属引用性说明,
应在文件作用域中的某一地方对静态的成员进行定义性说明,且仅能说明一次。
( 2)程序中语句:
int s::id=50;
为对成员 id的定义性说明,且同时初始化了。若该语句改为:
int s::id;
则 id的初值为 0。
( 3)符号,::”称为作用域运算符,表示 id属于结构类型 s的成员。对结构体的静态成员进行定义性说明的一般格式为:
类型 结构体类型名,,静态成员名;
2009-7-28 26
( 4)结构体中的成员可为已定义的任意类型,也可以是结构体类型的成员。如:
struct date{
int year,month,day;
};
struct s{
char name[20];
int id;
date d1;
};
s s1;

s1.d1.year=1999; s1.d1.day=2;
2009-7-28 27
共同体的定义及应用共同体类型在实际问题中有很多这样的例子。 例如在学校的教师和学生中填写以下表格,姓名 年龄 职业 单位 对,单位,一项学生应填入 班级编号,教师应填入 某系某教研室 。 班级可用整型量表示,教研室只能用字符类型。 要求把这两种类型不同的数据都填入,单位,这个变量中,就必须把,单位,定义为包含整型和字符型数组这两种类型的,共同体,。
使几个不同的变量占用同一段内存空间的结构称为共同体 。
2009-7-28 28
共同体类型的定义 ──与结构类型的定义类似:
union 共用类型名 {
成员列表;
};
共同体类型变量的说明及使用与说明结构体类型变量的方法类似,有三种方法:
( 1)先定义共同体类型,再定义共同体类型变量。
( 2)在定义共同体类型的同时,定义共同体类型变量。
( 3)不定义共同体类型名,直接定义共同体类型变量。
2009-7-28 29
如,union data{
char c;
int j;
};
data d1,d2; //先定义类型,后定义共同体变量 d1,d2
在特定时刻,共同体只有一个成员被保存,而不提供其它成员的信息。
作用域分辨符
2009-7-28 30
union data1{
char c1;
int j1;
}x1,x2,x3; //同时定义类型与变量 x1,x2,x3
union{
char c;
int j;
float x;
}a,b,c; //不定义类型,直接定义共同体变量使用共同体成员的一般格式:
共同体变量名,成员名如 x.c1=?a?; a.i=25;
2009-7-28 31
( 1) 在共同体中,各成员共享一段内存空间,一个共同体变量的长度等于各成员中最长的长度。如:
union{
char c1; //c1占 1个字节
char s[3]; //s占 3个字节
float x; //x占 4个字节
}y;
故 y分配 4个字节的空间,三个成员共同使用。
( 2)这里所谓的共享不是指把多个成员同时装入一个共同体变量内,而是指该共同体变量可被赋予任一成员值,但每次只能赋一种值,赋入新值则冲去旧值。 如在学校的教师和学生表格中的“单位”栏中只能是班级或某系某教研室。
共同体数据类型的特点
2009-7-28 32
( 3)共同体类型变量不能直接输入 /输出,作函数参数时作为值传递。
( 4)同类型的共同体可相互赋值。
( 5)共同体类型的成员可是已定义的任一类型,
也可是共同体或结构体,同样结构体类型的成员也可是共同体。
2009-7-28 33
枚举类型在实际问题中,有些变量的取值被限定在一个有限的范围内。例如,一个星期 内只有七天,一年 只有十二个月,一个班 每周有六门课程等等。如果把这些量说明为整型,字符型或其它类型显然是不妥当的。 为此
,C ++提供了一种称为,枚举,的类型。在,枚举,
类型的定义中列举出所有可能的取值,被说明为该,
枚举,类型的变量取值不能超过定义的范围。
应该说明的是,枚举类型是一种基本数据类型,而不是一种构造类型,因为它不能再分解为任何基本类型。
2009-7-28 34
枚举类型的定义:
enum 枚举类型名 {取值表 };
如,enum weekdays
{Sun,Mon,Tue,Wed,Thu,Fri,Sat};
枚举类型、枚举类型变量及使用注:( 1)枚举类型的元素称为 标识符常量,命名规则同标识符。程序执行时每个枚举类型元素用一个整数来表示。编译时,给枚举类型定义中列举的每个元素指定一个整型常量值。
( 2) 枚举元素作为常量是有值的 ──定义时的顺序号 ( 从0开始 ),所以枚举元素可以进行比较,
比较规则是,序号大者为大 ! 如:上例中的 Sun=0、
Mon=1,……,Sat=6,所以
Mon>Sun,Sat最大 。
2009-7-28 35
( 3)枚举元素的值也是可以人为改变的:在定义时由程序指定。如:
若 enum weekdays {Sun=4,Mon=1,Tue,Wed,
Thu,Fri,Sat};
则 Sun=4,Mon=1,从 Tue=2开始,依次增1。
( 4)不同的枚举元素可取相同的值,如上例中 Sun与
Thu都取 4,也可以给不同的枚举元素指定相同的值,
如:
enum weekdays {Sun=4,Mon=1,Tue,Wed,
Thu,Fri=4,Sat};
不同的枚举元素指定相同的值没有什么意义 。
( 5)枚举型仅适应于取值有限的数据。如:
根据现行的历法规定,1周7天,1年 12个月。
2009-7-28 36
( 6)枚举类型变量的说明与结构体类型变量类似。
a)第一种方法:
enum 枚举类型名 变量 1,变量 2,…,变量 n;
或 枚举类型名 变量 1,变量 2,…,变量 n;
如,colors c1,c2;
b)第二种方法:
enum 枚举类型名 {
枚举量表
}变量 1,变量 2,…,变量 n;
如,enum col{red,blue,black}x1,x2,x3;
c)第三种方法:
enum{
枚举量表
}变量 1,变量 2,…,变量 n;
如,enum{Sun,Mon,Wed,Thu,
Fri,Sat}day1,day2,day[20];
2009-7-28 37
建议使用前两种,因为第三种不能再说明与 day1
同类型的枚举变量。
( 7)说明枚举变量类型时可对其进行初始化。
如,col col1=red;
( 8)枚举类型变量只能使用赋值运算符和关系运算符。
可将枚举量表中列举的任一枚举常量赋给枚举类型变量,同类型的枚举变量可相互赋值。如:
day1=Sun; day2=day1;
枚举类型变量不能直接从键盘上输入。 如:
cin>>day1; //错误枚举类型变量可以直接输出,但输出的值是一个整数 (对应枚举常量的序号)。如:
day1=Sun;
cout<<day1; //输出值为 0
2009-7-28 38
例 7,输入 0~6,并将之转换为对应的枚举量 Sunday
,Monday,…,Saturday。
76
例 8,设口袋中有红、黄、蓝、白、黑五种颜色的球若干,每次从口袋中取出 3个不同颜色的球,计算出所有不同的取法。
分析,用枚举量 red,yellow,blue,while,black分别表示红、黄、蓝、白、黑五种颜色的球。计算不同的取球方法是一个组合问题。设取出的三个球为 i
,j,k,它们分别可以取以上五个枚举量之一的值,
并且满足条件,i,j,k的值均不相同。可以使用穷举法依次列出每一种取法。 77
也可用如下程序,761
2009-7-28 39
程序执行后输出:
1 red yellow blue
2 red yellow white
3 red yellow black
4 red blue yellow
5 red blue white
6 red blue black
7 red white yellow
8 red white blue
9 red white black
10 red black yellow
……
57 black blue yellow
58 black blue white
59 black white red
60 black white blue
2009-7-28 40
1.结构体类型是一种导出数据类型,定义结构体类型变量前需先定义结构体类型;
2.共同体是若干个变量共同使用同一个存储空间;
3.枚举是一种基本数据类型。枚举变量的取值是有限的,枚举元素是常量,不是变量。
本章小结