1、第七章 结构与联合,C+语言程序设计,2,本章主要内容,结构类型和对象的定义、初始化、成员函数的访问。 单链表的建立和遍历 运算符的定义与使用 联合类型和对象的定义与使用,结构的概念,用 int、double 等简单数据类型,只能从一个特定的角度来描述事物,如用 int 型数据来描述一个人的年龄,用 double 型数据描述一个人的工资等; 结构是一种复合数据类型,它把若干数据(简单的或复合的)组织在一起,从而可综合地、多角度地描述事物;,结构的概念,结构示例: struct Person char name10; /姓名 bool sex; /性别 int age; /年龄 float pa
2、y; /工资 ;,结构的概念,组成结构的数据称为结构的成员(或数据成员) 在某些场合,结构数据也称为记录,其成员也称为域、数据项或字段等; 通常使用结构是只定义它的数据成员,不定义它的成员函数。,结构的定义, 定义格式: struct 结构类型名 成员定义1 成员定义2 成员定义n ;,结构的定义,格式中的 成员定义 与变量定义的格式基本相同,只是不允许初始化,如:,struct A int a,b,c; ;,struct B char ch; int x,y; double z; ;,struct C char *cp; int a5; ;,结构的定义,由于不能初始化,结构中无法定义引用成员
3、 结构中的可以有结构成员,如: struct Person; struct CLASS /班级 char class_id10; /班号 Person monitor; /班长 int num_of_student;/人数 ;,结构的定义,结构中可以包含指向另一结构数据的指针,例如: struct AA; struct BB int b; AA *pAA; ;,结构的定义,结构中甚至可以包含指向自身的的指针,例如: struct F double data; F *next; ;,结构的定义,如果两个结构都包含有指向对方的指针,则其中一个结构必须提前声明,例如: struct BB;AA *p
4、a; struct AA;BB *pb;,结构的定义,如果两个结构都包含有指向对方的指针,则其中一个结构必须提前声明,例如: struct BB;AA *pa; struct AA;BB *pb;,可以为不完整的定义,struct AA;,结构体变量的定义、初始化,定义格式: 【struct】结构类型名 变量名 【=初始化数据同类型变量名】, ;举例: struct Arith char op; int a,b; ;,struct Arith x,y; Arith z1=+,10,xx, z2=*,60, z3=z1; Arith *d=,结构体变量的定义、初始化,结构体变量的定义、初始化,可
5、以在定义结构类型的同时定义结构变量,例如: struct AAA char s20; int top; a1=“MicroSoft“,0, a2=a1, a3, *ap; 注意: 如无特别必要,还是分开定义进行为好。,结构体变量的定义、初始化,结构类型的定义和结构变量的定义同时进行时,结构类型可以是无名的(常用于定义结构中的结构成员),例如: struct BBB char name10; struct int yy,mm,dd; birth; ;,结构体变量的定义、初始化,new运算符创建动态结构变量或动态结构数组,如:Airth *p = new Arith;Airth *q = new
6、Arith n; delete删除占用的空间delete p;delete q;,结构体变量的定义、初始化,用初始化数据对结构变量初始化,是将每个成员值依次复制到变量的相应域中。 当仅对结构变量的部分成员初始化时,未被初始化的成员由系统自动置为0。 全局域和文件域结构变量和static局部结构变量未被初始化时,每个成员被系统自动赋为0。 非静态的局部结构变量未被初始化时,它的每个成员的值是随意的,即不确定。,结构数据所占用的空间,结构数据所占空间的大小,理论上等于各成员大小之和。例如: sizeof(Arith) 应等于 sizeof(op) +sizeof(a) +sizeof(b),结构数
7、据所占用的空间,而实际占用空间的大小取决于编译系统的关于对齐方式的设置,有可能不同于理论值。对齐方式包括:1字节、2字节、4字节、8字节等方式。 对齐方式的“字节”数越多,对成员访问的速度就越快,但占用的空间也可能越多。,结构数据所占用的空间,Visual C+ 和 C+Builder 的默认对齐方式为“8字节” 只有在1字节方式下,才能保证实际值等于理论值。对于磁盘文件记录的结构,通常应采用1字节方式。 如无特别说明,结构空间大小均指理论大小。,结构数据所占用的空间,字节对齐三个原则结构体变量的首地址能够被其最宽基本类型成员的大小整除; 结构体每个成员相对于结构体首地址的偏移量都是成员大小的
8、整数倍,如果需要编译器会在成员之间填充字节; 结构体的总大小为结构体最基本类型成员大小的整数倍,如有需要编译器会在最末一个成员后加上填充字节。,结构数据所占用的空间,如:struct S1 struct S2char a; int b;int b; char a;short c; short c; ; 大小12 ; 大小8,结构成员的访问操作,格式: 结构变量.成员名 结构指针-成员名 例如: struct Arith char op; int a,b; ; Arith d=+,3,7,*pd=,结构成员的访问操作,struct AA int c;struct int n,m; *c; *p;
9、 p-c-n = (*p).c-n = (*(*p).c).n = (*p-c).n /等价,结构与数组的比较,相同点:都是复合型数据 不同点: 数组的“成员”都是同类型的,而结构的成员可以是不同类型的; 数组的“成员”通过 下标 进行访问,结构的成员通过 .成员名 进行访问 单独的数组变量名是指向数组的指针,而单独的结构变量名不是指针,它代表该结构数据本身; 数组数据不能整体赋值,而同类型结构数据可以整体赋值。,结构与函数, 结构数据可以作为函数的参数和函数的返回值,且都按“传值”方式传送; 由于参数按“传值”方式传送,当结构较大时,要耗费较多的空间和时间; 因此当结构较大时,可将参数定义为
10、引用参数,或常值引用参数。,例:对保存在结构数组的学生记录进行排序,使之按学号的由小到大的顺序排列在数组中;学生记录的结构如下:struct Student /学生记录结构 char num8; /学号 char name10; /姓名 short grade; /成绩 ;,结构与函数,假定要排序的结构数组是:Student a5= “ch231“,“王广敏“,69, “ec115“,“刘文“,82, “dt327“,“古明“,72, “cs102“,“张平“,78, “bx214“,“张文远“,65 ;,结构与函数,26:void range(int n)27:28: for(int i=1
11、;i0 35: ,结构与函数,结构与函数,例:从保存有学生记录的结构数组中查找一个给定学号的记录,若能够找到,返回记录位置(即元素下标)以示查找成功,否则返回-1以示查找失败。,结构与函数,6:int search(Student s, int n, Student x)7: 8:9: for(int i=0; in; i+)10: if(strcmp(si.num, x.num)=0)11: return i;12: return -1;13:,结构与函数,例:重新设计上例中search函数,使其在查找学生记录时,若成功则返回指向该记录的指针,否则返回空指针。,结构与函数,6:Student
12、* search(Student s, int n, const Student 12:,可以改为: const Student s,可以改为: return s+i;,可以改为: return NULL;,可以改为: if(!strcmp(si.num,x.num),结构与链表,结点和链表示意: struct IntNode int data; IntNode* next; ;,结构与链表,实现链表的创建、遍历、删除 void creatlist(IntNode*,结构与链表,12:void create(IntNode *,22: f=new IntNode; 23: f-data=x;
13、f-next=NULL; 24: if(n=1) return; 25: IntNode* p=f; 26: 27:/循环n-1次,每次建立一个结点链接到表尾 28: for(int i=1; ix; 30: p-next=new IntNode; 31: p=p-next; 32: p-data=x; 33: 34: p-next=NULL; 35:,结构与链表,57:void traverse(IntNode *f) 58: 59: while(f) 60: coutdatanext; 62: 63: coutendl; 64:,结构与链表,67:void deletelist(IntNo
14、de *f) 68: 69: while(f) 70: IntNode *p=f; 71: f=f-next; 72: delete p; 73: 74:,结构与链表,76:void main() /演示 77: 78: IntNode *head1=NULL, *head2=0; 79: int n; 80: coutn; 82: create(head1, n); 83: traverse(head1); 84: create1(head2, n); 85: traverse(head2); 86: deletelist(head1); 87: deletelist(head2); 91:
15、 ,结构与运算符重载, 运算符重载的概念 1.在C+中,运算符被视作一种特殊的函数,因此运算符重载就是一种特殊的函数重载。 2.重载的运算符称为运算符函数,函数名就是 operator 操作符 ,例如: operator + 3.运算符重载函数有两种等价的调用格式,例如,若重载了+,则 a+b 和 operator+(a,b) 都是对 operator+ 的合法调用。 重载的操作符应尽可能保持其原有的基本语义。,结构与运算符重载,- 运算符函数的定义 定义运算符函数的格式与定义一般函数的格式相同.operator (参数)operator (参数1,参数2) - 但要注意 前向自增减运算ope
16、rator + (参数) 后向自增减运算operator + (参数,int),虚设,可以不给出参数名,结构与操作符重载.,实例研究 例:已知一个表示分数的结构类型定义如下: struct Fraction /分数类型 int nume; /分子和符号 int deno; /分母 ; 用运算符重载实现针对分数(Fraction型对象)的下列操作:,结构与操作符重载,1分数的加法(+)2判断两分数是否相等(=)3显示输出一个分数()4. 键盘输入一个分数()5. 前增1 (+)6. 后增1 (+),重载操作符使用示例:Fraction a,b,c;cinab;c=a+b; cout“c: “c;
17、 if(a=b)cout“a=b“endl;elsecout“a!=b“endl;,结构与操作符重载,结构与操作符重载,1. 分数的加法 Fraction operator+(const Fraction ,结构与操作符重载,2. 判断两分数是否相等 bool operator=(const Fraction ,结构与操作符重载,4. 键盘输入一个分数istream ,5. 前增1 Fraction ,重载操作符使用示例:Fraction a,b,c;cinab;c=a+b; cout“c: “c; if(a=b)cout“a=b“endl;elsecout“a!=b“endl;,联合, 联合
18、的概念 不可并存的数据:学校借书证例子 enum reader_typeTEACHER,STUDENT; struct teacher_data char staff_id6; /职工号 char depart12; /工作部门 ; struct student_data char stu_id7; /学号 char class8; /班级 ;,联合,struct Reader char id5; /借书证号 char name8;/姓名 reader_type type; teacher_data teacher; student_data student; ;,联合,借助于联合,可使不可并
19、存的数据共享空间: struct Reader char id5; /借书证号 char name8;/姓名 reader_type type; union teacher_data teacher; student_data student; data; ;,联合,-联合数据的所有成员共同占有从同一起始地址开始的存储空间; -在任意时刻,联合数据的所有成员中只有一个成员有意义; -联合数据所占用的空间等于其中最大的一个成员所占用的空间。,联合, 联合类型的定义 与结构类型定义的格式基本相同,只须将保留字 struct 换成 union 即可,例如: union utype char ch; int gr; int *pt; double db; ;,联合., 联合变量的定义 与结构变量定义的格式相同,但只允许对联合中的第一个成员进行初始化,如: utype a,b; utype x=A;/对 ch 初始化,联合, 联合成员的访问 与结构成员的访问方式完全相同,也是借助于.和-这两个操作符; 对于匿名联合,由于是没有名称的联合变量,因此可直接访问其成员,例如: Reader a_stud; a_stud.type=STUDENT; strcpy(a_stud.student.class, “00130321“);,The End,第七章,