结构体和枚举类型_第1页
结构体和枚举类型_第2页
结构体和枚举类型_第3页
结构体和枚举类型_第4页
结构体和枚举类型_第5页
已阅读5页,还剩85页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

结构体和枚举类型第1页,共90页。(优选)结构体和枚举类型第2页,共90页。在现实生活中,有许多不同性质的数据实体。比如,通讯录通常由姓名、电话、E-mail、年龄等组成。姓名、电话、E-mail和所在城市可以用字符串表示,年龄可以用整型数表示。可是它们的每一项都是单独使用的,不能反映通讯录这样一个整体。用什么方法表示通讯录这个整体呢?新的被称为结构体的数据类型。为我们处理复杂的数据提供了便利的手段。第3页,共90页。什么是结构体结构体(structure)是一种数据类型,它把互相联系的数据组合成一个整体。例如,下面的表格显示了一个通讯录的信息:表8-1一个通讯录的信息表一个通讯录中有姓名、电话、性别、年龄、E-mail地址、所在城市,这些信息都是和一个叫“李明”的人有关。如果我们只把这些信息分别定义为独立的简单变量,就体现不出它们之间的相互关联了。所以,应当把它们组织成一个组合项,在一个组合项中包含若干个类型不同的数据项。用“结构体”来定义。8.1结构体类型第4页,共90页。结构体的定义结构体既然是一种数据类型,在使用前,先要“定义”出要使用的结构体类型。例:将通讯录定义成一个结构体。通讯录的信息由六项属性组成,首先要给这个结构体类型定义取一个名字,比如“AddressList”。然后,应该在结构体定义中对各属性进行说明。下面就是“通讯录”结构体类型:structAddressList{ charname[20]; /*姓名*/ chartelephone[12]; /*电话*/ charsex; /*性别*/ intage; /*年龄*/ chare_mail[40]; /*电子邮件*/ charaddr[30]; /*地址*/};8.1结构体类型第5页,共90页。其中,“struct”是关键字,是结构体的标识符,不能省略。“AddressList”是结构体类型名,它由我们自己进行命名的。“{}”中是结构体的成员,每个成员的数据类型既可以是简单的数据类型,也可以是复杂的数据类型,当然也可以是其他结构体数据类型。最后,定义完一个结构体后一定要用一个分号“;”结束。从上面这个例子,可以看出结构体定义格式如下:

8.1结构体类型struct名字{成员说明1;成员说明2;成员说明3;……成员说明n;};第6页,共90页。可以定义许多复杂的数据类型。比如,定义一个表示日期的结构体:structdate{ intyear; /*年*/ intmonth; /*月*/ intday; /*日*/};用日期这种结构体,我们就可以表示生日、开学时间、春节等等这样的日期。8.1结构体类型第7页,共90页。也可把两种结构体类型结合起来,“造出”更复杂的结构体。比如,一个通讯录的结构体中包含了表示出生日期的结构体structdate:structAddressList{ charname[20]; /*姓名*/ chartelephone[12]; /*电话*/ charsex; /*性别*/ intage; /*年龄*/ chare_mail[40]; /*电子邮件*/ charaddr[30]; /*地址*/ structdatebirthday; /*出生日期*/};8.1结构体类型第8页,共90页。我们先“造出”一个日期的结构体类型,同时我们又在通讯录这个结构体中,将出生日期这个成员变量定义为日期类型,这样通讯录结构体就变成更复杂一些的数据类型了。这样的结构可以叫做嵌套型的结构体,其结构可以如图8-1示意:图8-1嵌套型的结构体示意8.1结构体类型nametelephonesexageemailaddryearmonthdaybirthday第9页,共90页。定义结构体变量既然我们定义的结构体是一种数据类型,就可以像int、char、float这样的数据类型一样来使用,定义结构体类型的变量。用结构体类型定义变量的方式有如下几种:1.先定义结构体类型,再定义变量例,定义一个通讯录结构体:structAddressList{ charname[20]; /*姓名*/ chartelephone[12]; /*电话*/ charsex; /*性别*/ intage; /*年龄*/ chare_mail[40]; /*电子邮件*/ charaddr[30]; /*地址*/};/*定义2个结构体变量*/structAddressListAddressList1,AddressList2;8.1结构体类型第10页,共90页。定义了两个“AddressList”结构体类型的变量AddressList1和AddressList2。它们可以分别表示两个人的通讯录,比如:AddressList1:AddressList2:图8-2结构体变量8.1结构体类型第11页,共90页。结构体变量中的各个成员,在内存中是顺序存放的。各成员变量所占内存的大小是根据定义时它们的数据类型来决定。为了方便,也可以这样定义结构体变量:#defineADDRESSLISTstructAddressListADDRESSLIST{ charname[20]; /*姓名*/ chartelephone[12]; /*电话*/ charsex; /*性别*/ int age; /*年龄*/ chare_mail[40]; /*电子邮件*/ charaddr[30]; /*地址*/};ADDRESSLISTAddressList1,AddressList2;8.1结构体类型第12页,共90页。定义的这个符号常量“ADDRESSLIST”,它就代表了结构体类型“structAddressList”。这样,在未来的程序设计中,“ADDRESSLIST”可以和“structAddressList”完全等效使用了。2. 在定义结构体类型的同时声明变量structAddressList{ charname[20]; /*姓名*/ chartelephone[12]; /*电话*/ charsex; /*性别*/ intage; /*年龄*/ chare_mail[40]; /*电子邮件*/ charaddr[30]; /*地址*/}AddressList1,AddressList2;

