2019年面向对象程序设计精品教育.ppt
面向对象程序设计,2019/6/14,2,第十章 结构,§10.1 结构 §10.2 结构与指针 §10.3 结构与数组 §10.4 传递结构参数 §10.5 结构函数 §10.6 链表结构 §10.7 联合(Union) 小结,2019/6/14,3,前面已介绍了整型、实型、字符型等基本数据结构。 介绍了处理相同数据类型数据集合的数组。 对于处理具有某种联系,可以由不同类型的数据项组成的复杂数据类型,C+称为结构。 本章内容包括结构类型及变量的定义,访问结构的成员方法,结构作为参数传递的函数调用及返回结构的函数等。,2019/6/14,4,10.1 结构,一、结构及结构变量的定义 结构是用户自定义的新数据类型。声明结构类型时,首先指定关键字struct和结构名,然后用一对花括号将若干个结构成员数据类型说明括起来。 例如,要表示一个单位职工的收入情况,需要记录每个职工的姓名、年龄、工资等信息。当用结构类型表示时,结构中应包括一个字符串分量(表示姓名),一个整型分量(表示年龄),一个浮点型分量(表示工资)。按C+规定,可做如下定义: struct person char name10; int age; float wage; ;,2019/6/14,5,其中,struct 是关键字;person 是自定义的结构类型的名称;花括号中是结构成员的说明。 person 结构类型被定义后,从使用角度看,就等效于int,char,float等基本数据类型。 类型定义通常位于main( )函数之前,使该类型在定义点后面的程序中可见。 要使用结构变量也必须先定义后使用,例如: person worker; 声明一个结构并不分配内存,内存分配发生在定义这个新数据类型的变量中。 变量一旦定义,编译器将为woker 变量分配包含三种不同数据类型成员的存储空间,2019/6/14,6,二、结构成员的访问 一旦通过定义相应结构变量,分配了空间,就可以使用点操作符“.”(或称结构成员操作符)来访问结构中的成员。左操作数为结构类型变量,右操作数为结构中的成员。 一般形式:结构变量名. 结构成员名 例如: worker.age=25; cinworker.age; cinworker.wage; 下面是一个定义结构类型和变量的简单例子:,2019/6/14,7,#include struct weather float temp; int wind; ; void main( ) weather today; today.temp=25.5; today.wind=4; cout“Temp=”today.tempendl; cout“Wind=”today.windendl; ,结果: Temp=25.5 Wind=4,2019/6/14,8,三、结构变量赋值 数组不能彼此赋值,但同类型的结构变量可以彼此赋值。 例如下面程序对结构变量赋值: #include struct person char name20; long id; float salary; ; person pr1“Li ming”, 1082422, 5300.0;,2019/6/14,9,void main( ) person pr2; pr2=pr1; /assigning pr1 to pr2 coutpr2.name“ ”pr2.id“ ”pr2.salaryendl; 结果: Li ming 1082422 5300.0 不同类型的结构变量不允许相互赋值,即使两者包含有相同的成员。 注意:在C 中结构类型名必须包含关键字struct,故定义语句为:struct person worker,manager;,2019/6/14,10,10.2 结构与指针,结构变量的成员可以通过点操作符进行访问,也可以通过指针进行访问。 若定义一个结构指针,并把一个结构变量的地址赋给它,则通过该指针可对结构变量的成员进行访问。 结构指针定义格式如下: person *p; /定义指向结构类型的指针 person pr1; /定义结构类型变量 若p= (*p).salary 等效于p-salary.,2019/6/14,11,在使用指针访问成员时,通常使用箭头操作符“-”。 例如:下面程序中,定义了结构指针,通过结构指针访问结构成员。 #include #include strut person char name20; long id; float salary; ;,2019/6/14,12,void main( ) person pr1; person *p; p= 结果为: Wang ming 12345678 4800.0,2019/6/14,13,10.3 结构与数组,如果一个数组的元素是同一种结构类型的变量,那么这种数组称为结构数组。 要定义一个结构数组,必须先定义一个结构类型,然后再定义具有这种结构类型的一个数组。 例如,定义一个包含100个元素的person 结构数组: struct person char name20; long id; float salary; ; person allone100;,2019/6/14,14,数组中每个元素是一个完整的结构变量,它包含name、id、salary三个成员分量。 allone0 访问第一个数组元素; allone99访问最后一个数组元素。 例如:下面程序对一个person 结构数组中的元素进行“冒泡法”排序,工资高的排在后面。 #include struct person char name20; long id; float salary; ;,2019/6/14,15,person allone6=“jone”,12345,3390.0, “david”,13916,4490.5, “marit”,27519,3110.0, “jasen”,42876,6230.5, “peter”,23987,4000.2, “yoke”,12335,5110.0; void main( ) person temp; for(int i=1; i6;i+) /排序轮次数 for(int j=0;j=5-i;j+) /一轮中比较,2019/6/14,16,if(allonej.salaryallonej+1.salary) /工资高的后移 temp=allonej; allonej=allonej+1; alonej+1=temp; for(int k=0;k6;k+) coutallonek.name“ ” allonek.id“ ” allonek.salaryendl; ,2019/6/14,17,运行结果为: marit 27519 3110.0 jone 12345 3390.0 peter 23987 4000.2 david 13916 4490.5 yoke 12335 5110.0 jasen 42876 6230.5,2019/6/14,18,10.4 传递结构参数,结构变量也可以作为实参数进行函数调用。可以采用传值、传址、传引用的三种方式传递参数。 一、传递结构变量值 因为传递的是实参结构变量中拷贝的数值,所以实参结构变量的数值不会因为函数的调用而被修改。 例如:下面是一个传值调用的例子 #include struct person char name20; long id; float saslary; ;,2019/6/14,19,void print(person pr) coutpr.name“ ”pr.id“ ”pr.salaryendl; person allone4=“jone”,12345,3390.0, “david”,13916,4490.5, “marit”,27519,3110.0, “yoke”,12335,5110.0; void main( ) for(int i=0;i4;i+) print(allonei); /实参数为结构数组元素 ,2019/6/14,20,结果为: jone 12345 3390.0 david 13916 4490.5 marit 27519 3110.0 yoke 12335 5110.0,2019/6/14,21,二、传递结构变量的引用 结构变量也可以按引用方式传递,此时仅把实参的地址传给形参。由于传递的是地址,可以实现由形参直接修改实参的作用。 引用传递没有传递值的拷贝数据过程,节省了传送时间和所需的存储空间,传递效率提高。 例如,将前面的程序改为用引用传递结构变量,只需在print( )函数定义时,将形参说明为引用。其函数调用方式与传递方式相同。 void print(person ,2019/6/14,22,三、传递结构变量的地址 传递结构变量地址与传递引用的功能类似,都能实现双向传递。若将前面程序改为传递结构变量的地址,只需定义print( )函数时,将形参说明为指向结构变量的指针,函数调用时传递实参结构变量的地址。 void print(person* pr) coutnameidsalaryendl; print( ,2019/6/14,23,10.5 结构函数,返回值为结构类型的函数称为结构函数。 一、返回结构变量 一个函数可以返回一个结构变量。在main( )中,调用结构函数的返回值必须赋于具有相同结构类型的变量。 例如: #include struct person char name20; long id; float salary; ;,2019/6/14,24,person getperson( ) /定义返回结构变量的函数 person temp; couttemp.name; couttemp.idtemp.salary; return temp; /返回结构变量temp void print(person ,2019/6/14,25,void main( ) person employee3; for(int i=0;i3;i+) employeei=getperson( ); /返回值赋给同类型的结构变量 print(employeei); ,2019/6/14,26,结果: Please enter a name for one person: marit Please enter ones ID number and his salary: 27519 3110.0 marit 27519 3110.0 如果将上例中的getperson( )函数改为引用传递,则可提高程序运行效率,省去函数返回值赋以同类型结构变量的操作。 改写后的程序为:,2019/6/14,27,#include struct person char name20; long id; float salary; ; void getperson(person ,2019/6/14,28,void print(person ,2019/6/14,29,二、返回结构的引用 一个函数可以返回一个结构引用,也可以返回一个结构指针。但是,不要返回一个局部结构变量的引用或指针。,2019/6/14,30,10.6 链表结构,一、结构的嵌套 结构可以嵌套,即结构中可以是另一个结构类型的成员变量。 例如: struct person struct date char name10; int month; int age; int day; float wage; int year; data payday; ; worker; 也可以表示为:,2019/6/14,31,struct person char name10; int wage; struct date int month; int day; int year; payday; worker; 结构变量payday 是嵌套在结构person 内的一个成员分量。在访问嵌套结构的成员时,可以使用多个点操作符,从最外层到最内层逐个列出成员名: worker.wage=5000.0; worker.payday.month=11; ,2019/6/14,32,二、链表结构 结构成员变量不能包含有自身的结构变量,但可以是指向该结构变量的指针 通过包含一个指向自身结构的指针,可以实现不连续分布的结构变量的遍历 如下面的结构: struct list char name20; list *pn; 其中,name成员含有实际的信息;pn 是指向另一个list 结构变量的指针。,2019/6/14,33,显然,通过结构变量中的指针成员链接,能构成任意长度的结构链,这样的结构链称为链表。链表中的每个list 结构变量称为一个结点。,2019/6/14,34,链表是由一个个有序的结点组成的,每个结点是同类型的结构变量。 通过程序可以建立和显示链表,可以插入、删除及增加结点来维护链表。 链表总是包含有链首指针,链表的操作一般都先由链首指针引导。 三、链表的创建与遍历 例如:下面程序建立一个链表,并输出该链表。 #include struct student long number; float score; student *next; ;,2019/6/14,35,student *head; /链首指针 student *greate( ) /创建链表函数 student *ps; /创建新结点指针 student *pend; /移动的链尾指针,用于在其后插入结点 ps=new student; /动态申请新建结点的存储空间 cinps-numberps-score; /结点赋值 head=NULL; /开始时链表为空 pend=ps; while(ps-number!=0) if(head=NULL) head=ps;,2019/6/14,36,else pend-next=ps; pend=ps; /S点 ps=new student; cinps-numberps-score; pend-next=NULL; delete ps; return(head); void showlist(student *head) cout“The items of list are:n”;,2019/6/14,37,while(head) coutnumberscorenext; void main( ) showlist(greate( ); ,2019/6/14,38,输入: 结果: 401 85.0 The items of list are: 410 73.0 401, 85.0 425 91.0 410, 73.0 413 68.0 425, 91.0 432 82.0 413, 68.0 0 0 432, 82.0 在main( )中,把建立链表函数greate( )的返回值head(指向链表指针)作为实参数调用showlist( )函数。,2019/6/14,39,greate( )函数中,链表创建过程如下图所示: 进入循环之前: head NULL 第一次进入循环到达S点: pend ps head 第一次循环结束后: head pend ps,2019/6/14,40,第二次循环到达S点时: head pend ps 第二次循环结束时: head pend ps 程序结束时: head,NULL,2019/6/14,41,10.7 联合(Union),联合是一种与结构相类似的构造类型。联合与结构的主要区别在于,联合类型分量所占内存空间不是各个成员所需存储空间字节数的总和,而是联合成员中所需要存储空间最大的成员所需要的字节数。 编译器规定联合各个成员共享一个公共存储空间。在任何给定的时刻,只能允许一个成员驻留在联合中,而对结构而言,则是所有的成员都一直驻留在结构中。 定义联合类型的一般形式是: union 联合名 类型 变量名; 类型 变量名; 联合变量名;,2019/6/14,42,例如定义一个名为data 的联合类型和名为data 的结构类型: union date struct data char ch; char ch; int num; int num; long lnum; long lnum; value; value;,2019/6/14,43,其存储空间分配如下:,value,ch,num,lnum,union 中value 变量,共享 4字节,value,ch,num,lnum,struct 中value 变量,2019/6/14,44,下面是一个使用联合变量的程序例子: #include void main( ) union long ig3; char s12; t; t.ig0=0x20494542; t.ig1=0x474e494a; t.ig2=0x00000a21; coutt.s; 结果: BEI JING!,例中字符串对应的ASCII码 (十六进制)分别为: B E I 空格 J I N G !n,42 45 49 20 4a 49 4e 47 21 0a,2019/6/14,45,小结,结构是一种用户定义的数据类型,声明结构时,不产生内存的分配,只是在定义结构变量时,才分配内存空间。 结构作为参数进行函数调用时,传值方式是复制实参的值,当结构很大时(很复杂时),宜采用引用传递或传址,仅传递结构变量的地址,提高程序运行效率。 结构的概念是理解各种数据结构的关键,本章介绍的单向链表就是其中之一。 在C+中,结构是类的过渡,类的功能涵盖了结构的一切。因此结构和联合的使用在不断的缩小,他们更多地用在与硬件控制有关的低级程序设计中。 当我们在过程化程序设计中,养成了良好的编程风格,掌握了C+程序结构,把握了C+函数机制,融通了指针和引用,积累了较典型的过程化程序设计经验之后,就可以轻松自在地跨入学习面向对象程序设计方法的进程。,