第八章 结构体和共用体 结构体类型和结构体变量 结构体数组 结构体指针变量 共用体
学习目标 重点 了解 掌握 结构体类型和结构体变量 结构体数组 结构体指针变量 1 3 union共用体 typedef— 给数据类型取别名
8.1 8.2 8.3 8.4 章节框架 结构体类型和结构体变量 结构体数组 结构体指针变量 union共用体 ☞点击查看本小节知识架构 让IT教学更简单,让IT学习更有效 章节框架 8.1 结构体类型和结构体变量 ☞点击查看本小节知识架构 8.2 结构体数组 ☞点击查看本小节知识架构 8.3 结构体指针变量 ☞点击查看本小节知识架构 8.4 union共用体 ☞点击查看本小节知识架构
8.1 结构体类型和结构体变量 让IT教学更简单,让IT学习更有效 什么是结构体?
8.1 结构体类型和结构体变量 结构体是一种构造数据类型,把不同类型的数据整合在一起,每一个数据都称为该结构体类型的成员。
8.1 结构体类型和结构体变量 8.1.1 结构体类型定义 struct 结构体名 合法标识符 { 可省略:无名结构体 在程序设计中,使用结构体类型时,首先要对结构体类型的组成进行描述,结构体类型的定义方式如下: struct 结构体名 { 类型标识符 成员名1; 类型标识符 成员名2; …… }; 合法标识符 可省略:无名结构体 struct是关键字,不能省略 成员类型可以是基本类型或构造类型 必须有分号
8.1 结构体类型和结构体变量 struct employee { Int num; char name[20]; char sex; }; 结构名 struct employee { 结构成员 Int num; char name[20]; char sex; };
8.1 结构体类型和结构体变量 8.1.2 结构体变量的定义 1. 先定义结构,再说明结构变量 struct 结构体名 变量名列表; Struct employee { int num; char name[20]; char sex; int wage; char addr[30]; long int tel; }; Struct employee person1,person2; 注: 两个变量person1和person2为employee结构类型。也可以用宏定义使一个符号常量来表示一个结构类型。 9
8.1 结构体类型和结构体变量 2. 定义结构体类型的同时声明结构体变量 struct 结构体名 { 成员说明表列; }变量名表列; Struct employee { int num; char name[20]; char sex; int wage; char addr[30]; long int tel; }person1,person2;
8.1 结构体类型和结构体变量 3. 在定义结构体类型的同时说明结构体数组其一般形式为: struct { 成员说明表列; }boy[50]; struct { int num; char name[10]; int wage; char addr[30]; long int tel; }boy[50],person1,person2;
8.1 结构体类型和结构体变量 8.1.2 结构体变量的定义 结构体类型是用户自定义的一种数据类型,它同前面所介绍的简单数据类型一样,在编译时对结构体类型不分配空间。只有用它来定义某个变量时,才会为该结构体变量分配结构体类型所需大小的内存单元。
8.1 结构体类型和结构体变量 8.1.3 结构体变量的内存分配 struct date { int month; int day; int year; }; Struct employee char name[20]; char sex; struct date birthday; char addr[30]; }person1; 变量person1所占存储空间的大小为: 各成员变量所占存储单元字节数之和。
8.1 结构体类型和结构体变量 8.1.4 结构体变量的初始化 由于结构体变量中存储的是一组类型不同的数据,因此为结构体变量初始化的过程,其实就是为结构体中各个成员初始化的过程。根据结构体变量定义方式的不同,结构体变量初始化的方式可分为两种。 1.在定义结构体类型和结构体变量的同时,对结构体变量初始化 struct stduent {char name[8]; char sex; struct data birthday; float score[4]; }per[3]={{“LIMI”,’M’,1982,5,10,88.0,76.5,85.5,90.0}, {“zhangsan”,’F’,1983,10,10,85.0,76.5,95.5,70.0}, {“wangfang”,’M’,1982,6,15,82.0,76.0,75.0,90.5}};
8.1 结构体类型和结构体变量 2.定义好结构体类型后,对结构体变量初始化 如果一个结构体变量在定义时没有赋初值, 以后想赋值,必须逐个成员分别赋值,即下面的赋值方法是错误的。
8.1 结构体类型和结构体变量 8.1.5 结构体变量的引用 定义并初始化结构体变量的目的是使用结构体变量中的成员。在C语言中,引用结构体变量中一个成员的方式如下所示: 结构体变量名.成员名 在使用结构体变量时,应当遵守以下规则: (1)不能整体引用结构体变量,只能按成员使用结构体变量。其成员的引用方式为: 结构体变量名.成员名 指针变量名->成员名 (*指针变量名).成员名
√ √ √ √ √ √ √ √ 8.1 结构体类型和结构体变量 例: std.sex struct stduent { char name[8]; char sex; struct data birthday; float score[4]; }std,per[5],*ps; ps=&std; √ std.sex √ ps->sex √ (*ps).sex √ per[0].sex √ (*ps).score[2] √ ps->name √ ps->birthday.year √ per[0].birthday.month
8.1 结构体类型和结构体变量 【课堂举例】从键盘输入两个工人的姓名、工资和出生日期,输出他们各自的内容。然后交换两个人的信息,再输出各自的内容 #include<stdio.h> struct date {int year,month,day;}; struct worker { char name[30]; float pay; struct date birthday; }; void main() { struct worker man1,man2,temp; printf("输入第一个人的姓名:"); scanf("%s",man1.name); printf("输入第一个人的工资:"); scanf("%f",&man1.pay); printf("输入第一个人的出生日期(年-月-日):");
8.1 结构体类型和结构体变量 scanf("%d-%d-%d",&man1.birthday.year,&man1.birthday.month,&man1.birthday.day); printf("输入第二个人的姓名:"); scanf("%s",man2.name); printf("输入第二个人的工资:"); scanf("%f",&man2.pay); printf("输入第二个人的出生日期(年-月-日):"); scanf("%d-%d-%d",&man2.birthday.year,&man2.birthday.month,&man2.birthday.day); printf("打印输出:\n"); printf("第一个人的情况:%s出生于%d年%d月%d日,工资为%.2f元\n", man1.name,man1.birthday.year,man1.birthday.month,man1.birthday.day,man1.pay); printf("第二个人的情况:%s出生于%d年%d月%d日,工资为%.2f元\n", man2.name,man2.birthday.year,man2.birthday.month,man2.birthday.day,man2.pay);
8.1 结构体类型和结构体变量 temp=man2; man2=man1; man1=temp; printf("交换之后的情况:\n"); printf("第一个人的情况:%s出生于%d年%d月%d日,工资为%.2f元\n", man1.name,man1.birthday.year,man1.birthday.month,man1.birthday.day,man1.pay); printf("第二个人的情况:%s出生于%d年%d月%d日,工资为%.2f元\n", man2.name,man2.birthday.year,man2.birthday.month,man2.birthday.day,man2.pay); }
课堂作业 1、编程,定义一个结构体类型struct person,包含3个成员,分别是name(用来存放人的姓名),id(用来存放人的身份证号码),pay (用来存放人的工资)。定义一个变量man和woman分别是struct person类型,在程序中给man赋值(张三丰,370204197808011381,4567.8),而woman的值程序运行时,临时从键盘输入,然后输出这两个变量的值。 2、编程,定义一个结构体类型,包含y、m和d三个int型成员,分别表示一个日期的年、月、日,定义该类型的结构体变量,从键盘输入一个日期,赋给该结构体变量,并计算输出该日期是本年度中的第几天(注意闰年问题)。 3、写一个函数getdays(),实现从键盘输入一个日期,赋给该结构体变量,并计算输出该日期是本年度中的第几天(注意闰年问题)功能。主函数将年、月、日用结构体变量的形式传给getdays()函数, getdays()函数将计算结果返回,主函数中输出结果。 #include "stdio.h" struct{ int year; int month; int day;}date; void main() { int days; printf("input year,month,day:"); scanf("%d,%d,%d",&date.year,&date.month,&date.day); switch(date.month) {case 1:days=date.day;break; case 2:days=date.day+31;break; case 3:days=date.day+59;break; case 4:days=date.day+90;break; case 5:days=date.day+120;break; case 6:days=date.day+151;break; case 7:days=date.day+181;break; case 8:days=date.day+212;break; case 9:days=date.day+243;break; case 10:days=date.day+273;break; case 11:days=date.day+304;break; case 12:days=date.day+334;break; } if((date.year%4==0 && date.year%100!=0||date.year%400==0)&& date.month>3) days+=1; printf("%d/%d is the %dth day in %d.\n",date.month,date.day,days,date.year); 第二种解法: int days,i; int day_tab[13]={0,31,28,31,30,31,30,31,31,30,31,30,31}; days=0; for(i=1;i<date.month;i++) days=days+day_tab[i]; days=days+date.day;
8.2 结构体数组 8.2.1 结构体数组的定义 与前面讲解的数组不同,结构体数组中的每个元素都是结构体类型的,它们都是具有若干个成员的项。与定义结构体变量一样,可以采用三种方式定义结构体数组。 1.先定义结构体类型,后定义结构体数组 2.在定义结构体类型的同时定义结构体数组 3.直接定义结构体数组
8.2 结构体数组 8.2.2 结构体数组的初始化 结构体数组的初始化方式与数组类似,都是通过为元素赋值的方式完成的。由于结构体数组中的每个元素都是一个结构体变量,因此,在为每个元素赋值的时候,需要将其成员的值依次放到一对大括号中。 结构体数组的初始化和普通数组的初始化一样。
8.2 结构体数组 8.2.3 结构体数组的引用 结构体数组的引用是指对结构体数组元素的引用,由于每个结构体数组元素都是一个结构体变量,因此,结构体数组元素的引用方式与结构体变量类似,其语法格式如下所示: 数组元素名称.成员名
8.2 结构体数组 【课堂举例】开学之初,我所任课的班级要选一个班长,候选人是崔佳蓉、王晓慧、刘娟。全班同学对这三个候选人进行投票,要求每张选票只准选三个人当中的一个,否则作废。有效票数为10张,要求,编程统计这10张选票,输出每个候选人的得票数。
8.2 结构体数组 #include<stdio.h> #include<string.h> void main() { struct person {char name[20]; int count; }leader[3]={{"崔佳蓉",0},{"王晓慧",0},{"刘娟",0}}; int i,j; char name[20]; for(i=1;i<=10;i++) {printf("请输入第%d张选票上的名字:",i); gets(name); for(j=0;j<3;j++) if(strcmp(name,leader[j].name)==0) { leader[j].count++; break; } printf("姓名 得票 \n"); for(i=0;i<3;i++) { printf("%-10s%-10d\n",leader[i].name,leader[i].count); }
8.3 结构体指针变量 8.3.1 结构体指针变量 在使用结构体指针变量之前,首先需要定义结构体指针,结构体指针的定义方式与一般指针类似,例如,下列语句定义了一个Student类型的指针。 struct Student s = {"Zhang San", 20140100, 'M', 93.5}; struct Student *p = &s;
8.3 结构体指针变量 8.3.1 结构体指针变量 当程序中定义了一个指向结构体变量的指针后,就可以通过“指针名->成员变量名”的方式来访问结构体变量中的成员,接下来通过一个案例来演示结构体指针的用法,如例9-6所示。
8.3 结构体指针变量 【课堂举例】读程序 #include<stdio.h> struct student { char name[50]; int studentID; }; void main() struct student s={"zhang san",20140000}; struct student *p=&s; printf("%s %d\n",p->name,p->studentID); }
8.3 结构体指针变量 8.3.2 结构体数组指针 Struct sudent stu1[10], *p=stu1; 指针可以指向结构体数组,即将结构体数组的起始地址赋给指针变量,这种指针就是结构体数组指针。 struct student { int studentID; float score; }; Struct sudent stu1[10], *p=stu1; 0 1 2 3 4 001 86.5 002 92.0 003 78.0 004 66.5 005 88.0
8.3 结构体指针变量 【课堂举例】演示如何使用结构体数组指针输出多个学生的信息 #include<stdio.h> struct student { int num; char name[20]; char sex; int age; }stu[3]={{201401001,"wang ming",’M’,19},{201401002,"zhang ning",’w’,23},{201401003,"wang ming",’M’,19}}; void main() { struct student *p; printf("num\t\tname\t\tsex\tage\n"); for(p=stu;p<stu+3;p++) printf("%ld\t%-12s\t%-2c\t%4d\n",p->num,p->name,p->sex,p->age); }
课堂作业 1、定义一个结构体类型,用来表示日期(年、月、日),主函数输入两个日期,调用子函数比较两个日期当中哪个日期最早,且子函数返回较早的日期,在主函数输出结果。
8.4 Union共用体 什么是共用体? 让IT教学更简单,让IT学习更有效
8.4 union共用体 共用体又叫联合体,是一种特殊的数据类型,它允许多个成员使用同一块内存。灵活地使用共用体可以减少程序所使用的内存。
8.4 union共用体 8.4.1 共用体数据类型的定义 共用体类型变量的内存分配:共用体变量所占的内存长度等于最长的成员所占内存长度。 在C语言中,共用体类型同结构体类型一样,都属于构造类型,它在定义上与结构体类型十分相似,定义共用体类型的语法格式如下所示: union 共用体类型名称 { 数据类型 成员名1; 数据类型 成员名2; …… 数据类型 成员名n; }; 共用体类型变量的内存分配:共用体变量所占的内存长度等于最长的成员所占内存长度。
8.4 union共用体 8.4.2 共用体变量的定义 共用体变量的定义和结构体变量的定义类似,假如要定义两个data类型的共用体变量a和b,则可以采用下列三种方式。 1.先定义共用体类型,再定义共用体变量 2.在定义共用体类型的同时定义共用体变量 3.直接定义共用体类型变量
8.4 union共用体 8.4.3 共用体变量的初始化和引用 在共用体变量定义的同时,只能用其中一个成员的类型值进行初始化,共用体变量初始化的方式如下所示: union 共用体类型名 共用体变量 = { 其中一个成员的类型值 };
8.4 union共用体 8.4.3 共用体变量的初始化和引用 共用体变量的引用方式与结构体类似,但两者是有区别的,在程序执行的任何特定时刻,结构体变量中的所有成员是同时驻留在该结构体变量所占用的内存空间中,而共用体变量仅有一个成员驻留在共用体变量所占用的内存空间中。接下来通过一个案例来验证,如例9-11所示。
8.4 union共用体 【课堂举例】假定要编写一个程序,录入某个班级的学生和任课老师的信息,且按下列形式输出: 另外,每个人的完整信息可以用结构体类型表示: struct people { char name[10], tag[10];//tag表示身份信息 union type num_job; };
8.4 union共用体 #include<stdio.h> else #include<string.h> void main(){ union type { int num; char job[20]; }; struct people {char name[10],tag[10]; union type num_job;}; struct people pe[4]; int i; for(i=0;i<4;i++) {printf("请输入第%d个人的姓名:",i+1); scanf("%s",pe[i].name); printf("请输入第%d个人的身份(学生/老师):",i+1); scanf("%s",pe[i].tag); if(strcmp(pe[i].tag,"学生")==0) {printf("请输入学生的学号:"); scanf("%d",&pe[i].num_job.num); } else {printf("请输入教师的职务:"); scanf("%s",&pe[i].num_job.job);} } printf("姓名 身份 学号/职务\n"); for(i=0;i<4;i++) {printf("%-10s%-10s",pe[i].name,pe[i].tag); if(strcmp(pe[i].tag,"学生")==0) printf("%-10d\n",pe[i].num_job.num); printf("%-10s\n",pe[i].num_job.job);
typedef——给数据类型取别名 8.5 typedef-给数据类型取别名 在前面章节中,讲解了C语言提供的各种数据类型和用户自己声明的结构体、共用体、指针类型等。除了这些数据类型,C语言还允许用户使用typedef关键字为现有数据类型取别名。使用typedef关键字可以方便程序的移植,减少对硬件的依赖性。 1、为基本类型取别名 typedef int ZX; ZX i,j,k; 2、为数组类型取别名 typedef char NAME[10]; NAME class2; Char Class2[10];
使用typedef关键字为结构体类型student取别名。 3、为结构体取别名 使用typedef关键字为结构体类型student取别名。 Typedef struct student {int num; Char name[110]; Char sex;}STU; STU stu1;
课堂作业 题目:在职工信息管理系统中,用结构体实现职工信息的增加、浏览和修改。该项目采用模块化程序设计的方式,实现职工信息的增加、删除、浏览和修改等功能。由主函数main()、增加函数add()、查询函数search()和删除函数del()等功能模块所组成。
本章小结 本章小结 本章主要讲解了结构体和共用体两种构造类型,最后讲解用typedef定义数据类型。通过本章的学习,希望大家熟练掌握结构体和共用体的定义、初始化以及引用方式,为后期复杂数据的处理提供有力的支持。