8.1结构体类型第13页,共90页。这种方式和前面定义的方式效果一样,在定义结构体的同时,定义了2个structAddressList类型的变量AddressList1,AddressList2。这种方式通常用于函数中使用的局部结构体变量。3. 直接定义变量还可以用下面的方式直接定义结构体变量:struct /*省略结构体名称*/{ charname[20]; /*姓名*/ chartelephone[12]; /*电话*/ charsex; /*性别*/ intage; /*年龄*/ chare_mail[40]; /*电子邮件*/ charaddr[30]; /*地址*/}AddressList1,AddressList2;8.1结构体类型第14页,共90页。这种方式没有给出结构体名,通常也用于函数中使用的局部结构体变量。注意:1)对于结构体变量,在定义时,一定要先定义一个结构体类型,然后再定义该类型的变量。只能对结构体变量赋值、存取或运算,但不能对一个结构体类型进行这些操作;2)对结构体中的组成成员,可以单独使用,它的作用相当于普通变量。4. 类型定义typedef在编写程序的过程中,为了便于修改和表达清晰,我们往往还可以给数据类型取别名,在C++语言中叫做类型定义。类型定义的关键字是typedef,其使用格式为:

8.1结构体类型typedef数据类型标识符别名;第15页,共90页。比如我们给整型标识符int取个别名,叫做Integer,可以这样写:typedefintInteger;Integerk;这样定义的变量k就是一个整型数。8.1结构体类型第16页,共90页。同样可以对一个结构体进行类型定义,也就是给这个结构体取个别名。比如给前面定义的通讯录取个别名,并用别名定义变量:typedefstructAddressList{ charname[20]; /*姓名*/ chartelephone[12]; /*电话*/ charsex; /*性别*/ intage; /*年龄*/ chare_mail[40]; /*电子邮件*/ charaddr[30]; /*地址*/}ADDR_LIST;/*定义2个structAddressList类型的变量*/ADDR_LISTAddressList1,AddressList2;第17页,共90页。或者:structAddressList{……}typedefstructAddressListADDR_LIST;也可省略结构体的名称AddressList,写成如下的形式:typedefstruct{……}ADDR_LIST;8.1结构体类型第18页,共90页。结构体变量的初始化1. 结构体整体初始化声明一个结构体变量时,可以对它进行初始化,这和初始化一个数组是类似的。结合上面定义的通讯录结构体类型structAddressList,我们定义了一个structAddressList变量one,并对它进行初始化:structAddressListone={"李明北京"};8.1结构体类型第19页,共90页。注意:不能在定义结构体类型的时候,进行赋初值。例如:structAddressList /*下面的做法就是错误的*/{ charname="LiLin"; chartelephone[12]=; charsex='M'; intage=18; chare_mail[40]="lilin12@"; charaddr[30]="123BejingRoad";}one;第20页,共90页。例8.1定义一个结构体变量,并进行整体初始化,再输出其结果内容。程序清单C08_01.cpp#include<iostream.h>/*结构体定义部分*/structAddressList{ charname[20]; /*姓名*/ chartelephone[12]; /*电话*/ charsex; /*性别*/ intage; /*年龄*/ chare_mail[40]; /*电子邮件*/ charaddr[30]; /*地址*/};8.1结构体类型第21页,共90页。voidmain(){ /*定义并初始化结构体变量*/ structAddressListone={"李明北京"}; /*结构体变量的输出*/ cout<<"我们定义并初始化的结构体是:\n"<<endl; cout<<"姓名是:" <<<<endl <<"电话号码是:" <<one.telephone<<endl; cout<<"性别是:" <<one.sex<<endl cout<<"所在城市是:"<<one.addr<<endl;}8.1结构体类型第22页,共90页。输出结果:我们定义并初始化的结构体是:姓名是:李明电话号码是:性别是:M年龄是:16E-mail地址是:所在城市是:北京其中的“”、“one.telephone”是通过“.”运算符访问结构体变量的成员。一般情况下,不能将一个结构体变量作为整体来使用,只能使用其中的成员(分量)。使用结构体成员的方式:

