第十章结构体和共用体

Download Report

Transcript 第十章结构体和共用体

Slide 1

C程序设计
第9章 自定义数据类型
主讲教师: 鲁 萍

西安建筑科技大学 理学院

1


Slide 2

第9章 自定义数据类型
结构体变量
结构体数组
结构体与指针
指针与链表
共用体
枚举
小结

习题
2


Slide 3

结构体类型的定义
例1 学生信息:学号,姓名,成绩1,成绩2,成绩3,平均成绩
要求计算平均成绩,并输出学生的学号,姓名和平均成绩
问题:学生信息包含不同类型的数据

 结构体

例2 对一个班的若干学生进行管理,实现插入新生信息和删除转
学学生信息的功能。
问题:新数据无法和已有数据连续存储

 链表

3


Slide 4

结构体类型的定义
例1学生信息:学号,姓名,成绩1,成绩2,成绩3,平均成绩
要求计算平均成绩,并输出学生的学号,姓名和平均成绩
struct student{
结构体类型:
int num;
不同类型的数据的有序集合
char name[20];
float score1;
struct 类型名称 {
float score2;
成员表列
float score3;
};
float aver;
};
结构体变量:
用结构体类型说明的变量
//定义2个结构体变量
struct student stu1,stu2;
(定义结构体类型不分配内存
struct student stu[3];
单元!定义结构体变量时分配
//定义3个元素的结构体数组 存储单元)

4


Slide 5

结构体变量的初始化
定义时初始化:将各元素初值放在“{ }”里赋值给变量。
例: struct student{
int num;
char name[20];
float score1;
float score2;
float score3;
float aver;
} stu[3]={{001,"zhang3",80,88,75},
{002,"li4",90,83,84},
{003,"wang5",50,62,65}};


可以这样定义结构体变量
5


Slide 6

结构体变量的定义
存储:
(1)结构体的所有成员各自占用不 stu[0]
stu1
同的内存单元
(2)一共占用多少字节存储单元? 38字节
sizeof( struct student)
struct student{
int num;
char name[20];
float score1;
float score2;
float score3;
float aver;
}stu1,stu2;
stu[3];

stu[1]
stu2
38字节

001
“zhang3”
80
88
75
002
“li4”
90
83
84

int num
char name[20]
float score1
float score2
float score3
float aver
int num
char name[20]
float score1
float score2
float score3
float aver

stu[2]
38字节

6


Slide 7

结构体 变量引用
例11-1要求计算平均成绩,并输出学生的学号,姓名和平均成绩
struct student{
int num;
char name[20];
float score1;
float score2;
float score3;
float aver;
}stu[3]={{001,"zhang3",80,88,75},
{002,"li4",90,83,84},
{003,"wang5",50,62,65}};

stu[0]

stu[1]

001
“zhang3”
80
88
75
002
“li4”
90
83
84

num
name[20]
score1
score2
score3
aver
num
name[20]
score1
score2
score3
aver

for(i=0;i<3;i++)
{ stu[i].aver= stu[i].score1+ stu[i]. score2+ stu[i]. score3;
stu[i]. aver /=3;
}
成员的引用方式:结构体变量名. 成员名

7


Slide 8

结构体变量引用
A0901:学生信息:学号,姓名,成绩1,成绩2,成绩3,平均成绩
要求计算平均成绩,并输出学生的学号,姓名和平均成绩
for(i=0;i<3;i++)
printf("%5d%20s%8.2f\n",stu[i].num,stu[i].name,stu[i].aver);
输出学生的所有信息

printf(”%d,%s,%f,%f,%f,%f\n”,stud1); ×
不能对结构体变量整体输入输出,只能对各个成员分别输入输出
printf(”%d,%s,%f,%f,%f,%f\n”,stud1.num, stu1.name,
stu1.score1, stu1.score2, stu1.score3, stu1.aver);()

8


Slide 9

结构体例题
A0901 :#include
struct student{
int num; char name[20];
float score1; float score2; float score3;float aver;
};
void main()
{ struct student stu[3]={{001,"zhang3",80,88,75},
{002,"li4",90,83,84},
{003,"wang5",50,62,65}};
int i;
for(i=0;i<3;i++)
{ stu[i].aver=stu[i].score1+stu[i].score2+stu[i].score3;
stu[i].aver /=3;
}
for(i=0;i<3;i++)
printf("%5d%20s%8.2f\n",stu[i].num,stu[i].name,stu[i].aver);
9
}


Slide 10

指向结构体变量的指针
A0901 :#include
struct student{
int num; char name[20]; float score1; float score2; float score3;float aver;

}stu={001,"zhang3",80,88,75};

P

001
“zhang3”
80
88
75

struct student *p=&stu;
stu.
stu.score2+ p->
stu.score3;
p-> score1+ p->
p-> aver=stu.
stu. aver /=3;
(*p).
printf("%5d%20s%8.2f\n", p->
stu.num, (*p).
stu.name,(*p).
stu.aver);
1、结构体类指针变量的定义:结构体类型名称
2、通过指针变量引用成员:
1) 结构体类指针变量名->成员名 (常用)
2) (*结构体类指针变量名).成员名

*指针变量名

10


Slide 11

指向结构体数组的指针
A0901 :#include
struct student{
int num; char name[20]; float score1; float score2; float
aver;
001
P score3;float
“zhang3”
}; stu[3]={{001,"zhang3",80,88,75},{002,"li4",90,83,84}, {003,"wang5",50,62,65}};

stu[0]

struct stud *p=stu;

p++ 指向数组中
的下一个元素

80
88
75

