《第08章.结构体和枚举类型.ppt》由会员分享,可在线阅读,更多相关《第08章.结构体和枚举类型.ppt(92页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第8章结构体和枚举类型 本章要点:教学目标教学目标本章讲解结构和结构变量的定义格式、结构成员的表示、结构变量的赋初值和赋值、结构变量的运算。在此基础上进一步讲述结构与指针、结构与数组、结构与函数的应用。教学重点和难点教学重点和难点 结构体类型的定义 定义和初始化结构体变量 类型定义typedef 结构体数组 结构体指针 结构体与函数 单向链表及其操作 枚举类型在现实生活中,有许多不同性质的数据实体。比如,通讯录通常由姓名、电话、E-mail、年龄等组成。姓名、电话、E-mail和所在城市可以用字符串表示,年龄可以用整型数表示。可是它们的每一项都是单独使用的,不能反映通讯录这样一个整体。用什么方
2、法表示通讯录这个整体呢?新的被称为结构体的数据类型。为我们处理复杂的数据提供了便利的手段。8.1.1 什么是结构体结构体(structure)是一种数据类型,它把互相联系的数据组合成一个整体。例如,下面的表格显示了一个通讯录的信息:表8-1 一个通讯录的信息表一个通讯录中有姓名、电话、性别、年龄、E-mail地址、所在城市,这些信息都是和一个叫“李明”的人有关。如果我们只把这些信息分别定义为独立的简单变量,就体现不出它们之间的相互关联了。所以,应当把它们组织成一个组合项,在一个组合项中包含若干个类型不同的数据项。用“结构体”来定义。8.1 结构体类型8.1.2 结构体的定义结构体既然是一种数据
3、类型,在使用前,先要“定义”出要使用的结构体类型。例:将通讯录定义成一个结构体。通讯录的信息由六项属性组成,首先要给这个结构体类型定义取一个名字,比如“AddressList”。然后,应该在结构体定义中对各属性进行说明。下面就是“通讯录”结构体类型:struct AddressListchar name20;/*姓名姓名*/char telephone12;/*电话电话*/char sex;/*性别性别*/int age;/*年龄年龄*/char e_mail40;/*电子邮件电子邮件*/char addr30;/*地址地址*/;8.1 结构体类型其中,“struct”是关键字,是结构体的标识
4、符,不能省略。“AddressList”是结构体类型名,它由我们自己进行命名的。“”中是结构体的成员,每个成员的数据类型既可以是简单的数据类型,也可以是复杂的数据类型,当然也可以是其他结构体数据类型。最后,定义完一个结构体后一定要用一个分号“;”结束。从上面这个例子,可以看出结构体定义格式如下:8.1 结构体类型struct 名字 成员说明1;成员说明2;成员说明3;成员说明n;;可以定义许多复杂的数据类型。比如,定义一个表示日期的结构体:struct dateint year;/*年年*/int month;/*月月*/int day;/*日日*/;用日期这种结构体,我们就可以表示生日、开学
5、时间、春节等等这样的日期。8.1 结构体类型也可把两种结构体类型结合起来,“造出”更复杂的结构体。比如,一个通讯录的结构体中包含了表示出生日期的结构体struct date:struct AddressListchar name20;/*姓名姓名*/char telephone12;/*电话电话*/char sex;/*性别性别*/int age;/*年龄年龄*/char e_mail40;/*电子邮件电子邮件*/char addr30;/*地址地址*/struct date birthday;/*出生日期出生日期*/;8.1 结构体类型我们先“造出”一个日期的结构体类型,同时我们又在通讯录这
6、个结构体中,将出生日期这个成员变量定义为日期类型,这样通讯录结构体就变成更复杂一些的数据类型了。这样的结构可以叫做嵌套型的结构体,其结构可以如图8-1示意:图8-1 嵌套型的结构体示意8.1 结构体类型nametelephonesexageemailaddryearmonthdaybirthday8.1.3 定义结构体变量既然我们定义的结构体是一种数据类型,就可以像int、char、float这样的数据类型一样来使用,定义结构体类型的变量。用结构体类型定义变量的方式有如下几种:1.先定义结构体类型,再定义变量例,定义一个通讯录结构体:struct AddressListchar name20;
7、/*姓名姓名*/char telephone12;/*电话电话*/char sex;/*性别性别*/int age;/*年龄年龄*/char e_mail40;/*电子邮件电子邮件*/char addr30;/*地址地址*/;/*定义定义2个结构体变量个结构体变量*/struct AddressList AddressList1,AddressList2;8.1 结构体类型定义了两个“AddressList”结构体类型的变量AddressList1和AddressList2。它们可以分别表示两个人的通讯录,比如:AddressList1:AddressList2:图8-2 结构体变量8.1 结
8、构体类型结构体变量中的各个成员,在内存中是顺序存放的。各成员变量所占内存的大小是根据定义时它们的数据类型来决定。为了方便,也可以这样定义结构体变量:#define ADDRESSLIST struct AddressListADDRESSLISTchar name20;/*姓名姓名*/char telephone12;/*电话电话*/char sex;/*性别性别*/int age;/*年龄年龄*/char e_mail40;/*电子邮件电子邮件*/char addr30;/*地址地址*/;ADDRESSLIST AddressList1,AddressList2;8.1 结构体类型定义的这个
9、符号常量“ADDRESSLIST”,它就代表了结构体类型“struct AddressList”。这样,在未来的程序设计中,“ADDRESSLIST”可以和“struct AddressList”完全等效使用了。2.在定义结构体类型的同时声明变量struct AddressListchar name20;/*姓名姓名*/char telephone12;/*电话电话*/char sex;/*性别性别*/int age;/*年龄年龄*/char e_mail40;/*电子邮件电子邮件*/char addr30;/*地址地址*/AddressList1,AddressList2;8.1 结构体类型
10、这种方式和前面定义的方式效果一样,在定义结构体的同时,定义了2个struct AddressList类型的变量AddressList1,AddressList2。这种方式通常用于函数中使用的局部结构体变量。3.直接定义变量还可以用下面的方式直接定义结构体变量:struct/*省略结构体名称省略结构体名称*/char name20;/*姓名姓名*/char telephone12;/*电话电话*/char sex;/*性别性别*/int age;/*年龄年龄*/char e_mail40;/*电子邮件电子邮件*/char addr30;/*地址地址*/AddressList1,AddressLi
11、st2;8.1 结构体类型这种方式没有给出结构体名,通常也用于函数中使用的局部结构体变量。注意:1)对于结构体变量,在定义时,一定要先定义一个结构体类型,然后再定义该类型的变量。只能对结构体变量赋值、存取或运算,但不能对一个结构体类型进行这些操作;2)对结构体中的组成成员,可以单独使用,它的作用相当于普通变量。4.类型定义typedef在编写程序的过程中,为了便于修改和表达清晰,我们往往还可以给数据类型取别名,在C+语言中叫做类型定义。类型定义的关键字是typedef,其使用格式为:8.1 结构体类型typedef 数据类型标识符 别名;比如我们给整型标识符int取个别名,叫做Integer,
12、可以这样写:typedef int Integer;Integer k;这样定义的变量k就是一个整型数。8.1 结构体类型同样可以对一个结构体进行类型定义,也就是给这个结构体取个别名。比如给前面定义的通讯录取个别名,并用别名定义变量:typedef struct AddressListchar name20;/*姓名姓名*/char telephone12;/*电话电话*/char sex;/*性别性别*/int age;/*年龄年龄*/char e_mail40;/*电子邮件电子邮件*/char addr30;/*地址地址*/ADDR_LIST;/*定义定义2个个struct Address
13、List类型的变量类型的变量*/ADDR_LIST AddressList1,AddressList2;或者:struct AddressListtypedef struct AddressList ADDR_LIST;也可省略结构体的名称AddressList,写成如下的形式:typedef structADDR_LIST;8.1 结构体类型8.1.4 结构体变量的初始化1.结构体整体初始化声明一个结构体变量时,可以对它进行初始化,这和初始化一个数组是类似的。结合上面定义的通讯录结构体类型struct AddressList,我们定义了一个struct AddressList变量one,并对
14、它进行初始化:struct AddressList one=李明李明,01062548445,M,16,北京北京;8.1 结构体类型注意:不能在定义结构体类型的时候,进行赋初值。例如:struct AddressList/*下面的做法就是错误的下面的做法就是错误的*/char name=Li Lin;char telephone12=010-62281234;char sex=M;int age=18;char e_mail40=;char addr30=123 Bejing Road;one;例8.1 定义一个结构体变量,并进行整体初始化,再输出其结果内容。程序清单 C08_01.cpp#i
15、nclude/*结构体定义部分结构体定义部分*/struct AddressListchar name20;/*姓名姓名*/char telephone12;/*电话电话*/char sex;/*性别性别*/int age;/*年龄年龄*/char e_mail40;/*电子邮件电子邮件*/char addr30;/*地址地址*/;8.1 结构体类型void main()/*定义并初始化结构体变量定义并初始化结构体变量*/struct AddressList one=李明李明,01062548445,M,16,北京北京;/*结构体变量的输出结构体变量的输出*/cout 我们定义并初始化的结构体
16、是:我们定义并初始化的结构体是:n endl;cout 姓名是:姓名是:one.name endl 电话号码是:电话号码是:one.telephone endl;cout 性别是:性别是:one.sex endlcout 所在城市是:所在城市是:one.addr endl;8.1 结构体类型输出结果:我们定义并初始化的结构体是:我们定义并初始化的结构体是:姓名是:李明姓名是:李明电话号码是:电话号码是:01062548445性别是:性别是:M年龄是:年龄是:16E-mail地址是:地址是:所在城市是:北京所在城市是:北京其中的“one.name”、“one.telephone”是通过“.”运算
17、符访问结构体变量的成员。一般情况下,不能将一个结构体变量作为整体来使用,只能使用其中的成员(分量)。使用结构体成员的方式:8.1 结构体类型结构体变量名.成员名通过这种方式,我们就可以使用结构体变量one中的成员了。例:cout one.name ,one.telephone ,one.sex ,one.age ,one.e_mail ,one.age;8.1 结构体类型3.逐级访问成员在前面曾经定义了包含生日的通讯录结构体,生日这个成员变量又是日期结构体类型。对于生日这个成员变量,我们可以一级一级访问其成员。例如:AddressList1.birthday.month=9;AddressLi
18、st1.birthday.day=20;AddressList1.birthday.year=1994;8.1 结构体类型4.把结构体变量当作整体赋值只有在以下两种情况下,才可以把结构体变量作为一个整体来赋值和访问。1)结构体变量整体赋值例:AddressList2=AddressList1;通过这种模式,可以直接完成结构体之间的赋值。2)取结构体变量地址例如:cout AddressList1.telephone;/*输入输入AddressList1的电话的电话*/需要注意,不能把结构体变量整体输入进来。例如:cin AddressList1;我们在使用结构体变量时,通常把结构体变量的地址用
19、作函数的参数,以实现传地址调用。8.1 结构体类型8.1.5 结构体数组我们知道,一个结构体变量可以存放一组相关的数据(例如,一个通讯录可以存放一个人的姓名、电话、性别、年龄、E-mail和地址等信息),正如前面引入数组一样,我们也可以定义一个数组,其每一成员都是一个结构体,它们都分别包含多个成员变量。1.结构体数组的定义我们在定义结构体数组之前,首先要进行结构体类型的定义。然后再像以前介绍过的数组定义方式定义结构体数组。8.1 结构体类型例如,我们定义一个具有3个元素的通讯录结构体数组:/*定义结构体类型定义结构体类型*/typedef struct AddressListchar name
20、20;/*姓名姓名*/char telephone12;/*电话电话*/char sex;/*性别性别*/int age;/*年龄年龄*/char e_mail40;/*电子邮件电子邮件*/char addr30;/*地址地址*/ADDR_LIST;/*定义结构体数组定义结构体数组*/ADDR_LIST addlist3;/*定义有定义有3个元素的结构体数组个元素的结构体数组*/这样就定义了一个具有3个元素的结构体数组,这些数组元素在内存中是连续存放的。8.1 结构体类型2.结构体数组的初始化我们可以把结构体初始化和数组元素初始化结合起来,对结构体数组进行初始化。经过初始化,就可以分别输出结构
21、体数组元素的值。例8.2 结构体数组的初始化。程序清单 C08_02.cpp#include typedef struct char name20;/*姓名姓名*/char telephone12;/*电话电话*/char sex;/*性别性别*/int age;/*年龄年龄*/char e_mail40;/*电子邮件电子邮件*/char addr30;/*地址地址*/ADDR_LIST;8.1 结构体类型void Print(ADDR_LIST*,int Count);void main()/*定义并初始化结构体变量定义并初始化结构体变量*/ADDR_LIST addrlist3=李明李明,
22、01062548445,M,16,北京北京,王芳王芳,02162281234,F,20,上海上海,Marry,02786614571,F,19,武武汉汉,;Print(addrlist,3);8.1 结构体类型void Print(ADDR_LIST*List,int Count)int i;/*结构体变量的输出结构体变量的输出*/cout 我们定义并初始化的结构体数组的数据如下:我们定义并初始化的结构体数组的数据如下:nn;for(i=0;i Count;i+)cout 第第 i+1 个记录:个记录:endl;cout 姓名:姓名:Listi.name endl;cout 电话号码:电话号码
23、:Listi.telephone endl;cout 性别:性别:Listi.sex endl;cout 年龄:年龄:Listi.age endl;cout E-mail:Listi.e_mail endl;cout 所在城市:所在城市:Listi.addr endl;cout endl;8.1 结构体类型输出结果我们定义并初始化的结构体数组的数据如下:我们定义并初始化的结构体数组的数据如下:第第1个记录:个记录:姓名:李明姓名:李明电话号码:电话号码:01062548445 性别:性别:M 年龄:年龄:16 E-mail:所在城市:北京所在城市:北京第第2个记录:个记录:姓名:王芳姓名:王芳
24、电话号码:电话号码:02162281234 性别:性别:F 年龄:年龄:20 E-mail:所在城市:上海所在城市:上海8.1 结构体类型第第3个记录:个记录:姓名:姓名:Marry电话号码:电话号码:02786614571 性别:性别:F 年龄:年龄:19 E-mail:所在城市:武汉所在城市:武汉8.1 结构体类型8.1.6 结构体指针结构体指针,就是一个结构体类型的指针,它指向一个结构体变量。这和整型指针、字符指针是一样的。其实例8.2的Print函数中就使用了结构体指针作为形参(*List)。1.结构体指针我们再看一个应用结构体指针的小例子。例8.3 我们定义一个表示某人生日的结构体变
25、量,同时定义一个结构体指针指向它,分别通过结构体变量和结构体指针输出结构体成员的值,观察其结果的不同。8.1 结构体类型程序清单 C08_03.cpp/*结构体变量和结构体指针的关系结构体变量和结构体指针的关系*/#include/*结构体类型定义,其中结构体结构体类型定义,其中结构体date是结构体是结构体PERSON的成员变量的成员变量*/struct dateint month;/*表示月,从表示月,从112*/int day;/*表示日期,从表示日期,从131*/int year;/*表示年表示年*/;/*定义结构体类型,并且是复合(成员变量是结构体类型)类型定义结构体类型,并且是复合
26、(成员变量是结构体类型)类型*/typedef structint No;/*序号序号*/char name20;/*姓名姓名*/struct date birthday;/*出生日期出生日期*/PERSON;8.1 结构体类型void main()PERSON Users;/*定义定义Users是一个结构体变量是一个结构体变量*/PERSON*p;/*定义定义*p是一个结构体指针是一个结构体指针*/cout 请输入结构体变量的信息:请输入结构体变量的信息:n;cout Users.No;/*Users.No是整型变量是整型变量*/cout Users.name;/*Users.name字符数
27、组的名字符数组的名字,其表示地址字,其表示地址*/cout Users.birthday.year Users.birthday.month Users.birthday.day;p=&Users;/*将结构体变量将结构体变量Users的地址赋值给指针的地址赋值给指针p*/cout n通过结构体变量输出的结果是:通过结构体变量输出的结果是:n;cout 序号:序号:Users.No endl8.1 结构体类型 姓名:姓名:Users.name endl 生日:生日:Users.birthday.year Users.birthday.month Users.birthday.day endl;
28、cout n通过结构体指针变量输出的结果:通过结构体指针变量输出的结果:n;cout 序号:序号:(*p).No endl 姓名:姓名:(*p).name endl 生日:生日:(*p).birthday.year (*p).birthday.month (*p).birthday.day”表示为“p-No”。同样,“(*p).name”也等价于“p-name”。因此,下面三种形式是等价的:Users.成员名成员名(*p).成员名成员名p-成员名成员名有了这些规则,我们可以把上面“通过结构体指针变量输出”的语句改为:printf(序号是:序号是:%dn姓名是:姓名是:%sn生日是:生日是:%d
29、-%d-%dn,p-No,p-name,p-birthday.month,p-birthday.day,p-birthday.year);其中“-”称为指向运算符。8.1 结构体类型2.指向结构体数组的指针指针和数组之间的关系十分密切:如果指针p指向数组的某个特定元素,那么p+1就指向该数组中下一个元素,p+i指向该元素后面第i个元素,p-i指向该元素之前第i个元素。同样,对结构体数组及其元素也可以用指针变量来指向。例,我们在例8.2中定义了一个结构体数组,并进行了初始化。现在我们用指向结构体数组的指针进行操作,结果会是怎么样呢?例8.4 定义一个结构体数组变量,进行数组元素的整体初始化,并利
30、用指向结构体数组的指针输出结构体的数据。8.1 结构体类型程序清单 C08_04.cpp#include/*结构体定义部分结构体定义部分*/struct AddressListchar name20;/*姓名姓名*/char telephone12;/*电话电话*/char sex;/*性别性别*/int age;/*年龄年龄*/char e_mail40;/*电子邮件电子邮件*/char addr30;/*地址地址*/;typedef struct AddressList ADDR_LIST;/*将此结构体类型定义为将此结构体类型定义为ADDR_LIST*/8.1 结构体类型void mai
31、n()/*定义并初始化结构体变量定义并初始化结构体变量*/ADDR_LIST List3=李明李明,01062548445,M,16,北京北京,王芳王芳,02162281234,F,20,上海上海,Marry,02786614571,F,19,武汉武汉,;ADDR_LIST*p;/*定义一个指向结构体类型的指针定义一个指向结构体类型的指针*/*结构体变量的输出结构体变量的输出*/cout 用指向结构体数组的指针输出的结构体变量值是:用指向结构体数组的指针输出的结构体变量值是:n;for(p=List;p List+3;p+)cout endl;cout 姓名:姓名:name endl 电话号码
32、:电话号码:telephone endl;cout 性别:性别:sex endl 年龄:年龄:age endl;8.1 结构体类型cout e_mail:e_mail endl;cout 所在城市:所在城市:addr telephone”先使p自加1,然后得到它指向的元素中的telephone成员值,即“List1.telephone(02162281234)”。“(p+)-telephone”先得到“p-telephone”的值,即01062548445,然后再p自加1,即指向List1。2)如果定义p是结构体类型ADDR_LIST的指针,它只能指向一个此结构体类型的变量。例如,下面这样描述
33、是错误的:p=&addrlist0.name;/*错误错误*/8.1 结构体类型8.1.7 结构体与函数有时,我们想把一个结构体变量的值传递给另一个函数,用什么方法呢?可以利用前面学过函数的传值调用,既可以传递单个结构体成员也可以传递整个结构体。例如:用List0.name或List0.telephone作函数的实参,通过函数调用将实参值传递给形参。这种用法和用普通变量作实参没有任何区别,都是“值传递”方式,被调用函数无法修改主调函数中的结构体变量成员。如果我们需要被调用函数能改变主调函数中结构体变量成员,该用什么方法呢?通过指针的学习,自然使我们想到可以用指向结构体变量的指针作实参,或将结构
34、体变量的地址作为实参调用函数。比起传值调用,传地址方式不需要对整个结构体做一份拷贝,只需要把结构体变量的地址传递给函数就可以了。8.1 结构体类型图 8-5 回顾:传值和传地址调用的比较示意8.1 结构体类型主调函数被调函数函数形参(a)传值调用实际参数复制主调函数被调函数函数形参(b)传引用调用实际参数指向先让我们看一看指针指向结构体变量的小例子!例8.5 用结构体变量的地址作为实参调用函数。定义一个结构体包括学生的学号、姓名和三门主课(数学、语文、英语)的成绩和平均分。在主函数main定义此结构体变量Exam,调用函数GetInfo()输入赋值到Exam,再调用函数Comp()计算平均分并
35、输出。程序清单 C08_05.cpp#include typedef structint math;/*数学成绩数学成绩*/int chinese;/*语文成绩语文成绩*/int english;/*英语成绩英语成绩*/SCORE;8.1 结构体类型typedef structint No;/*学号学号*/char Name20;/*姓名姓名*/SCORE Score;/*三门成绩三门成绩*/int Average_score;/*平均分平均分*/Information;/*函数声明部分函数声明部分*/void GetInfo(Information*p);/*从键盘输入数据从键盘输入数据*/
36、void Comp(Information*p);/*计算平均分计算平均分*/void main()Information Exam;/*定义一个学生信息的结构体变量定义一个学生信息的结构体变量*/GetInfo(&Exam);/*输入结构体变量的成员值,用地址作为参数输入结构体变量的成员值,用地址作为参数*/Comp(&Exam);/*用地址作为参数用地址作为参数*/8.1 结构体类型void GetInfo(Information*p)/*形参采用指针类型形参采用指针类型*/cout 请输入一位学生的信息:请输入一位学生的信息:n;cout p-No;cout p-Name;cout Na
37、me p-Score.math p-Score.chinese p-Score.english;void Comp(Information*p)/*形参采用指针类型形参采用指针类型*/p-Average_score=(p-Score.math+p-Score.chinese+p-Score.english)/3;8.1 结构体类型cout n调用函数调用函数 Comp()计算计算 Name 的平均成绩如下:的平均成绩如下:n;cout 学号:学号:No endl 数学:数学:Score.math ,语文:语文:Score.chinese ,英语:英语:Score.english endl;co
38、ut 三门功课平均成绩:三门功课平均成绩:Average_score Average_score)=85)cout 成绩优秀!成绩优秀!n;elsecout 成绩一般!成绩一般!n;8.1 结构体类型输出结果请输入一位学生的信息:请输入一位学生的信息:学号:学号:010姓名:姓名:JordanJordan的三门主课成绩的三门主课成绩(数学数学,语文语文,英语英语)是:是:98,76,97调用函数调用函数Comp()计算计算Jordan的平均成绩如下:的平均成绩如下:学号:学号:10数学:数学:98,语文:,语文:76,英语:,英语:97三门功课平均成绩:三门功课平均成绩:90成绩优秀!成绩优秀
39、!8.1 结构体类型这里,输入函数GetInfo(),计算函数Comp()的形参都是结构体Information类型的指针。在调用它们的时候,使用Information类型变量Exam的地址,这样在函数中对形参的修改就是直接对实参的修改。图8-6(a)是调用函数GetInfo()或者Comp()后的实参和形参的关系。(a)函数形参是结构体指针,实参是结构体变量地址,调用后,指针指向实参的结构体8.1 结构体类型Exam(主函数中定义,作为实参)NoNameScoreAverage_Score函数中的形参 p p(b)例8.5中的两个函数GetInfo()、Comp()处理的数据都是主函数中定义
40、的Exam图8-6 函数形参是结构体指针,实参是结构体变量地址8.1 结构体类型主函数main结 构 体 变 量Examp 函数Comp()处理函数GetInfo()p 处理在C+语言中,允许将整个结构体作为函数的参数进行传递,当然必须保证函数的形参和实参类型必须相同。但这种方法,程序运行时需要将全部成员一个一个传递给函数,又费时、又浪费空间,开销太大。如果结构体类型中成员很多,比如一个大的结构体,这种情况下,还是使用结构体指针进行函数参数传递,效率要更高。下面我们用传递结构体变量和传递结构体指针的方法修改,并输入一个结构体变量,从中体会不同的参数传递方式的差异。例8.6 定义一个日期结构体类
41、型,并定义一个日期结构体变量,对其初始化。编写两个函数,一个的形参是日期结构体类型,一个的形参是日期结构体指针类型。两个函数中都先对形参修改,然后输出。8.1 结构体类型程序清单 C08_06.cpp#include/*结构体定义部分结构体定义部分*/typedef structint year;/*年年*/int month;/*月月*/int day;/*日日*/DATE;8.1 结构体类型/*函数定义函数定义*/void Mp1(DATE OneDay)OneDay.year=1999;void Mp2(DATE*pOneDay)pOneDay-year=2050;void main()
42、DATE OneDay=2002,10,1;/*定义一个结构体定义一个结构体DATE类型变量,并初始化类型变量,并初始化*/DATE*p=&OneDay;/*定义一个结构体定义一个结构体DATE指针变量指针变量,并指向并指向OneDay*/cout 日期结构体变量原始值:日期结构体变量原始值:;cout year -month -day;cout endl;8.1 结构体类型Mp1(OneDay);cout n调用传值函数调用传值函数 Mp1(DATE OneDay)的结果:的结果:;cout OneDay.year -OneDay.month -OneDay.day;cout endl;Mp
43、2(p);/*等价于等价于 Mp2(&OneDay)*/cout n调用传指针函数调用传指针函数 Mp2(DATE*pOneDay)的结果:的结果:;cout year -month -day;cout endl;输出结果日期结构体变量原始值:日期结构体变量原始值:2002-10-1调用传值函数调用传值函数Mp1(DATE OneDay)的结果:的结果:2002-10-1调用传指针函数调用传指针函数Mp2(DATE*pOneDay)的结果:的结果:2050-10-18.1 结构体类型通过上面这段程序,我们可以看到,调用Mp1()不会影响实参值,而调用Mp2()就会影响实参值,我们从中可以再次体
44、会到传值和传地址调用的不同。下面用图8-7示意这个实例的参数传递情况。8.1 结构体类型图8-7 例8.7中的调用函数Mp1()、Mp2()参数传递情况8.1 结构体类型Mp2()DATE pOneDayMp1()yearmonthdayDATE OneDay传递地址(指向)传递地址(指向)DATE OneDayyearmonthday传递数据传递数据在实际生活中,我们常常遇到这样一些情况:交通灯只有红、黄、绿三种颜色;一个星期有七天;一年有十二个月;一个小组有张三、李四等。这些变量的取值被限定在一个有限的范围内,如果把这些量说明为整型、字符型或其他类型显然都不合适。为此,语言提供了一种称为“
45、枚举”的类型。所谓“枚举”是指将变量的值一一列举出来,变量的值只限于列举出来的值范围内。这样,被说明为该“枚举”类型的变量取值就不能超过定义的范围了。需要说明的是,枚举类型是一种基本数据类型,而不是一种构造类型,因为它不能再分解为任何基本类型。在定义结构体的时候,我们也可以应用枚举类型。8.2 枚举类型8.2.1 枚举类型的定义枚举类型和其他基本数据类型一样,在使用它声明变量之前,必须先定义枚举类型。定义枚举类型定义的格式为:枚举类型的定义语句的关键字是enum。用户定义的枚举类型名,它是一个标识符,表示一个新的枚举类型。花括号括起来的是该类型定义体,其中的内容又称为枚举表。枚举表是一组由用户
46、命名的符号常量,它们用逗号分开,每个符号常量又称为枚举常量或枚举值。枚举表内的值确定了枚举类型变量的取值范围。例如,我们定义:enum color red,yellow,green;enum day Sun,Mon,Tues,Wed,Thur,Fri,Sat;8.2 枚举类型enum 枚举类型名 枚举表;其中,red、yellow、green,Sun、MonSat称为“枚举元素”或“枚举常量”。第一条语句定义了一个枚举类型color,用来表示交通灯的颜色,它的取值范围是三个枚举值red、yellow和green,分别代表红色、黄色和绿色。第二条语句定义了一个枚举类型day,用来表示日期,它包含
47、7个枚举值,分别表示星期日、星期一至星期六。另外枚举表中的元素都是常量,它们规定了枚举变量的取值范围。数组可就不同了,数组的元素可以是基本类型、或者用户自定义的数据类型等,而且数组元素是变量。8.2 枚举类型8.2.2 枚举变量的声明定义了一个枚举类型,我们可以用它来定义变量。例如,在前面定义了枚举类型enum color,我们可以使用它来定义变量:enum color stop,go;或者为:enum color red,yellow,green stop,go;后面的stop,go是该类型的两个变量,它们的取值只能是red,yellow,green之一。例如:stop=red;go=gre
48、en;8.2 枚举类型8.2.3 枚举类型变量的赋值和使用枚举类型在使用中有以下规定:1.枚举元素是常量在编译器中,枚举元素本身由系统定义了一个表示序号的数值,从0开始顺序定义为0,1,2如在enum day中,Sun值为0,Mon值为1Sat值为6。例8.7 我们可以按整型数据输出枚举类型变量的值:程序清单 C08_7.cpp#include enum color red,yellow,green;8.2 枚举类型void main()enum color stop,go;/*声明枚举变量声明枚举变量stop,go*/stop=red;/*为枚举变量赋值为枚举变量赋值*/go=green;p
49、rintf(枚举变量枚举变量go的值是:的值是:%dn,go);printf(枚举变量枚举变量stop的值是:的值是:%dn,stop);输出结果枚举变量枚举变量go的值是:的值是:2枚举变量枚举变量stop的值是:的值是:0程序中,语句“enum color red,yellow,green;”在确定枚举值的同时分别为它们定义了表示序号的值:red为0,yellow为1,green为2。同时,枚举变量的值只能用赋值语句来获得。8.2 枚举类型2.允许在定义枚举类型时,指定枚举常量的值。例如:enum color red=3,yellow=1,green;这里,green的值从yellow的值顺序加1。即,green 的值是2。8.2 枚举类型3.枚举值可以作判断例如:if(stop=red)cout 请停车!请停车!n;4.整型与枚举类型是不同的数据类型,不能进行直接赋值例,错误的赋值:stop=2;/*stop是枚举类型是枚举类型*/不过,可以通过强制类型转换,对枚举变量赋值整型值。例如:stop=(enum color)2;8.2 枚举类型8.2.4 枚举类型的应用举例例8.8 在屏幕上提示:请用户选择行走的方向,然后显示出所选方向。程序清单C08_8.cpp#include#include void main()char*question=请选择方向请选择方