8.1结构体类型结构体变量名.成员名第23页,共90页。通过这种方式,我们就可以使用结构体变量one中的成员了。例:cout<<<<","<<one.telephone<<","<<one.sex<<","<<one.age<<","<<one.e_mail<<","<<one.addr;注意,成员“.”操作符左边必须是结构体变量名,右边必须是结构体中已定义的成员名。下面这些写法都是错误的:strcpy(AddressL,"wangli");/*AddressList是结构体类型名,不是结构体变量*/one.book=6; /*结构体AddressList中没有定义“book”这个成员*/8.1结构体类型第24页,共90页。2. 初始化结构体部分成员既然,结构体变量的成员可以通过“.”操作符来访问,我们就可以使用赋值语句对它们进行初始化了。例如,对于上面例8.1,对变量one的初始化,还可以使用赋值语句完成:strcpy(,"李明");strcpy(one.telephone,"01062548445");one.sex='M';one.age=16;strcpy(one.addr,"北京");使用这种方式,比起第一种初始化方式要灵活一下,一般适用于对结构体的某个成员变量进行设置时使用。当然,使用输入语句也可以实现部分结构体成员的初始化。例如:cin>>one.age;8.1结构体类型第25页,共90页。3. 逐级访问成员在前面曾经定义了包含生日的通讯录结构体,生日这个成员变量又是日期结构体类型。对于生日这个成员变量,我们可以一级一级访问其成员。例如:

8.1结构体类型第26页,共90页。4. 把结构体变量当作整体赋值只有在以下两种情况下,才可以把结构体变量作为一个整体来赋值和访问。1)结构体变量整体赋值例:

AddressList2=AddressList1;通过这种模式,可以直接完成结构体之间的赋值。2)取结构体变量地址例如:

cout<<&AddressList1; /*输出AddressList1的地址*/ cin>>AddressList1.telephone; /*输入AddressList1的电话*/需要注意,不能把结构体变量整体输入进来。例如:

cin>>AddressList1;我们在使用结构体变量时,通常把结构体变量的地址用作函数的参数,以实现传地址调用。8.1结构体类型第27页,共90页。结构体数组我们知道,一个结构体变量可以存放一组相关的数据(例如,一个通讯录可以存放一个人的姓名、电话、性别、年龄、E-mail和地址等信息),正如前面引入数组一样,我们也可以定义一个数组,其每一成员都是一个结构体,它们都分别包含多个成员变量。1. 结构体数组的定义我们在定义结构体数组之前,首先要进行结构体类型的定义。然后再像以前介绍过的数组定义方式定义结构体数组。8.1结构体类型第28页,共90页。例如,我们定义一个具有3个元素的通讯录结构体数组:/*定义结构体类型*/typedefstructAddressList{ charname[20]; /*姓名*/ chartelephone[12]; /*电话*/ charsex; /*性别*/ intage; /*年龄*/ chare_mail[40]; /*电子邮件*/ charaddr[30]; /*地址*/}ADDR_LIST;/*定义结构体数组*/ADDR_LISTaddlist[3];/*定义有3个元素的结构体数组*/这样就定义了一个具有3个元素的结构体数组,这些数组元素在内存中是连续存放的。8.1结构体类型第29页,共90页。2. 结构体数组的初始化我们可以把结构体初始化和数组元素初始化结合起来,对结构体数组进行初始化。经过初始化,就可以分别输出结构体数组元素的值。例8.2结构体数组的初始化。程序清单C08_02.cpp#include<iostream.h>typedefstruct{ charname[20]; /*姓名*/ chartelephone[12]; /*电话*/ charsex; /*性别*/ intage; /*年龄*/ chare_mail[40]; /*电子邮件*/ charaddr[30]; /*地址*/}ADDR_LIST;8.1结构体类型第30页,共90页。voidPrint(ADDR_LIST*,intCount);voidmain(){ /*定义并初始化结构体变量*/ ADDR_LISTaddrlist[3]={ {"李明北京"}, {"王芳","02162281234",'F',20,"wangf@","上海"}, {"Marry","02786614571",'F',19,"onegirl@263.net","武汉"},}; Print(addrlist,3);}8.1结构体类型第31页,共90页。voidPrint(ADDR_LIST*List,intCount){ inti; /*结构体变量的输出*/ cout<<"我们定义并初始化的结构体数组的数据如下:\n\n"; for(i=0;i<Count;i++) { cout<<"第"<<i+1<<"个记录:"<<endl; cout<<"姓名:"<<List[i].name<<endl; cout<<"电话号码:"<<List[i].telephone<<endl; cout<<"性别:"<<List[i].sex<<endl; cout<<"年龄:"<<List[i].age<<endl; cout<<"E-mail:"<<List[i].e_mail<<endl; cout<<"所在城市:"<<List[i].addr<<endl; cout<<endl; } }8.1结构体类型第32页,共90页。输出结果我们定义并初始化的结构体数组的数据如下:第1个记录:姓名:李明电话号码:

