第 8 章 结构体与共用体
description
Transcript of 第 8 章 结构体与共用体
第第 88 章 结构体与共用体章 结构体与共用体第第 88 章 结构体与共用体章 结构体与共用体
CC 语言程序设计语言程序设计
23/4/21 2
本章内容本章内容本章内容本章内容 结构体(结构结构体(结构 structurestructure )类型)类型 共用体(联合共用体(联合 unionunion )类型)类型 结构体变量、结构体数组、结构体指针结构体变量、结构体数组、结构体指针 向函数传递结构体向函数传递结构体 用结构体指针实现动态数据结构用结构体指针实现动态数据结构 链表的概念及操作原理 链表的概念及操作原理
23/4/21 3
从基本数据类型、复合数据类型到从基本数据类型、复合数据类型到抽象数据类型抽象数据类型
从基本数据类型、复合数据类型到从基本数据类型、复合数据类型到抽象数据类型抽象数据类型
二进制数二进制数————类型本不存在类型本不存在– 内存里存的内容,你认为它是什么,它就是什么内存里存的内容,你认为它是什么,它就是什么– 在早期的机器指令及汇编语言中,数据对象均用二在早期的机器指令及汇编语言中,数据对象均用二进制数表示,没有类型的概念进制数表示,没有类型的概念
一般的一般的 CPUCPU 只支持两种类型只支持两种类型– 整数、浮点数整数、浮点数
23/4/21 4
从基本数据类型、复合数据类型到从基本数据类型、复合数据类型到抽象数据类型抽象数据类型
从基本数据类型、复合数据类型到从基本数据类型、复合数据类型到抽象数据类型抽象数据类型
在高级语言引入了基本数据类型在高级语言引入了基本数据类型– 整型、浮点型、字符型等整型、浮点型、字符型等– 不同语言会定义不同的基本类型不同语言会定义不同的基本类型– 基本数据类型并不能方便地解决所有问题基本数据类型并不能方便地解决所有问题
有些语言(如有些语言(如 PL/1PL/1 )中试图规定较多的类型,如数组、)中试图规定较多的类型,如数组、树、栈等,但实践证明不是个好办法树、栈等,但实践证明不是个好办法
23/4/21 5
从基本数据类型、复合数据类型到从基本数据类型、复合数据类型到抽象数据类型抽象数据类型
从基本数据类型、复合数据类型到从基本数据类型、复合数据类型到抽象数据类型抽象数据类型
用户自己构造数据类型用户自己构造数据类型 -- 复合数据类型复合数据类型– 由基本数据类型迭代派生而来,表示复杂的数据对象由基本数据类型迭代派生而来,表示复杂的数据对象
典型的代表就是“结构体”典型的代表就是“结构体” 数组和指针数组和指针
23/4/21 6
抽象数据类型(抽象数据类型( Abstract Data TypeAbstract Data Type ,简称,简称 ADAD
TT ))– 在复合数据类型基础上增加了对数据的操作在复合数据类型基础上增加了对数据的操作
抽象数据类型进而进化为“类抽象数据类型进而进化为“类 (Class)”(Class)”
– 这是一个跨时代的进步这是一个跨时代的进步– ClassClass 是是 Object-OrientedObject-Oriented 的一个重要概念的一个重要概念
从基本数据类型、复合数据类型到从基本数据类型、复合数据类型到抽象数据类型抽象数据类型
从基本数据类型、复合数据类型到从基本数据类型、复合数据类型到抽象数据类型抽象数据类型
23/4/21 7
思考一个问题思考一个问题思考一个问题思考一个问题 在程序里表示一个人(姓名、年龄、性别在程序里表示一个人(姓名、年龄、性别……),怎么表),怎么表
示?示? 想表示多个人呢?想表示多个人呢? 如何用计算机程序实现下述表格的管理?如何用计算机程序实现下述表格的管理?
表 8-1 某学校学生成绩管理表学号 姓名 性别 入学时间 计算机原理 英 语 数 学 音 乐1 令狐冲 男 1999 90 83 72 82
2 林平之 男 1999 78 92 88 78
3 岳灵珊 女 1999 89 72 98 66
4 任莹莹 女 1999 78 95 87 90
5 … …
6 … …
23/4/21 8
数组的解决方法数组的解决方法数组的解决方法数组的解决方法int int studentId[30];studentId[30]; /* /* 最多可以管理最多可以管理 3030 个学生个学生 , ,
每个学生的学号用数组的下标表示每个学生的学号用数组的下标表示 **//
charchar studentName[30][10];studentName[30][10];
charchar studentSex[30][2];studentSex[30][2];
int int timeOfEnter[30]; timeOfEnter[30]; /* /* 入学时间用入学时间用 intint 表示表示 **//
int int scoreComputer[30];scoreComputer[30];/*/* 计算机原理课的成绩计算机原理课的成绩 **//
int int scoreEnglish[30];scoreEnglish[30]; /* /* 英语课的成绩英语课的成绩 **//
int int scoreMath[30];scoreMath[30]; /* /* 数学课的成绩数学课的成绩 **//
int int scoreMusic[30];scoreMusic[30]; /* /* 音乐课的成绩音乐课的成绩 **//
23/4/21 9
intint studentId[30] = {1,2,3,4,5,6}; studentId[30] = {1,2,3,4,5,6};
charchar studentName[30][10]={{"studentName[30][10]={{" 令狐冲令狐冲 "},{""},{" 林平之林平之 "},"},
{"{" 岳灵珊岳灵珊 "},{""},{" 任莹莹任莹莹 "}};"}};
charchar studentSex[30][2]={{"studentSex[30][2]={{" 男男 "},{""},{" 男男 "},{""},{" 女女 "},"},
{"{" 女女 "}};"}};
intint timeOfEnter[30] = {1999,1999,1999,1999};timeOfEnter[30] = {1999,1999,1999,1999};
intint scoreComputer[30] = {90,78,89,78};scoreComputer[30] = {90,78,89,78};
intint scoreEnglish[30] = {83,92,72,95};scoreEnglish[30] = {83,92,72,95};
intint scoreMath[30] = {72,88,98,87};scoreMath[30] = {72,88,98,87};
intint scoreMusic[30] = {82,78,66,90}; scoreMusic[30] = {82,78,66,90};
数组的解决方法数组的解决方法数组的解决方法数组的解决方法
23/4/21 10
数据的内存管理方式数据的内存管理方式
90788978
……
83927295
……
72889887
……
82786690
……
1
234
……
令狐冲林平之岳灵珊任莹莹
……
男男女女
……
1999199919991999……
数组的解决方法数组的解决方法数组的解决方法数组的解决方法
23/4/21 11
数据的内存管理方式数据的内存管理方式
90788978
……
83927295
……
72889887
……
82786690
……
1
234
……
令狐冲林平之岳灵珊任莹莹
……
男男女女
……
1999199919991999……
数组的解决方法数组的解决方法数组的解决方法数组的解决方法
分配内存不集中,寻址效率不高 对数组进行赋初值时,容易发生错位
结构显得比较零散,不容易管理
23/4/21 12
希望的内存分配图希望的内存分配图 希望的内存分配图希望的内存分配图 1
令狐冲男
1999
90
83
72
82
2
林平之男
1999
78
92
88
78
3
岳灵珊女
1999
89
72
98
66
4
任莹莹女
1999
78
95
87
90
23/4/21 13
结构体的解决方法结构体的解决方法结构体的解决方法结构体的解决方法 struct struct STUDENTSTUDENT
{{int int studentID;studentID; /* /* 每个学生的序号每个学生的序号 **/ / char char studentName[10];studentName[10];/*/* 每个学生的姓名每个学生的姓名 **/ / char char studentSex[4];studentSex[4]; /* /* 每个学生的性别每个学生的性别 **/ / intint timeOfEnter;timeOfEnter; /* /* 每个学生的入学时间每个学生的入学时间 **/ / intint scoreComputer;scoreComputer; /* /* 每个学生的计算机原理成绩每个学生的计算机原理成绩
**/ / intint scoreEnglish;scoreEnglish; /* /* 每个学生的英语成绩每个学生的英语成绩 **/ / intint scoreMath;scoreMath; /* /* 每个学生的数学成绩每个学生的数学成绩 **/ / intint scoreMusic;scoreMusic; /* /* 每个学生的音乐成绩每个学生的音乐成绩 **/ /
};}; structstruct STUDENT STUDENT 是一个类型是一个类型 structstruct STUDENT STUDENT students[4];students[4]; students[0].studentIDstudents[0].studentID
students[0].scoreComputerstudents[0].scoreComputer– 它们都是变量,一般称为结构的成员变量它们都是变量,一般称为结构的成员变量
23/4/21 14
用户自定义的数据类型用户自定义的数据类型用户自定义的数据类型用户自定义的数据类型 结构体:结构体:
– 把把关系紧密关系紧密、且、且逻辑相关逻辑相关的多种的多种不同类型不同类型的变量,组织的变量,组织到统一的名字之下到统一的名字之下
– 占用占用相邻相邻的一段内存单元的一段内存单元 共用体:共用体:
– 把把情形互斥情形互斥、但、但逻辑相关逻辑相关的多种的多种不同类型不同类型的变量,组织的变量,组织到统一的名字之下到统一的名字之下
– 占用占用同一段同一段内存单元,每一时刻只有一个数据起作用内存单元,每一时刻只有一个数据起作用
23/4/21 15
10010 LiFun M 18 87.5 Beijingnum name sex age score addr
形成一个样板形成一个样板用于生成结构体变量用于生成结构体变量
struct 结构体名{ 类型关键字 成员名 1; 类型关键字 成员名 2; …... 类型关键字 成员名 n;};
构成结构体的变量构成结构体的变量称结构体称结构体成员(成员( membermember ))也称也称域(域( filedfiled ))
结构体类型的定义结构体类型的定义结构体类型的定义结构体类型的定义
Don’t forget the Don’t forget the
semicolonsemicolon!!!! struct student{ int num; char name[20]; char sex; int age; float score; char addr[30];};
23/4/21 16
10010 LiFun M 18 87.5 Beijingnum name sex age score addr
struct student{ int num; char name[20]; char sex; int age; float score; char addr[30];};
struct 结构体名{ 类型关键字 成员名 1; 类型关键字 成员名 2; …... 类型关键字 成员名 n;};
结构体类型的定义结构体类型的定义结构体类型的定义结构体类型的定义
只定义了数据的形式,即声明了一种复杂的数据类型,并未生成任何变量。
23/4/21 17
先定义结构体类型再定义变量名
在定义类型的同时定义变量
直接定义结构体变量(不出现结构体名)
struct student student1,student2;
struct student{ int num; char name[20]; char sex; int age; float score; char addr[30];} student1,student2;
struct { int num; char name[20]; char sex; int age; float score; char addr[30];} student1,student2;
结构体变量的定义结构体变量的定义结构体变量的定义结构体变量的定义
23/4/21 18
定义自己的类型名定义自己的类型名定义自己的类型名定义自己的类型名
structstruct studentstudent student1,student2; student1,student2;/*It works*//*It works*/ studentstudent student1,student2; student1,student2;/*Can this work?*//*Can this work?*/
typedeftypedef structstruct studentstudent STUD STUD ; ;
STUDSTUD student1,student2; student1,student2; /*It works!*//*It works!*/
typedef为一种已存在的类型定义一个新名字
STUD与 struct student类型是同义词
struct student{ int num; char name[20]; char sex; int age; float score; char addr[30];};
23/4/21 19
structstruct 类型的特点类型的特点structstruct 类型的特点类型的特点 是一个一个普通的类型是一个一个普通的类型
– 可以定义该类型的变量、数组、指针可以定义该类型的变量、数组、指针…………– 可以做函数的参数类型和返回值类型可以做函数的参数类型和返回值类型– 它的成员可以是任意类型它的成员可以是任意类型
基本类型、数组、指针、结构体、共用体基本类型、数组、指针、结构体、共用体…………
structstruct 类型的变量类型的变量– 两个结构体变量之间可以相互赋值两个结构体变量之间可以相互赋值
所以做为函数的参数时,是传值调用所以做为函数的参数时,是传值调用– 可以取地址可以取地址 &&– 不可直接参与算术和比较运算不可直接参与算术和比较运算
面向对象和数据库是面向对象和数据库是 structstruct思想的发展思想的发展
23/4/21 20
结构体的内存占用结构体的内存占用结构体的内存占用结构体的内存占用 double 占用内存字节数 占用内存字节数 = 8 struct 类型用内存字节数 类型用内存字节数 = ? 是所有成员变量的内存总和吗?是所有成员变量的内存总和吗?
structstruct number number{{
shortshort i; i; charchar ch; ch;
floatfloat f; f;};};
printf("%d\n", sizeof(printf("%d\n", sizeof(structstruct number)); number));
用运算符用运算符 sizeofsizeof获得结构体大小获得结构体大小sizeofsizeof(( 变量或表达式变量或表达式 ))
sizeofsizeof(( 类型类型 ))
88
23/4/21 21
结构体的内存占用结构体的内存占用结构体的内存占用结构体的内存占用
事实上所有数据类型在内存中都是从偶数偶数地址开始存放的且结构所占的实际空间一般是按照机器字长对齐的不同的编译器、平台,对齐方式会有变化结构体变量的成员的存储对齐规则对齐规则是与机器相关的具有特定数据类型的数据项的大小数据项的大小也是与机器相关的所以一个结构体在内存中的存储格式也是与机器相关的
ii ffchch
ii chch ff
23/4/21 22
struct STUDENT{
int studentID;char studentName[10];char studentSex[4];struct date timeOfEnter;int scoreComputer;int scoreEnglish;int scoreMath;int scoreMusic;
}; struct STUDENT stu[30];
结构体数组结构体数组结构体数组结构体数组学号 姓名 性别
入学时间计算机
原理年 月 日 英语 数学 音乐
struct date{ int year; int month; int day;};
结构体定义可以嵌套
23/4/21 23
struct STUDENT stu[30] = {{1," 令狐冲 ","男 ",{1999,08,26},90,83,72,82}, {2," 林平之 ","男 ",{1999,08,26},78,92,88,78}, {3," 岳灵珊 ","女 ",{1999,08,26},89,72,98,66}, {4," 任莹莹 ","女 ",{1999,08,26},78,95,87,90} };
初始化初始化
结构体数组结构体数组结构体数组结构体数组struct STUDENT{
int studentID;char studentName[10];char studentSex[4];struct date timeOfEnter;int scoreComputer;int scoreEnglish;int scoreMath;int scoreMusic;
};
23/4/21 24
struct STUDENT stu[30] = {{1," 令狐冲 ","男 ",{1999,08,26},90,83,72,82}, {2," 林平之 ","男 ",{1999,08,26},78,92,88,78}, {3," 岳灵珊 ","女 ",{1999,08,26},89,72,98,66}, {4," 任莹莹 ","女 ",{1999,08,26},78,95,87,90} };
初始化初始化
1 令狐冲 男901999 8 26
80 72 82
2 林平之 男781999 8 26
92 88 78
3 岳灵珊 女891999 8 26
72 98 66
4 任莹莹 女781999 8 26
95 87 90
建立了数据库中的多条记录,每条对应一个学生信息建立了数据库中的多条记录,每条对应一个学生信息
23/4/21 25
结构体变量的指针结构体变量的指针结构体变量的指针结构体变量的指针pStu
stustruct STUDENT{
int studentID;char studentName[10];char studentSex[4];struct date timeOfEnter;int scoreComputer;int scoreEnglish;int scoreMath;int scoreMusic;
};
structstruct STUDENT stu;stu; /* /* 定义结构体变量定义结构体变量 **// structstruct STUDENT *pStu; *pStu; /*/* 定义结构体指针定义结构体指针 **// pStu = &stu;pStu = &stu;
成员 1
成员 2
成员 3
成员 4
成员 5
成员 6
成员 7
成员 8
23/4/21 26
pStustu
struct STUDENT{
int studentID;char studentName[10];char studentSex[4];struct date timeOfEnter;int scoreComputer;int scoreEnglish;int scoreMath;int scoreMusic;
};
structstruct STUDENT stu;stu; /* /* 定义结构体变量定义结构体变量 **// structstruct STUDENT *pStu; *pStu; /*/* 定义结构体指针定义结构体指针 **// pStu = &stu;pStu = &stu;
成员 1
成员 2
成员 3
成员 4
成员 5
成员 6
成员 7
成员 8
如何访问结构体的成员如何访问结构体的成员如何访问结构体的成员如何访问结构体的成员
通过通过 sstutu 和和成员运算符成员运算符访问结构体成员访问结构体成员– stu.stu.studentID = 1; studentID = 1;
通过通过 pStupStu 和和指向运算符指向运算符访问结构体成员访问结构体成员– (*pStu).(*pStu).studentID = 1;studentID = 1;– pStu->pStu->studentID = 1;studentID = 1;
23/4/21 27
struct STUDENT{
int studentID;char studentName[10];char studentSex[4];struct date timeOfEnter;int scoreComputer;int scoreEnglish;int scoreMath;int scoreMusic;
};
structstruct STUDENT stu;stu; /* /* 定义结构体变量定义结构体变量 **// structstruct STUDENT *pStu; *pStu; /*/* 定义结构体指针定义结构体指针 **// pStu = &stu;pStu = &stu;
如何访问如何访问嵌套的嵌套的结构体的成员结构体的成员如何访问如何访问嵌套的嵌套的结构体的成员结构体的成员
stu.stu.timeOfEnter.timeOfEnter. year = 1999; year = 1999;
(*pStu).(*pStu).timeOfEnter.timeOfEnter. year = 1999;year = 1999;
pStu->pStu->timeOfEnter.timeOfEnter. year = 1999;year = 1999;
struct date{ int year; int month; int day;};
23/4/21 28
思考题思考题思考题思考题 structstruct point point
{{intint x; x;intint y; y;
};};
structstruct rect rect{{
structstruct point point pt1;pt1;
structstruct point point pt2;pt2;};};
structstruct rect rt; rect rt; structstruct rect rect **rp = &rt;rp = &rt; 下面表达式哪些合法?下面表达式哪些合法?
– rt.pt1.xrt.pt1.x– (*rp).pt1.x(*rp).pt1.x– rp->pt1.xrp->pt1.x– rt->pt1.xrt->pt1.x
上面合法的表达式都是等价的上面合法的表达式都是等价的吗?吗?
23/4/21 29
struct STUDENT stu[4] = {{1," 令狐冲 ","男 ",{1999,08,26},90,83,72,82}, {2," 林平之 ","男 ",{1999,08,26},78,92,88,78}, {3," 岳灵珊 ","女 ",{1999,08,26},89,72,98,66}, {4," 任莹莹 ","女 ",{1999,08,26},78,95,87,90} };
结构体数组的指针结构体数组的指针结构体数组的指针结构体数组的指针pStu
stu[4]struct STUDENT{
int studentID;char studentName[10];char studentSex[4];struct date timeOfEnter;int scoreComputer;int scoreEnglish;int scoreMath;int scoreMusic;
};
struct STUDENT *pStu; /*定义结构体指针 */ pStu = stu; /*相当于 pStu = &stu[0];*/
stu[0]
stu[1]
stu[2]
stu[3]
23/4/21 30
使用 pStu++,使 pStu指向 stu[i]
pStu -> studentID
等价于 stu[i]. studentID
如何访问结构体数组元素的成员如何访问结构体数组元素的成员如何访问结构体数组元素的成员如何访问结构体数组元素的成员pStu
stu[4]struct STUDENT{
int studentID;char studentName[10];char studentSex[4];struct date timeOfEnter;int scoreComputer;int scoreEnglish;int scoreMath;int scoreMusic;
};
struct STUDENT *pStu; /*定义结构体指针 */ pStu = stu; /*相当于 pStu = &stu[0];*/
stu[0]
stu[1]
stu[2]
stu[3]
23/4/21 31
向函数传递结构体向函数传递结构体向函数传递结构体向函数传递结构体 向函数传递结构体的单个成员向函数传递结构体的单个成员
– 复制单个成员的内容复制单个成员的内容
– 函数内对结构内容的修改不影响原结构函数内对结构内容的修改不影响原结构
向函数传递结构体的完整结构?向函数传递结构体的完整结构? 向函数传递结构体的首地址?向函数传递结构体的首地址?
23/4/21 32
struct date{ int year; int month; int day;};void func(struct date p){ p.year = 2000; p.month = 5; p.day = 22;}
main(){ struct date d; d.year = 1999; d.month = 4; d.day = 23; printf(“%d,%d,%d\n”, d.year, d.month, d.day); func(d); printf(“%d,%d,%d\n”, d.year, d.month, d.day);}
1999,4,231999,4,23
结构体结构体变量变量做函数参数做函数参数结构体结构体变量变量做函数参数做函数参数
23/4/21 33
struct date{ int year; int month; int day;};void func(struct date *p*p){ p->p->year = 2000; p->p->month = 5; p->p->day = 22;}
main(){ struct date d; d.year = 1999; d.month = 4; d.day = 23; printf(“%d,%d,%d\n”, d.year, d.month, d.day); func(&d&d); printf(“%d,%d,%d\n”, d.year, d.month, d.day);}
1999,4,232005,5,222005,5,22
结构体结构体指针指针做函数参数做函数参数结构体结构体指针指针做函数参数做函数参数
指针做函数形参实参必须为地址值
23/4/21 34
struct date{ int year; int month; int day;};struct datestruct date func(struct date pp){ p.p.year = 2000; p.p.month = 5; p.p.day = 22;}
main(){ struct date d; d.year = 1999; d.month = 4; d.day = 23; printf(“%d,%d,%d\n”, d.year, d.month, d.day); d =d = func(d); printf(“%d,%d,%d\n”, d.year, d.month, d.day);}
结构体变量结构体变量做函数做函数返回值返回值
结构体变量结构体变量做函数做函数返回值返回值
存在一个错误
23/4/21 35
struct date{ int year; int month; int day;};struct datestruct date func(struct date pp){ p.p.year = 2000; p.p.month = 5; p.p.day = 22; return p;return p;}
main(){ struct date d; d.year = 1999; d.month = 4; d.day = 23; printf(“%d,%d,%d\n”, d.year, d.month, d.day); d =d = func(d); printf(“%d,%d,%d\n”, d.year, d.month, d.day);}
1999,4,232005,5,222005,5,22
结构体变量结构体变量做函数做函数返回值返回值
结构体变量结构体变量做函数做函数返回值返回值
23/4/21 36
向函数传递结构体向函数传递结构体向函数传递结构体向函数传递结构体 向函数传递结构体的完整结构向函数传递结构体的完整结构
– 复制整个结构体成员的内容,多个值复制整个结构体成员的内容,多个值– 函数内对结构内容的修改不影响原结构函数内对结构内容的修改不影响原结构– 内容传递更直观,但内容传递更直观,但开销大开销大
向函数传递结构体的首地址向函数传递结构体的首地址– 用用结构体数组结构体数组 // 结构体指针结构体指针做函数参数做函数参数– 仅复制结构体的首地址,一个值仅复制结构体的首地址,一个值– 修改结构体指针所指向的结构体的内容修改结构体指针所指向的结构体的内容– 指针传递效率高指针传递效率高
23/4/21 37
for (pt=stu; pt<stu+30; pt++){
sum[0] = sum[0] + pt->scoreComputer; sum[1] = sum[1] + pt->scoreEnglish; sum[2] = sum[2] + pt->scoreMath; sum[3] = sum[3] + pt->scoreMusic;
}for (i=0; i<4; i++){ average[i] = sum[i]/4;
printf("%20s : %4.2f\n", name[i], *(average+i));
}
例例 8.2:8.2: 利用指向结构体数组的指针计利用指向结构体数组的指针计算学生各科的平均成绩算学生各科的平均成绩
例例 8.2:8.2: 利用指向结构体数组的指针计利用指向结构体数组的指针计算学生各科的平均成绩算学生各科的平均成绩
学号 姓名 性别入学时间 计算机
原理年 月 日 英语 数学 音乐
23/4/21 38
例例 8.28.2例例 8.28.2mainmain()(){{
structstruct STUDENT *pt; STUDENT *pt;floatfloat sum[4] = {0.0},average[4] = {0.0}; sum[4] = {0.0},average[4] = {0.0};intint i; i;charchar **name[]={"score of Computer","score of English",name[]={"score of Computer","score of English", "score of Math","score of Music"};"score of Math","score of Music"};
pt = stu; /*ptpt = stu; /*pt 指向结构体数组的第一个元素指向结构体数组的第一个元素 **//forfor (pt=stu; pt<stu+30; pt++) (pt=stu; pt<stu+30; pt++){{
sum[0] = sum[0] + pt->scoreComputer; sum[0] = sum[0] + pt->scoreComputer; sum[1] = sum[1] + pt->scoreEnglish; sum[1] = sum[1] + pt->scoreEnglish; sum[2] = sum[2] + pt->scoreMath;sum[2] = sum[2] + pt->scoreMath; sum[3] = sum[3] + pt->scoreMusic; sum[3] = sum[3] + pt->scoreMusic;
}}forfor (i=0; i<4; i++) (i=0; i<4; i++){{
average[i] = sum[i]/4;average[i] = sum[i]/4; printfprintf("%20s : %4.2f\n", name[i], *(average+i)); ("%20s : %4.2f\n", name[i], *(average+i));
}}}}
23/4/21 39
思考思考思考思考 下面的结构是什么意思?下面的结构是什么意思?
structstruct temp temp{{
intint data; data; structstruct temp pt; temp pt;
};}; CBCB 下的错误提示:下的错误提示:
– field 'pt' has incomplete typefield 'pt' has incomplete type TCTC 下的错误提示:下的错误提示:
– Undefined structure ‘temp’Undefined structure ‘temp’– Structure size too largeStructure size too large
VCVC 下的错误提示:下的错误提示:– 'pt' uses undefined struct ‘temp’'pt' uses undefined struct ‘temp’
下面的结构是什么意思呢?下面的结构是什么意思呢? structstruct temp temp{{
intint data; data; structstruct temp *pt; temp *pt;
};};
结构体声明时不能包含本结构体类型成员系统将无法为这样的结构体类型分配内存
可包含指向本结构体类型的指针变量
23/4/21 40
数组:线性表的顺序表示方式数组:线性表的顺序表示方式数组:线性表的顺序表示方式数组:线性表的顺序表示方式A B C D E
0 1 2 3 4
元素
序号
A B C
0 1 2 3 4
元素
下标 5
优点:便于快速、随机存取线性表中任一元素缺点:插入和删除操作需要移动大量元素
D E X
A B
0 1 2 3 4
元素
下标
C D E
23/4/21 41
数组:线性表的顺序表示方式数组:线性表的顺序表示方式数组:线性表的顺序表示方式数组:线性表的顺序表示方式A B C D E
0 1 2 3 4
元素
序号
缺点: 属于静态内存分配,程序一旦运行长度不能改变。若想改变,只能修改程序。一旦确定,会带来两个问题:
1 )不能超过数组元素最大长度的限制,否则溢出。
2 )数组元素低于所设定的最大长度,将造成系统资源的浪费。
23/4/21 42
思考思考思考思考 能否有一个办法,保证系统资源的最合理运能否有一个办法,保证系统资源的最合理运
用?用?– 当我们需要添加一个元素时,程序会自动添加;当我们需要添加一个元素时,程序会自动添加;– 当我们需要减少一个元素时,程序会自动放弃该元当我们需要减少一个元素时,程序会自动放弃该元素原来占有的内存。素原来占有的内存。
动态数据结构动态数据结构– 结构体结构体– 动态内存分配动态内存分配
23/4/21 43
链表的定义链表的定义链表的定义链表的定义
structstruct Link Link{{
intint data;data; structstruct Link Link
*next;*next;};};
data nexthead data next data next data NULL
链表链表(( Linked tableLinked table )) ::线性表的链式存储结构线性表的链式存储结构–特点:用一组任意的存储单元存储线性表的数据;特点:用一组任意的存储单元存储线性表的数据;存储单元可以是连续的,也可是不连续的存储单元可以是连续的,也可是不连续的
23/4/21 44
链表的定义链表的定义链表的定义链表的定义
structstruct Link Link{{
intint data;data; structstruct Link Link
*next;*next;};};
data nexthead data next data next data NULL
链表链表(( Linked tableLinked table )) ::线性表的链式存储结构线性表的链式存储结构–为表示每个元素与后继元素的逻辑关系,除存储元为表示每个元素与后继元素的逻辑关系,除存储元素本身信息外,还要存储其直接后继信息素本身信息外,还要存储其直接后继信息
两部分信息组成一个结点
23/4/21 45
链表的定义链表的定义链表的定义链表的定义
structstruct Link Link{{
intint data;data; structstruct Link Link
*next;*next;};};
data nexthead data next data next data NULL
链表链表(( Linked tableLinked table )) ::线性表的链式存储结构线性表的链式存储结构–为表示每个元素与后继元素的逻辑关系,除存储元为表示每个元素与后继元素的逻辑关系,除存储元素本身信息外,还要存储其直接后继信息素本身信息外,还要存储其直接后继信息
数据域:存储数据元素信息
指针域:存储直接后继的节点信息
23/4/21 46
链表的定义链表的定义链表的定义链表的定义
structstruct Link Link{{
intint data;data; structstruct Link Link
*next;*next;};};
data nexthead data next data next data NULL
链表链表(( Linked tableLinked table )) ::线性表的链式存储结构线性表的链式存储结构– nn 个节点链接成一个链表(因为只包含一个指针域,个节点链接成一个链表(因为只包含一个指针域,故又称线性链表或单向链表)故又称线性链表或单向链表)
数据域:存储数据元素信息
指针域:存储直接后继的节点信息
23/4/21 47
链表的典型实现链表的典型实现链表的典型实现链表的典型实现 CC 语言代码语言代码
data = Anode
data = Bnode
data = C ∧node
head
空指针 NULL 表示链表结尾
structstruct Link Link{{
intint data;data; structstruct Link Link
*next;*next;};};
链表的头指针:便于操作
23/4/21 48
链表的插入操作链表的插入操作链表的插入操作链表的插入操作 在在 xx 后插入新节点后插入新节点
– t = malloc(t = malloc(sizeofsizeof(struct Node));(struct Node));– t->next = x->next;t->next = x->next;– x->next = t;x->next = t;
Bx
A
t
C
23/4/21 49
链表的删除操作链表的删除操作链表的删除操作链表的删除操作 删除节点 删除节点 x -> nextx -> next
– t = x->next;t = x->next;– x->next = t->next;x->next = t->next;– free(t);free(t);
B
C
x
A
t
23/4/21 50
共用体,或称为联合(共用体,或称为联合( UnionUnion ))共用体,或称为联合(共用体,或称为联合( UnionUnion ))structstruct number number{{
shortshort i; i; charchar ch; ch;
floatfloat f; f;};};
0x0037b00unionunion number number{{
shortshort i; i; charchar ch; ch;
floatfloat f; f;};};
printf("%d\n", sizeof(struct number));printf("%d\n", sizeof(struct number));
ii chch ff
iichchff
printf("%d\n", sizeof(union number));printf("%d\n", sizeof(union number));
23/4/21 51
共用体,或称为联合(共用体,或称为联合( UnionUnion ))共用体,或称为联合(共用体,或称为联合( UnionUnion )) sizeof(union number)取决于占空间最多占空间最多的那个成
员变量
0x0037b00
同一内存单元在每一瞬时只能存放其中一种类型的成员;
起作用的成员是最后一次存放最后一次存放的成员不能作为函数参数 不能进行比较操作,只能对第一个成员初始化
ff
23/4/21 52
structstruct person person{{ charchar name[20]; name[20]; charchar sex; sex; intint age; age; unionunion {{ intint single; single; structstruct {{ charchar spouseName[20]; spouseName[20]; intint child; child; }married;}married; structstruct date divorcedDay; date divorcedDay; }marital;}marital; intint marryFlag; marryFlag;
};};
共用体的应用共用体的应用共用体的应用共用体的应用姓名name
性别sex
年龄age
婚姻状况
婚姻状况标记
未婚 已婚 离婚
配偶
子女 年 月 日
unionunion {{ intint single; single; structstruct {{ charchar spouseName[20]; spouseName[20]; intint child; child; }married;}married; structstruct date divorcedDay; date divorcedDay; }marital; }marital;
structstruct {{ charchar spouseName[20]; spouseName[20]; intint child; child;}married; }married;
23/4/21 53
实验九 结构体编程练习实验九 结构体编程练习在屏幕上模拟显示一个数字式时钟在屏幕上模拟显示一个数字式时钟
实验九 结构体编程练习实验九 结构体编程练习在屏幕上模拟显示一个数字式时钟在屏幕上模拟显示一个数字式时钟
定义一个时钟结构体类型:struct clock{ int hour; int minute; int second;};
typedef struct clock CLOCK;
23/4/21 54
voidvoid update(CLOCK *t) update(CLOCK *t) {{ t->second++;t->second++; ifif (t->second == 60) (t->second == 60) { { t->second = 0;t->second = 0; t->minute++;t->minute++; } } ifif (t->minute == 60) (t->minute == 60) {{ t->minute = 0;t->minute = 0; t->hour++;t->hour++; }}
ifif (t->hour == 24) (t->hour == 24) t->hour = 0;t->hour = 0;}}
voidvoid display(CLOCK *t) display(CLOCK *t) {{ printf("%2d:%2d:%2d\r",printf("%2d:%2d:%2d\r", t->hour, t->hour,
t->minute, t->minute, t->second);t->second);
}}
实验九 结构体编程练习实验九 结构体编程练习在屏幕上模拟显示一个数字式时钟在屏幕上模拟显示一个数字式时钟
实验九 结构体编程练习实验九 结构体编程练习在屏幕上模拟显示一个数字式时钟在屏幕上模拟显示一个数字式时钟
23/4/21 55
这一章我们学习了这一章我们学习了这一章我们学习了这一章我们学习了 两种新的数据类型两种新的数据类型
– 结构体和共用体结构体和共用体 几种重要的应用几种重要的应用
– 结构体变量结构体变量– 结构体数组结构体数组– 结构体指针结构体指针– 用结构体数组或者结构体指针做函数参数用结构体数组或者结构体指针做函数参数– 用结构体指针实现动态数据结构用结构体指针实现动态数据结构
23/4/21 56
作业作业作业作业 习题习题
– 8.1~8.4,8.68.1~8.4,8.6