002
for(p=stu;p“li4”
{ p->aver=p->score1+p->score2+p->score3;
90
stu[1]
p->aver /=3;
83
84
}
for(p=stu;pprintf("%5d%20s%8.2f\n", p->num, p->name, p->aver);
stu[2]

11


Slide 12

用指针构成链表
struct student{
int num;
char name[20];
float score1;
float score2;
float score3;
float aver;

新 增加 一个学生? 不行!
数组不能动态定义!新增信息存储单元不连续
001

链表:可以使物理上不连续的存储单元在逻辑
“zhang3”
80
上连续访问

struct student *next;
1249

};

指针

88
75
81.3
002
“li4”
90
83
84
85.7
003
指针
wang5
50
62
65
59

1356

1475

指针

每个结构中的最后一个是指针,
指向下一个节点的首地址,形成链式结构

12


Slide 13

构建链表
A0902例 建立如下链表,由3个学生数据的结点组成。输出
各结点中的数据,并计算学生成绩的平均值。

head
next

链表的起始

001

002

004

89.5

90

85

next

next

next

struct student
{ int num;
float score;
struct student *next;
};

=NULL

标记链表的结束

13


Slide 14

构建链表
void main()
struct student
{ struct student a,b,c,*head,*p;
{ int num; float score;
a.num=001; a.score=89.5;
struct student *next;
b.num=002; b.score=90;
};
c.num=004; c.score=85;
a
b
c
head=&a;
head
a.next=&b;
P
001 P
002 P
004
next
b.next=&c;
89.5
90
85
c.next=NULL;
p=head;
next
next
next
while ( p!=NULL)
{ printf(“%d % f \n”,p->num,p->score);
NULL
P
p=p->next;
}
14
}


Slide 15

链表操作:插入、删除
1. malloc 函数:
//动态申请一个节点空间
内存动态存储区中分配一个长度
struct student *d;
为size的连续空间
int len=sizeof(struct student); 2. free函数 释放空间
d=(struct student *) malloc(len);
d-->
//为节点赋值
003
scanf("%d",&(d->num));
78
scanf("%f",&(d->score));
next
a
b
//将节点插入链表head
c
d->next=b.next;
004
001
002
next
b.next=d;
85
89.5
90
//链表删除元素d
next
b.next=d->next
next
next
free(d);

//释放空间

=NULL
15


Slide 16

结构体数组练习
A0903:有10人投票,对3个候选人得票进行统计。每此
输入一个候选人的名字,要求输出最后统计结果。
【程序思路分析】
将输入的后选人的名字与结构体中的初始名字比较,若
两者相等,则将该后选人的票数加1;
投票人数通过循环方式进行控制;有多少人就循环多少
次,但每次只能投一个人的票。
结构定义:
struct person{
char name[20];
int count;
}pers[3]={{"Zhang",0},{"Wang",0},{"Li",0}};
16


Slide 17

main(){
struct person{
char name[20];
int count;
}pers[3]={{"Zhang",0},{"Wang",0},{"Li",0}};
int i=0,j=0;
char nam[20];
for (;i<10;i++){ /*控制投票人数*/
scanf(“%s”,nam); /*输入候选人姓名*/
for(j=0;j<3;j++) /*控制候选人数*/
if(strcmp(nam,pers[j].name)==0) pers[j].count++;
}
printf("\n");
for(i=0;i<3;i++)
printf("%6s %d",pers[i].name,pers[i].count);
}

17


Slide 18

结构体变量嵌套
成员也可以是一个结构变量。
struct clock
{ int hour, minute, second;};
struct date
{ int year, month, day;
struct clock time;
} today,nextday ;
1. 单独引用结构体变量的成员

today.year=2004;
today.time.second=15;
2. 结构体变量作为一个整体引用

nextday=today;
18


Slide 19

共用体
共用体类型定义
使几种不同类型的变量存放到
同一内存单元中,相互覆盖。
union 类型名称{
成员表列
};
变量定义:方法同结构体
变量引用
共用体变量名.成员名称
例:a.i=1;
a.ch=‘A’;
a.f=10.50;
完成上述赋值操作后,有效
的成员是a.f

union data{
int i;
char ch;
float f;
};
a,b,c;

共用体变量所占内存长度
等于最长的成员的长度
地址
1000

整形
i

1000

字符变
量ch

1000


f

变量
i


f


f


f
19


Slide 20

枚举类型
一、枚举类型的定义[格式]:
enum 枚举类型名称 {枚举类成员名}
例:enum weekday{sun,mon,tue,wed,thu,fri,sat};
0
1
2
3
4
5
6
枚举元素从数值0开始编号,按常量处理
例: main(){
enum weekday{sun,mon,tue,wed,thu,fri,sat};
enum weekday today=mon;
printf(“today=%d ",today);
}
运行结果: today=1

20


Slide 21

小结——自定义数据类型
struct student{
int num;
char name[20];
float score1;
float score2;
float score3;
float aver;
}stu,s[3];

结构体:
 结构体变量的引用
结构体数组
用指针访问结构体

构建链表

共用体

001

002

004

枚举

89.5

90

85

next

next

next
21


Slide 22

习题
B0901(习题9.1) 定义一个结构体变量(包括年、月、日)。
计算该日在本年中是第几天,注意闰年的问题
B0902 (习题9.5)有10个学生,每个学生的数据包括学号、
姓名、3门课的成绩,从键盘输入10个学生数据,要求计
算每个学生的平均成绩,并输出平均分最高的学生的所有
信息。
(该程序可扩展为对任意一个班的学生)

22