性别:M

年龄:16E-mail:所在城市:北京第2个记录:姓名:王芳电话号码:

性别:F

年龄:20E-mail:所在城市:上海8.1结构体类型第33页,共90页。第3个记录:姓名:Marry电话号码:

性别:F

年龄:19E-mail:所在城市:武汉8.1结构体类型第34页,共90页。结构体指针结构体指针,就是一个结构体类型的指针,它指向一个结构体变量。这和整型指针、字符指针是一样的。其实例8.2的Print函数中就使用了结构体指针作为形参(*List)。1. 结构体指针我们再看一个应用结构体指针的小例子。例8.3我们定义一个表示某人生日的结构体变量,同时定义一个结构体指针指向它,分别通过结构体变量和结构体指针输出结构体成员的值,观察其结果的不同。8.1结构体类型第35页,共90页。程序清单C08_03.cpp/*结构体变量和结构体指针的关系*/#include<iostream.h>/*结构体类型定义,其中结构体date是结构体PERSON的成员变量*/structdate{ intmonth; /*表示月,从1-12*/ intday; /*表示日期,从1-31*/ intyear; /*表示年*/};/*定义结构体类型,并且是复合(成员变量是结构体类型)类型*/typedefstruct{ intNo; /*序号*/ charname[20]; /*姓名*/ structdatebirthday; /*出生日期*/}PERSON;8.1结构体类型第36页,共90页。voidmain(){ PERSONUsers; /*定义Users是一个结构体变量*/

PERSON*p; /*定义*p是一个结构体指针*/ cout<<"请输入结构体变量的信息:\n"; cout<<"请输入序号:"; cin>>Users.No; /*Users.No是整型变量*/ cout<<"姓名:"; cin>>U; /*U字符数组的名字,其表示地址*/ cout<<"请输入生日日期(YYYY-MM-DD):";

p=&Users; /*将结构体变量Users的地址赋值给指针p*/ cout<<"\n通过结构体变量输出的结果是:\n"; cout<<"序号:"<<Users.No<<endl8.1结构体类型第37页,共90页。

<<"姓名:"<<U<<endl <<"生日: cout<<"\n通过结构体指针变量输出的结果:\n"; cout<<"序号:"<<(*p).No<<endl <<"姓名:"<<(*p).name<<endl <<"生日:"<<(*p).birthday.year <<(*p).birthday.month <<(*p).birthday.day<<endl;}8.1结构体类型第38页,共90页。输出结果请输入结构体变量的信息:请输入序号:010姓名:Jordan请输入生日日期(YYYY-MM-DD):1973-3-23通过结构体变量输出的结果是:序号:10姓名:Jordan生日:1973-3-23通过结构体指针变量输出的结果:序号:10姓名:Jordan生日:1973-3-238.1结构体类型第39页,共90页。可见,通过结构体变量和结构体指针变量输出的结果完全一样。在程序中我们定义了一个结构体类型PERSON,然后在主函数定义了一个PERSON类型变量Users。与此同时,定义了一个结构体PERSON指针变量p,并让它指向Users。情况如图8-3所示。

