1、单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,内容提要,多种数据特征的封装,结构体,结构,结构变量,结构数组,结构指针,公用体,枚举类型,多种数据特征和函数的封装,类,类,对象,构造函数与析构函数,类的组合,多文件结构,0,6.1多种数据特征的封装结构体,在描述某些事物时,有时只用一种数据类型往往很难处理,如手机通话记录中的信息就有多种数据类型,对方电话号码可以用字符数组或者字符串,持续时间可以用整型(以秒计时)、浮点型、双精度类型中的一种,如果只是将这两类信息定
2、义为相互独立的简单变量,是很难反映它们之间的内在联系的,在C语言中,可以使用结构将多种数据信息封装在一起。,1,6.1.1结构,结构是,C,语言中一种新的构造数据类型,它能把有内在联系的不同类型的数据统一成一个整体,使它们相互关联;同时,结构又是一个变量的集合,可以按照对基本数据类型的操作方法单独使用其成员变量。,2,嵌套定义例子,struct time,int hour,minute,second;,struct day,int year,month,date;,struct conversion,char phonenumber11;,int duration;,struct day oc
3、currentday;,struct time occurrenttime;,;,5,6.1.2结构变量,如同,C,语言中的基本数据类型一样,在定义了结构类型后,还需要定义结构类型的变量,然后才能通过结构变量来操作和访问结构的数据。,6,结构变量定义,单独定义,格式,1,:结构体名,变量名列表;,格式,2,:,struct,结构体名,变量名列表;,混合定义,struct,结构体名,成员表列,变量名表列;,无类型定义,struct,成员表列,变量名表列;,7,结构变量初始化,struct conversion,char phonenumber11;,int duration;,struct da
4、y occurrentday;,struct time occurrenttime;,account1=“1111111111”,120,2012,8,8,16,15,30;,8,结构变量使用,结构变量成员的引用,结构体变量名,.,成员名,结构变量的整体赋值,结构变量,1=,结构变量,2,结构变量作为函数参数,结构变量可以作为函数参数以及函数的返回值,9,【例6-1】,查找是否有指定电话号码的通话记录,【,问题分析,】,表示通话记录,【,算法描述,】,录入通话记录,按照电话号码寻找相匹配的通话记录,10,【源程序】,#include /,包含基本输入输出库头文件,using namespace
5、 std;/,使用名字空间,struct time /,定义时间结构体,int hour,minute,second;,struct day /,定义日期结构体,年、月、日,int year,month,date;,struct conversion/,通话记录类型,char phonenumber11;/,电话号码,int duration;/,通话时长,struct day occurrentday;/,日期,struct time occurrenttime;/,时间,account1=“1111111111”,120,2012,8,8,16,15,30;,/,初始化结构体变量,acco
6、unt1,11,int main()/,主函数,char temp11;,cout”,请输入对方的电话号码,”,temp;,if(strcmp(account1.phonenumber,temp)=0)/,比较电话号码,cout”find”tempendl;,coutaccount1.durationendl;/,打印结构体的成员,coutaccount1.occurrentday.year”t”;,coutaccount1.occurrentday.month”t”;,cout account1.occurrentday.dateendl;,coutaccount1.occurrenttim
7、e.hour”t”;,coutaccount1.occurrenttime.minute”t”;,cout account1.occurrenttime.second endl;,12,else,cout”not find”tempendl;,return 0;,13,【运行结果】,结果一:,请输入对方的电话号码,1111111111,find1111111111,120,2012 8 8,16 15 30,结果二:,请输入对方的电话号码,2222222222,not find2222222222,14,【思路扩展】,如果将结构变量的初始化过程改写成从键盘输入各成员的值再赋值给各成员,应该如何
8、修改?如果将查找过程编写成函数,又该如何修改?,15,6.1.3结构数组,一个结构变量只能表示一个实体的信息,例如account1只能表示1条通话记录,如果有许多相同类型的实体,就需要使用结构数组,例如100条通话记录,由于每条记录的基本信息都是相同的,就可以将这些具有相同结构类型的变量组织起来,形成一个结构数组。,结构数组是结构与数组的结合,与普通数组的不同之处在于每个数组元素都是一个结构类型的数据,包含各个成员。,16,结构数组定义,struct conversion,char phonenumber11;,int duration;,struct time occurrentday;,s
9、truct time occurrenttime;,account100;,17,结构数组初始化,struct conversion account100=“1111111111”,11,2012,8,8,16,15,30,“2222222222”,22,2012,8,8,16,15,30;,18,结构数组使用,结构数组成员的引用,结构数组名,下标,.,结构成员名,结构数组元素的整体赋值,结构数组元素,i=,结构数组元素,j,19,【例6-2】,词频统计:输入一系列英文单词,单词之间用空格隔开,用“,xyz,”表示结束输入,统计输入过哪些单词以及各单词出现的次数,统计时,区分大小写字母,最后按
10、单词的字典顺序输出单词和出现次数的对照表。,【,问题分析,】,字典的组成,【,算法描述,】,统计不同单词出现的次数,20,【源程序】,#include /,包含基本输入输出库头文件,#include,using namespace std;/,使用名字空间,struct WordList/,字典类型,char word50;,int freq;,;,21,void Sort(WordList list,int count)/,排序函数,for(int i=0;ii;j=j-1),if(strcmp(listj-1.word,listj.word)0),WordList tmp;,tmp=lis
11、tj-1;,listj-1=listj;,listj=tmp;,22,int main()/,主函数,WordList list5000;,int i,num=0;,char temp50;,cout”,请输入一系列英语单词,以,xyz,表示输入结束,”,temp;,while(strcmp(temp,”xyz”)!=0),for(i=0;i=num)/,若字典中无该单词,添加该词,strcpy(listi.word,temp);,listi.freq=1;,num+;,cintemp;/,继续输入单词,Sort(list,num);/,对字典进行排序,cout”,词频统计结果如下:,”,en
12、dl;,for(i=0;inum;i+),coutlisti.word”t”listi.freq,指向结构数组的指针,结构数组元素,.,成员名,结构数组元素,-,成员名,结构指针名,-,成员名,(*,结构指针名,).,成员名,结构指针作为函数参数,27,【例6-3】,利用带结构指针的函数实现通话记录的输入、输出和查找等功能。,【,问题分析,】,输入、输出和查找函数,【,算法描述,】,批量录入通话记录,再按照电话号码寻找相匹配的通话记录。,28,【源程序】,#include /,包含基本输入输出库头文件,using namespace std;/,使用名字空间,struct time /,时间结
13、构体,int hour,minute,second;,struct day /,日期结构体,int year,month,date;,struct conversion /,通话记录结构体,char phonenumber11;,int duration;,struct day occurrentday;,struct time occurrenttime;,void input(struct conversion*);/,输入函数声明,void print(struct conversion);/,输出函数声明,struct conversion find(struct conversion
14、char tempnumber11);,29,int main()/,主函数,char temp11;,struct conversion account1,account5;/,结构体变量、数组,input(account);/,调用输入函数,couttemp;/,输入要查找的电话号码,account1=find(account,temp);/,调用查找函数,if(strcmp(account1.phonenumber,0000000000)!=0)/,判断是否找到,print(account1);/,找到则显示,else,coutnot findendl;,return 0;/,主函数
15、结束,30,void input(struct conversion*p)/,批量输入通话记录,cout,请输入,5,个人的通话记录(电话、时长、日期、时间),n;,for(int i=0;ipi.phonenumberpi.duration;,cinpi.occurrentday.yearpi.occurrentday.monthpi.occurrentday.date;,cinpi.occurrenttime.hourpi.occurrenttime.minutepi.occurrenttime.second;,31,void print(struct conversion q)/,输出指
16、定结构变量的全部成员信息,coutq.phonenumbertq.durationendl;,coutq.occurrentday.yeart;,coutq.occurrentday.montht;,cout q.occurrentday.dateendl;,coutq.occurrenttime.hourt;,coutq.occurrenttime.minutet;,cout q.occurrenttime.second endl;,32,struct conversion find(struct conversion*p,char tempnumber11)/,查找指定电话,struct
17、conversion r=0000000000;/,结构变量部分成员初始化,for(int i=0;i5;i+),if(strcmp(pi.phonenumber,tempnumber)=0),r=pi;/,结构变量的整体赋值,return r;,33,【运行结果】,请输入,5,个人的通话记录(电话、时长、日期、时间),1111111111,120,2012,8,8,8,8,8,2222222222,130,2012,8,9,8,8,9,3333333333,140,2012,8,1,8,8,8,4444444444,150,2012,9,9,9,9,9,5555555555,160,2012
18、9,9,9,9,9,input the phonenumber:,3333333333,3333333333 140,2012 8 1,8 8 8,34,【思路扩展】,什么情况下在函数中使用结构变量或者结构指针作为函数参数较好?,35,6.1.5公用体,结构体与共用体的本质区别只要在于存储方式,结构体的每个成员各自占用分配给自己的存储单元,各自拥有自己的地址,结构体类型分配的内存空间大小就是各成员所占存储单元的总和。共用体的各个成员则占用共同的存储单元,具有相同的首地址,占用存储单元最多的成员的长度就是共用体的长度。,36,公用体的定义,union,公用体名,类型,1,成员名,1;,类型,2
19、成员名,2;,类型,n,成员名,n;,;,37,共用体变量定义,单独定义,union postion pos1,pos2,*p;,混合定义,union postion,int grand;,char title20;,pos1,pos2,*p;,38,公用体变量初始化,共用体变量或数组在初始化时,只能对它的第一个成员赋值,对多个成员赋值是不允许的,union postion pos1=1,;,/,正确,union postion pos2=1,2;/,正确,union postion pos2=1,lector,2,lector;/,错误,39,共用体变量的使用,共用体变量的引用,共用体变量
20、名,.,成员,共用体变量指针,.,成员,公用体变量的整体赋值,共用体变量,1=,共用体变量,2,40,【例6-4】,学校人事信息管理:批量输入和输出学生或者教师信息,包括姓名、年龄、职业和职位等信息,每位学生或者教师都包含前,3,项信息,但对学生而言,其第,4,项信息表示年级;对教师而言,其第,4,项信息表示职称。,【,问题分析,】,学校人事信息的表示,【,算法描述,】,输入和输出学校人事信息。,41,【源程序】,#include /,包含基本输入输出库头文件,using namespace std;/,使用名字空间,union postion,int grand;,char title20;
21、struct person,char name20;,int age;,char job10;,postion pos;,;,42,int main()/,主函数,person p3;,int i;,for(i=0;ipi.namepi.agepi.job;,if(strcmp(pi.job,”student”)=0),cin pi.pos.grand;,else,cin pi.pos.title;,cout”*”endl;,43,cout”name”t”age”t”job”t”,grand/title”endl;,for(i=0;i3;i+),coutpi.name”t”pi.age”
22、t”,pi.job”t”;,if(strcmp(pi.job,”student”)=0),cout pi.pos.grandendl;,else,cout pi.pos.titleendl;,return 0;/,程序结束,,44,【运行结果】,tom,21,student,3,john,19,teacher,professor,rose,19,student,1,*,name age job grand/title,tom 21 student 3,john 19 teacher professor,rose 19 student 1,45,【思路扩展】,结构体类型中包含共用体类型的定义会在
23、哪些情况中出现?共用体类型中包含结构体类型的定义会在哪些情况中出现?,46,6.1.6枚举类型,在一些实际的应用中,有些变量的取值常常被限定在一个有限范围内,如一个星期只有7天,一年只有12个月等。C语言提供的“枚举”类型能够在类型定义时列举出所有可能的取值,将枚举类型变量的取值限定在取值范围内。由于枚举变量只能取一个值,不能再分解为任何基本类型,因此枚举类型只是一种基本数据类型,而不是构造类型。,47,枚举的定义,enum 枚举名 枚举常量表,48,枚举变量的定义,单独定义,enum color temp;,混合定义,enum color red,yellow,blue,white,blac
24、k temp;,无类型定义,enum red,yellow,blue,white,black temp;,49,枚举变量的使用,可以把枚举常量赋值给枚举变量,但不能直接把元素的序号赋值给枚举变量。,50,【例6-5】,五色球的组合:口袋中有红、黄、蓝、白、黑,5,种颜色的小球若干,如果每次都从口袋中取出,3,个不同颜色的小球,共有多少种组合?试输出每种组合的,3,种颜色。,【,问题分析,】,小球颜色的表示,【,算法描述,】,使用穷举法测试符合三种颜色要求的每种组合。,51,#include /,包含基本输入输出库头文件,using namespace std;/,使用名字空间,int main
25、)/,主函数,enum colorred,yellow,blue,white,black;,int count=0;,int temp;,for(int i=red;i=blue;+i)/,第一次取球,for(int j=i+1;j=black;+j)/,第二次取球,for(int k=j+1;k=black;k+)/,第三次取球,+count;,52,for(int t=0;t3;+t)/,输出每次组合中,3,次取球的颜色,switch(t),case 0:temp=I;break;,case 1:temp=j;break;,case 2:temp=k;break;,default:cou
26、t”impossiblen”;,switch(enum color)temp),case red:cout”red”t”;break;,case yellow:cout”yellow”t”;break;,case blue:cout”blue”t”;break;,case white:cout”white”t”;break;,case black:cout”black”t”;break;,default:cout”impossiblen”;,53,cout”n”;,cout”,共有,”,count”,种组合,”,成员变量或成员函数,对象的整体赋值,对象,1=,对象,2,对象作为函数的形式参数,
27、66,【例6-6】,定义手机类,mobile,,包括电话号码,mynumber,变量以及初始化函数,init,、拨打电话函数,dial,、接听电话函数,answer,、挂断电话函数,hangup,。,【,问题分析,】,手机类的定义。,【,算法描述,】,定义,mobile,类,67,【源程序】,#include,using namespace std;,class mobile,private:,char mynumber11;/,机主的电话号码,public:,void init(char number11=”0000000000”)/,隐式定义的内联函数,strcpy(mynumber,nu
28、mber);,void dial();/,拨打电话,void answer(char othernumber11);/,接听电话,void hangup();/,挂断电话,;,68,void mobile:dial(),cout”Dialing number is”mynumberendl;,cout”Dialing on.”endl;,void mobile:answer(char othernumber11),cout”Answering number is”othernumberendl;,cout”Answering in.”endl;,inline void mobile:hangu
29、p()/,显示定义的内联函数,cout”Hanging up.”m.mynumber;,void dial(mobile m)/,拨打电话,cout”Dialing number is”m.mynumberendl;,cout”Dialing on.”endl;,74,void answer(char othernumber11)/,接听电话,cout”Answering number is”othernumberendl;,cout”Answering in.”endl;,void hangup()/,挂断电话,cout”Hanging up.”endl;,75,int main()/mai
30、n function,mobile m1;,init(m1);,dial(m1);,hangup();,answer(”2222222222”);,hangup();,return 0;,76,【运行结果】,1111111111,Dialing number is1111111111,Dialing on.,Hanging up.,Answering number is2222222222,Answering in.,Hanging up.,77,【思路扩展】,【,例,6-6,】,与,【,例,6-7,】,的区别有哪些?,78,对象与指针,指向对象的指针,类名,*,对象指针名;,指向对象成员的指
31、针,返回值类型名,(,类名,:*,指针变量名,)(,参数表,),;,指针变量名,=,类名,:,成员函数名;,指向对象的指针和指向对象成员的指针都只能访问公有成员。,this,指针,存放对象的起始地址,79,【例6-8】,利用指向对象的指针以及指向对象成员函数指针完成手机,mobile,类中拨打、接听等函数的调用。,【,问题分析,】,指向对象的指针、指向对象成员变量的指针以及指向对象成员函数指针的使用,【,算法描述,】,在,mobile,类中使用指向对象的指针和指向对象成员函数指针,80,【源程序】,#include,using namespace std;,class mobile,publi
32、c:,char mynumber11;,void init(char number11=”0000000000”)/,隐式定义的内联函数,strcpy(mynumber,number);,void dial();/,拨打电话,void answer(char othernumber11);/,接听电话,void hangup();/,挂断电话,;,81,void mobile:dial(),cout”Dialing number is”mynumberendl;,cout”Dialing on.”endl;,void mobile:answer(char othernumber11),cout
33、Answering number is”othernumberendl;,cout”Answering in.”endl;,void mobile:hangup()/,显示定义的内联函数,cout”Hanging up.”init(”1111111111”);,p1-dial();,p1-hangup();,p1-answer(”2222222222”);,p1-hangup();,char*p2;,p2=m1.mynumber;,cout*p2endl;,83,void(mobile:*p3)(char number11);,void(mobile:*p4)();,void(mobile:
34、p5)(char othernumber11);,void(mobile:*p6)();,p3=mobile:init;,p4=mobile:dial;,p5=mobile:answer;,p6=mobile:hangup;,(m1.*p3)(”1111111111”);,(m1.*p4)();,(m1.*p6)();,(m1.*p5)(”2222222222”);,(m1.*p6)();,return 0;,84,【运行结果】,Dialing number is1111111111,Dialing on.,Hanging up.,Answering number is2222222222,
35、Answering in.,Hanging up.,1,Dialing number is1111111111,Dialing on.,Hanging up.,Answering number is2222222222,Answering in.,Hanging up.,85,【思路扩展】,指向对象的指针、指向对象成员变量的指针以及指向对象成员函数指针会在哪些情况中使用?,86,6.2.3构造函数,构造函数,在对象被创建时利用特定的值构造对象,将对象初始化为一个特定的状态。,拷贝构造函数,使用一个已经存在的对象(由拷贝构造函数的参数指定),去初始化同类的一个新对象。,析构函数,用于完成对象被删
36、除前的一些善后工作,87,构造函数,类名,(,形参列表,),函数体,88,拷贝构造函数,类名,(,类名,&,对象名,),函数体;,89,析构函数,类名,(),函数体,90,【例6-9】,定义,mobile,类,仅成员变量,mynumber,以及构造函数和析构函数。,【,问题分析,】,定义构造函数和析构函数,【,算法描述,】,定义带构造函数和析构函数的,mobile,类。,91,【源程序】,#include,using namespace std;,class mobile,public:,char mynumber11;,mobile();/,不带参数的构造函数,mobile,mobile(c
37、har number11);/,带参数的构造函数,mobile,mobile();,;,mobile:mobile(),strcpy(mynumber,”0000000000”);,coutmynumberendl;,92,mobile:mobile(char number11),strcpy(mynumber,number);,coutmynumberendl;,mobile(),cout”Turn off the phone”endl;,int main(),mobile m1;,return 0;,93,【运行结果】,0000000000,Turn off the phone,94,6.
38、2.4类的组合,组合,类名,:,类名,(,形参表,):,内嵌对象,1(,形参表,),,内嵌对象,2(,形参表,),.,类的初始化,引用,循环依赖,向前引用,95,【例6-10】,定义具有,GSM,和,CDMA,两种发射制式的,mobile,类,【,问题分析,】,内嵌对象的使用,【,算法描述,】,在,mobile,类中使用内嵌对象、构造函数和析构函数,96,【源程序】,#include,using namespace std;,class mobilecdma,private:,char mynumber11;/,机主的电话号码,public,:,mobile(char number11)/,初
39、始化,mynumber=number;,cout”Turn on the mobile”mynumberendl;,mobile(),cout”Turn off the mobile”mynumberendl;,;,97,class mobile,private:,char mynumber11;/,机主的电话号码,mobilecdma core;/CDMA,内核,内嵌对象,public:,mobile(char*number,char*number1):core(number1)/,初始化,strcpy(mynumber,number);,cout”Turn on the mobile”my
40、numberendl;,mobile(),cout”Turn off the mobile”mynumberendl;,;,98,int main(),mobile m1(”1111111111”,”2222222222”);,return 0;,99,【运行结果】,Turn on the mobile2222222222,Turn on the mobile1111111111,Turn off the mobile1111111111,Turn off the mobile2222222222,100,6.2.5多文件结构,一般把类和成员变量的定义放在一个,.h,文件,把成员函数和静态成员
41、的定义放在,.cpp,文件中,主函数放在另外的一个,.cpp,文件中。,101,【例6-11】,使用多文件结构组织,mobile,类。,【,问题分析,】,源文件划分,【,算法分析,】,mobile,类的多文件结构,102,.h,/mobil.h,文件放,mobile,的定义,#ifndef MOBILE_H,#define MOBILE_H,class mobile,private:,char mynumber11;/,机主的电话号码,public,:,mobile(char number11);/,构造函数,void dial();/,拨打电话,void answer(char othern
42、umber11);/,接听电话,void hangup();/,挂断电话,mobile();/,析构函数,#endif,103,.cpp,/mobile.cpp,文件放,mobile,成员函数的定义,#include,#include mobile.h,using namespace std;,mobile:mobile(char number11)/,初始化,strcpy(mynumber,number);,cout”Turn on the mobile”mynumberendl;,mobile:mobile(),cout”Turn off the mobile”mynumberendl;,
43、104,void mobile:dial(),cout”Dialing number is”mynumberendl;,cout”Dialing on.”endl;,void mobile:answer(char othernumber11),cout”Answering number is”othernumberendl;,cout”Answering in.”endl;,void mobile:hangup(),cout”Hanging up.”endl;,105,.cpp,/main.cpp,放主函数,#include mobile.h,#include,using namespace
44、std;,int main(),mobile m1(”1111111111”);,m1.dial();,m1.hangup();,m1.answer(”2222222222”);,m1.hangup();,return 0;,106,【运行结果】,Turn on the mobile1111111111,Dialing number is1111111111,Dialing on.,Hanging up.,Answering number is2222222222,Answering in.,Hanging up.,Turn off the mobile1111111111,107,【思路扩展
45、在什么情况下会使用类的多文件结构?,108,【例6-12】,对每个学生的成绩进行判断,找出有不及格的课程,然后显示该同学的学号姓名以及不及格课程的名称和分数。,【,问题分析,】,定义结构体的数据类型,student,,其成员分别是学号、姓名和一个数组,该数组用来保存,5,门课的成绩,初始化时给出每个学生的学号、姓名和各门课程的成绩。,【,算法描述,】,在学生成绩结构体数组中查找不及格信息。,109,【源程序】,#include,using namespace std;,int main(),struct student,char stno9;,char stname20;,int scor
46、e5;,;,110,student stud10=08091101,张品,76,87,69,76,78,08091102,李利,97,67,79,45,90,08091103,应一利,54,69,76,79,56,08091104,周勤,87,88,97,99,76,08091105,吴风,69,56,98,34,32,08091106,赵强,77,87,99,65,76,08091107,李力平,91,67,67,87,65,08091108,张军利,87,45,77,56,79,08091109,冯红,100,69,89,89,76,08091110,孙李,99,76,97,96,79;,
47、char course520=,数学,物理,化学,英语,计算机,;,int i,j,cnt;,cout,每个同学的成绩:,endl;,cout,学号,t,姓名,t,数学,t,物理,t,化学,t,英语,t,计算机,endl;,cout=endl;,111,for(i=0;i10;i+),coutstudi.stnotstudi.stnamet;,for(j=0;j5;j+),coutstudi.scorejt;,coutendl;,cout=endl;,cout,不及格同学的课程和成绩如下:,endl;,/,处理不及格分数,for(i=0;i10;i+),cnt=0;,112,for(j=0;j
48、5;j+),if(studi.scorej0),cout“,姓名:,”,studi.stname“,学号:,”,studi.stno“,不及格门数:,cntendl;,cout=endl;,for(j=0;j5;j+),if(studi.scorej60),coutcoursej:studi.scorejendl;,cout=id,id);,strcpy(this-name,name);,this-gender=gender;,this-age=age;,strcpy(this-birthplace,birthplace);,strcpy(this-familyAddress,familyAd
49、dress);,120,void input(),cout,请输入以下数据:,endl;,cout,身份证号,t;,cout,姓名,t;,cout,性别,t;,cout,年龄,t;,cout,籍贯,t;,cout,家庭住址,this-id;,cinthis-name;,cinthis-gender;,cinthis-age;,cinthis-birthplace;,cinthis-familyAddress;,121,void output(),cout,身份证号,t;,cout,姓名,t;,cout,性别,t;,cout,年龄,t;,cout,籍贯,t;,cout,家庭住址,endl;,co
50、utidt;,coutnamet;,coutgendert;,coutaget;,coutbirthplacet;,coutfamilyAddressid,id);,char*getID(),return this-id;,125,(,2,)可否把全部成员函数定义在类之外,比如对于,set,函数的定义可以改为以下形式:,在类中进行声明:,void set(char id,char name,char gender,int age,char birthplace,char familyAddress);,在类外进行定义:,void Citizen:set(char id,char name,ch