8.1结构体类型第40页,共90页。图8-3结构体变量和结构体指针的关系8.1结构体类型10Jordan1973323PERSON:Usersp第41页,共90页。这样,结构体变量Users和结构体指针p就表示同一部分数据。从源程序中我们可以看出,对于指针类型的结构体变量的成员,我们使用“(*p).No”、“(*p).name”这样的形式访问。其中,“(*p)”表示p指向的结构体变量Users,“(*p).No”就是p指向的结构体变量中的成员No。注意,“*p”两侧的括弧可不能省!因为运算符“.”的优先级要高于指针运算符“*”,如果省略括弧,“*p.No”就表示了“p.No”是指针了(等价于“*(p.No)”),它和“(*p).No”不是一回事。8.1结构体类型第42页,共90页。可以把“(*p).No”改用指向运算符“->”表示为“p->No”。同样,“(*p).name”也等价于“p->name”。因此,下面三种形式是等价的:Users.成员名(*p).成员名p->成员名有了这些规则,我们可以把上面“通过结构体指针变量输出”的语句改为:

printf("序号是:%d\n姓名是:%s\n生日是:%d-%d-%d\n",p->No,p->name, p->birthday.month,p->birthday.day,p->birthday.year);其中“->”称为指向运算符。8.1结构体类型第43页,共90页。2. 指向结构体数组的指针指针和数组之间的关系十分密切:如果指针p指向数组的某个特定元素,那么p+1就指向该数组中下一个元素,p+i指向该元素后面第i个元素,p-i指向该元素之前第i个元素。同样,对结构体数组及其元素也可以用指针变量来指向。例,我们在例8.2中定义了一个结构体数组,并进行了初始化。现在我们用指向结构体数组的指针进行操作,结果会是怎么样呢?例8.4定义一个结构体数组变量,进行数组元素的整体初始化,并利用指向结构体数组的指针输出结构体的数据。8.1结构体类型第44页,共90页。程序清单C08_04.cpp#include<iostream.h>/*结构体定义部分*/structAddressList{ charname[20]; /*姓名*/ chartelephone[12]; /*电话*/ charsex; /*性别*/ intage; /*年龄*/ chare_mail[40]; /*电子邮件*/ charaddr[30]; /*地址*/};typedefstructAddressListADDR_LIST;/*将此结构体类型定义为ADDR_LIST*/8.1结构体类型第45页,共90页。voidmain(){ /*定义并初始化结构体变量*/ ADDR_LISTList[3]={ {"李明北京"}, {"王芳","02162281234",'F',20,"wangf@","上海"}, {"Marry","02786614571",'F',19,"onegirl@263.net","武汉"},}; ADDR_LIST*p; /*定义一个指向结构体类型的指针*/ /*结构体变量的输出*/ cout<<"用指向结构体数组的指针输出的结构体变量值是:\n"; for(p=List;p<List+3;p++) { cout<<endl; cout<<"姓名:"<<p->name<<endl <<"电话号码:"<<p->telephone<<endl; cout<<"性别:"<<p->sex<<endl <<"年龄:"<<p->age<<endl;8.1结构体类型第46页,共90页。

cout<<"e_mail:"<<p->e_mail<<endl; cout<<"所在城市:"<<p->addr<<endl; }}输出结果用指向结构体数组的指针输出的结构体变量值是:姓名:李明电话号码:

性别:M

年龄:16e_mail:所在城市:北京

8.1结构体类型第47页,共90页。姓名:王芳电话号码:

性别:F

年龄:20e_mail:所在城市:上海姓名:Marry电话号码:

性别:F

年龄:19e_mail:所在城市:武汉8.1结构体类型第48页,共90页。输出结果和例8.2的一样。我们在程序中定义了指向ADDR_LIST结构体数组List的指针p,在for语句中先赋值p的初值为List,即结构体数组的起始地址,如图8-4所示。在第一次循环中,输出List[0]的各成员值,然后执行p++,使p指向List[1]的起始地址。同样,第二次循环后,p指向List[2]的起始地址。再执行p++后,p的值为List+3,循环条件不满足,于是退出循环。

8.1结构体类型第49页,共90页。图8-4指向结构体数组的指针8.1结构体类型List[0]List[1]List[2]pp+1p+2第50页,共90页。我们在使用指向结构体数组指针时需要注意以下几点:1)(++p)和(p++)是不同的。例如:“(++p)->telephone”先使p自加1,然后得到它指向的元素中的telephone成员值,即“List[1].telephone("02162281234")”。“(p++)->telephone”先得到“p->telephone”的值,即"01062548445",然后再p自加1,即指向List[1]。2)如果定义p是结构体类型ADDR_LIST的指针,它只能指向一个此结构体类型的变量。例如,下面这样描述是错误的:

p=&addrlist[0].name; /*错误*/8.1结构体类型第51页,共90页。结构体与函数有时,我们想把一个结构体变量的值传递给另一个函数,用什么方法呢?可以利用前面学过函数的传值调用,既可以传递单个结构体成员也可以传递整个结构体。例如:用List[0].name或List[0].telephone作函数的实参,通过函数调用将实参值传递给形参。这种用法和用普通变量作实参没有任何区别,都是“值传递”方式,被调用函数无法修改主调函数中的结构体变量成员。如果我们需要被调用函数能改变主调函数中结构体变量成员,该用什么方法呢?通过指针的学习,自然使我们想到可以用指向结构体变量的指针作实参,或将结构体变量的地址作为实参调用函数。比起传值调用,传地址方式不需要对整个结构体做一份拷贝,只需要把结构体变量的地址传递给函数就可以了。

8.1结构体类型第52页,共90页。图8-5回顾:传值和传地址调用的比较示意8.1结构体类型主调函数被调函数函数形参(a)传值调用实际参数复制主调函数被调函数函数形参(b)传引用调用实际参数指向第53页,共90页。先让我们看一看指针指向结构体变量的小例子!例8.5用结构体变量的地址作为实参调用函数。定义一个结构体包括学生的学号、姓名和三门主课(数学、语文、英语)的成绩和平均分。在主函数main定义此结构体变量Exam,调用函数GetInfo()输入赋值到Exam,再调用函数Comp()计算平均分并输出。程序清单C08_05.cpp#include<iostream.h>typedefstruct{ intmath; /*数学成绩*/ intchinese; /*语文成绩*/ intenglish; /*英语成绩*/}SCORE;8.1结构体类型第54页,共90页。typedefstruct{ intNo; /*学号*/ charName[20]; /*姓名*/ SCOREScore; /*三门成绩*/ intAverage_score; /*平均分*/}Information;/*函数声明部分*/voidGetInfo(Information*p); /*从键盘输入数据*/voidComp(Information*p); /*计算平均分*/voidmain(){ InformationExam; /*定义一个学生信息的结构体变量*/ GetInfo(&Exam); /*输入结构体变量的成员值,用地址作为参数*/ Comp(&Exam); /*用地址作为参数*/} 8.1结构体类型第55页,共90页。voidGetInfo(Information*p) /*形参采用指针类型*/{ cout<<"请输入一位学生的信息:\n"; cout<<"学号:"; cin>>p->No; cout<<"姓名:"; cin>>p->Name; cout<<p->Name<<"的三门主课成绩(数学,语文,英语)是:\n"; cin>>p->Score.math>>p->Score.chinese>>p->Score.english;}voidComp(Information*p) /*形参采用指针类型*/{ p->Average_score=(p->Score.math+p->Score.chinese+p->Score.english)/3;

8.1结构体类型第56页,共90页。cout<<"\n调用函数Comp()计算"<<p->Name<<"的平均成绩如下:\n"; cout<<"学号:"<<p->No<<endl <<"数学:"<<p->Score.math<<"," <<"语文:"<<p->Score.chinese<<"," <<"英语:"<<p->Score.english<<endl; cout<<"三门功课平均成绩:"<<p->Average_score<<endl; if((p->Average_score)>=85) cout<<"成绩优秀!\n"; else cout<<"成绩一般!\n";}8.1结构体类型第57页,共90页。输出结果请输入一位学生的信息:学号:010姓名:JordanJordan的三门主课成绩(数学,语文,英语)是:98,76,97调用函数Comp()计算Jordan的平均成绩如下:学号:10数学:98,语文:76,英语:97三门功课平均成绩:90成绩优秀!8.1结构体类型第58页,共90页。这里,输入函数GetInfo(),计算函数Comp()的形参都是结构体Information类型的指针。在调用它们的时候,使用Information类型变量Exam的地址,这样在函数中对形参的修改就是直接对实参的修改。图8-6(a)是调用函数GetInfo()或者Comp()后的实参和形参的关系。

(a)函数形参是结构体指针,实参是结构体变量地址,调用后,指针指向实参的结构体8.1结构体类型Exam(主函数中定义,作为实参)No NameScoreAverage_Score函数中的形参p第59页,共90页。(b)例8.5中的两个函数GetInfo()、Comp()处理的数据都是主函数中定义的Exam图8-6函数形参是结构体指针,实参是结构体变量地址8.1结构体类型主函数main结构体变量Examp函数Comp()处理函数GetInfo()p处理第60页,共90页。在C++语言中,允许将整个结构体作为函数的参数进行传递,当然必须保证函数的形参和实参类型必须相同。但这种方法,程序运行时需要将全部成员一个一个传递给函数,又费时、又浪费空间,开销太大。如果结构体类型中成员很多,比如一个大的结构体,这种情况下,还是使用结构体指针进行函数参数传递,效率要更高。下面我们用传递结构体变量和传递结构体指针的方法修改,并输入一个结构体变量,从中体会不同的参数传递方式的差异。例8.6定义一个日期结构体类型,并定义一个日期结构体变量,对其初始化。编写两个函数,一个的形参是日期结构体类型,一个的形参是日期结构体指针类型。两个函数中都先对形参修改,然后输出。8.1结构体类型第61页,共90页。程序清单C08_06.cpp#include<iostream.h>/*结构体定义部分*/typedefstruct{ intyear; /*年*/ intmonth; /*月*/ intday; /*日*/}DATE;8.1结构体类型第62页,共90页。/*函数定义*/voidMp1(DATEOneDay){ OneDay.year=1999;}voidMp2(DATE*pOneDay){ pOneDay->year=2050;}voidmain(){ DATEOneDay={2002,10,1};/*定义一个结构体DATE类型变量,并初始化*/ DATE*p=&OneDay; /*定义一个结构体DATE指针变量,并指向OneDay*/ cout<<"日期结构体变量原始值:"; cout<<p->year<<"-"<<p->month<<"-"<<p->day; cout<<endl;

8.1结构体类型第63页,共90页。Mp1(OneDay); cout<<"\n调用传值函数Mp1(DATEOneDay)的结果:"; cout<<OneDay.year<<"-"<<OneDay.month<<"-"<<OneDay.day; cout<<endl; Mp2(p); /*等价于Mp2(&OneDay)*/ cout<<"\n调用传指针函数Mp2(DATE*pOneDay)的结果:"; cout<<p->year<<"-"<<p->month<<"-"<<p->day; cout<<endl;}输出结果日期结构体变量原始值:2002-10-1调用传值函数Mp1(DATEOneDay)的结果:2002-10-1调用传指针函数Mp2(DATE*pOneDay)的结果:2050-10-18.1结构体类型第64页,共90页。通过上面这段程序,我们可以看到,调用Mp1()不会影响实参值,而调用Mp2()就会影响实参值,我们从中可以再次体会到传值和传地址调用的不同。下面用图8-7示意这个实例的参数传递情况。8.1结构体类型第65页,共90页。图8-7例8.7中的调用函数Mp1()、Mp2()参数传递情况8.1结构体类型Mp2()DATEpOneDayMp1()yearmonthdayDATEOneDay传递地址(指向)DATEOneDayyearmonthday传递数据第66页,共90页。在实际生活中,我们常常遇到这样一些情况:交通灯只有红、黄、绿三种颜色;一个星期有七天;一年有十二个月;一个小组有张三、李四等。这些变量的取值被限定在一个有限的范围内,如果把这些量说明为整型、字符型或其他类型显然都不合适。为此,C语言提供了一种称为“枚举”的类型。所谓“枚举”是指将变量的值一一列举出来,变量的值只限于列举出来的值范围内。这样,被说明为该“枚举”类型的变量取值就不能超过定义的范围了。需要说明的是,枚举类型是一种基本数据类型,而不是一种构造类型,因为它不能再分解为任何基本类型。在定义结构体的时候,我们也可以应用枚举类型。8.2枚举类型第67页,共90页。枚举类型的定义枚举类型和其他基本数据类型一样,在使用它声明变量之前,必须先定义枚举类型。定义枚举类型定义的格式为:

枚举类型的定义语句的关键字是enum。用户定义的枚举类型名,它是一个标识符,表示一个新的枚举类型。花括号括起来的是该类型定义体,其中的内容又称为枚举表。枚举表是一组由用户命名的符号常量,它们用逗号分开,每个符号常量又称为枚举常量或枚举值。枚举表内的值确定了枚举类型变量的取值范围。例如,我们定义:enumcolor{red,yellow,green};enumday{Sun,Mon,Tues,Wed,Thur,Fri,Sat};8.2枚举类型enum枚举类型名{枚举表};第68页,共90页。其中,red、yellow、green,Sun、Mon……Sat称为“枚举元素”或“枚举常量”。第一条语句定义了一个枚举类型color,用来表示交通灯的颜色,它的取值范围是三个枚举值red、yellow和green,分别代表红色、黄色和绿色。第二条语句定义了一个枚举类型day,用来表示日期,它包含7个枚举值,分别表示星期日、星期一至星期六。另外枚举表中的元素都是常量,它们规定了枚举变量的取值范围。数组可就不同了,数组的元素可以是基本类型、或者用户自定义的数据类型等,而且数组元素是变量。8.2枚举类型第69页,共90页。枚举变量的声明定义了一个枚举类型,我们可以用它来定义变量。例如,在前面定义了枚举类型enumcolor,我们可以使用它来定义变量:

enumcolorstop,go;或者为:

enumcolor{red,yellow,green}stop,go;后面的stop,go是该类型的两个变量,它们的取值只能是red,yellow,green之一。例如:

stop=red; go=green;8.2枚举类型第70页,共90页。枚举类型变量的赋值和使用枚举类型在使用中有以下规定:1. 枚举元素是常量在编译器中,枚举元素本身由系统定义了一个表示序号的数值,从0开始顺序定义为0,1,2……如在enumday中,Sun值为0,Mon值为1……Sat值为6。例8.7我们可以按整型数据输出枚举类型变量的值:程序清单C08_7.cpp#include<iostream.h>enumcolor{red,yellow,green};8.2枚举类型第71页,共90页。voidmain(){ enumcolorstop,go; /*声明枚举变量stop,go*/ stop=red; /*为枚举变量赋值*/ go=green; printf("枚举变量go的值是:%d\n",go); printf("枚举变量stop的值是:%d\n",stop);}输出结果枚举变量go的值是:2枚举变量stop的值是:0程序中,语句“enumcolor{red,yellow,green};”在确定枚举值的同时分别为它们定义了表示序号的值:red为0,yellow为1,green为2。同时,枚举变量的值只能用赋值语句来获得。8.2枚举类型第72页,共90页。2. 允许在定义枚举类型时,指定枚举常量的值。例如:

enumcolor{red=3,yellow=1,green};这里,green的值从yellow的值顺序加1。即,green的值是2。8.2枚举类型第73页,共90页。3. 枚举值可以作判断例如:

if(stop==red) cout<<"请停车!!!\n";4. 整型与枚举类型是不同的数据类型,不能进行直接赋值例,错误的赋值:

stop=2; /*stop是枚举类型*/不过,可以通过强制类型转换,对枚举变量赋值整型值。例如:

stop=(enumcolor)2;8.2枚举类型第74页,共90页。枚举类型的应用举例例8.8在屏幕上提示:请用户选择行走的方向,然后显示出所选方向。程序清单C08_8.cpp#include<iostream.h>#include<string.h>voidmain(){ char*question="请选择方向[1:西,2:北,3:东,4:南]"; char*pwest="你选择向西"; char*pnorth="你选择向北"; char*peast="你选择向东"; char*psouth="你选择向南";

enumlocation{west=1,north=2,east=3,south=4}; enumlocationdirection;8.2枚举类型第75页,共90页。

intn; cout<<question;

cin>>n; direction=(enumlocation)n; switch(direction) { casewest:cout<<pwest<<endl;break; casenorth:cout<<pnorth<<endl;break; caseeast:cout<<peast<<endl;break; casesouth:cout<<psouth<<endl;break; default:cout<<"在原地等待\n";break; }}8.2枚举类型第76页,共90页。输出结果请选择方向[1:西,2:北,3:东,4:南]2你选择向北从上面这段程序可以看出,用枚举类型能够很方便地制作一个选择菜单。例8.9在结构体中定义枚举类型的成员。定义一个结构体类型Regist用于统计学生注册情况(学号、姓名、注册日期),其中成员注册日期是枚举类型变量(从Sun到Sat七天)。输入学生注册信息,根据注册日期(比如星期三之前)判断一个学生是否迟到,并显示结果。8.2枚举类型第77页,共90页。程序清单C08_9.cpp#include<iostream.h>#include<string.h>#defineCOUNT4/*定义枚举类型,表示注册时间*/enumday{Sun,Mon,Tues,Wed,Thur,Fri,Sat};/*定义注册情况结构体*/typedefstruct{ charname[20]; /*姓名*/ intnumber; /*学号*/

enumdayRegist_day; /*注册时间*/}Regist;voidInput(Regist*stu); /*用于输入学生注册情况的函数*/intJudge(Regist*stu); /*判断学生是否迟到的函数*/8.2枚举类型第78页,共90页。voidmain(){ Registstudent[COUNT]; /*定义四个学生的数组*/ Regist*p;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论