《C语言程序设计第8章结构体和共用体.ppt》由会员分享,可在线阅读,更多相关《C语言程序设计第8章结构体和共用体.ppt(49页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第第8 8章章 结构体和共用体结构体和共用体学习目标1.掌握结构体类型、结构体变量、结构体数组的定义2.掌握结构体变量指针、结构体数组元素指针等基本概念3.掌握结构体指针的声明、初始化、赋值及引用4.了解共用体类型的定义、共用体变量的声明、赋值及使用5.了解枚举类型的定义、枚举类型变量的声明、赋值及使用6.理解typedef的功能8.1 结构体结构体 数组中各元素是属于同一个类型。若要将不同类型的数据组合成一个有机的整体,例如:姓名、年龄、性别、成绩组合为一个组合项,C用结构体来建立这种数据结构。8.1.1 结构体类型结构体类型 一个结构体类型可以由若干个被称为成员(或域)的成分组成。每个成员
2、具有自身的名字和数据类型,同一结构中的成员名不能相同。例如一个学生的信息,它包括以下5项:(1)学号:用5位数字表示,长整型;(2)姓名:用汉语拼音表示,最多20个字符;(3)性别:用M或F表示,分别表示男或女;(4)生日:如19881015,表示年月日;(5)地址:用字符数组表示,最多30个字符。8.1.2 结构体类型的声明结构体类型的声明一个结构体类型的一般形式为:struct 结构体名 类型名1 成员名1;类型名2 成员名2;类型名n 成员名n;例如:struct stu long int num;/*学号*/char name20;/*姓名*/char sex;/*性别*/unsign
3、ed long birthday;/*生日*/char addr30;/*地址*/;说明:(1)结构体声明描述了结构体的组织形式,但在编译时并不为它分配存储空间。(2)结构体的成员可以是简单变量、数组、指针、结构体或共用体等。(3)结构体不可嵌套定义,但可以嵌套使用,例如:struct date int day;char month4;int year;struct student long int num;char name20;char sex;struct date birthday;/*结构体成员是另一种结构类型,结构体在此嵌套*/char*addr;numnamesexbirthda
4、yaddrdaymonthyear嵌套结构体嵌套结构体studentstudent的逻辑结构的逻辑结构 (4)结构体声明可以在函数内部,也可以在函数外部。(5)定义结构体类型时,注意不能遗漏最后的分号。8.1.3 结构体变量结构体变量一、结构体变量的定义一、结构体变量的定义可以采取以下三种方法定义结构体类型变量。1在声明结构体类型的同时定义变量。例如:struct student long int num;char name20;char sex;int age;float score;s1,s2,s3;声明结构体类型的同时定义结构体变量的一般形式为:struct 结构体名 类型名1 成员名1
5、;类型名2 成员名2;类型名n 成员名n;变量名,变量名,变量名m;特点:定义一次结构体变量之后,在该定义之后的任何位置仍可用该结构体类型来定义其它结构体变量。2直接定义结构类型变量例如:struct long int num;char name20;char sex;int age;float score;stu1,stu2,stu3;直接定义结构体变量的一般形式为:struct 类型名1 成员名1;类型名2 成员名2;类型名n 成员名n;变量名,变量名,变量名m;特点:由于在struct后不出现结构体名,故不便于在源程序的其他地方定义该类型的新变量。3先声明结构体类型再定义变量名例如:st
6、ruct student long int num;char name20;char sex;int age;float score;struct student stu1,stu2,stu3;一般形式为:struct 结构体名 类型名1 成员名1;类型名2 成员名2;类型名n 成员名n;struct 结构体名 变量名,变量名,变量名m;特点:在该定义之后的任何位置,不仅可用该结构体类型来定义其他结构体变量,而且可把其结构体声明部分作为文件存放起来,这样就可借助于include命令把它复制到任何源文件中,用以定义同类型的其它结构体变量。注意:(1)定义一定要在结构体声明之后或与结构体声明同时进
7、行,对尚未声明的结构体类型,不能用它来定义结构体变量。(2)存储空间分配是按照其对应的各成员项的定义顺序进行的。(3)同一结构类型的每个结构体变量,存储空间的大小都相同,是各成员项所占空间之和。例如:sizeof(stu1)的值为31;sizeof(struct student)的值为31;sizeof(float)的值为4。(4)结构体变量中的成员可以单独使用,地位与一般变量相同。(5)结构体变量一般不用register型。二、结构体变量的初始化二、结构体变量的初始化struct student long int num;char name20;char sex;char addr20;st
8、u1,stu2=89031,Lilin,M,123 Beijing Road;/*结构体变量stu2初始化*/三、结构体变量的引用三、结构体变量的引用形式:结构体变量名成员名#includevoid main()struct student long int num;char name20;char sex;char addr20;stu1,stu2=89031,Lilin,M,123 Beijing Road;/*结构体变量stu2初始化*/printf(NO.:%ldnname:%snsex:%cnaddress:%sn,stu2.num,stu2.name,stu2.sex,stu2.a
9、ddr);stu1=stu2;/*两个相同类型的结构体变量之间可以进行赋值操作*/printf(NO.:%ldnname:%snsex:%cnaddress:%sn,stu1.num,stu1.name,stu1.sex,stu1.addr);注意:(1)不能将一个结构体变量作为一个整体进行输入和输出。例:scanf(%ld%s%c%s,&stu1);printf(NO.:%ldnname:%snsex:%cnaddress:%sn,stu2);只能对结构体变量中的各个成员分别进行输入和输出,如:stu1.num=89031;strcpy(stu1.name,Liling);scanf(%c%
10、s,&stu1.sex,stu1.addr);(2)对结构体中的成员,可以单独使用,它的作用与地位相当于普通变量。stu1.num=stu2.num;(3)结构体变量可以进行整体赋值,但不能整体进行比较。下列语句是错误的:if(stu1stu2)printf(name:%sn,stu1.name);(4)如果成员本身又属一个结构体类型,则要逐级地找到最低的一级成员。只能对最低级的成员进行存取。8.2 结构体数组结构体数组8.2.1 结构体数组的定义结构体数组的定义1定义结构体类型后定义结构数组。例如:struct student long int num;char name20;char se
11、x;int age;float score;struct student stu5;2直接定义一个结构数组。例如:struct student long int num;char name20;char sex;int age;float score;stu5;或 struct long int num;char name20;char sex;int age;float score;stu5;numnamesexagescorestu0stu1stu2stu3stu4结构体数组的逻辑结构结构体数组的逻辑结构 8.2.2 结构数组的初始化结构数组的初始化 格式:struct 结构体名 结构数组
12、名元素个数=初始数据;struct student stu3=80101,Lilin,M,18,80102,Wanglan,F,19,80103,Zhangjun,F,20;struct student stu=80101,Lilin,M,18,80102,Wanglan,F,19,80103,Zhangjun,F,20;struct student long int num;char name20;char sex;int age;stu=80101,Lilin,M,18,80102,Wanglan,F,19,80103,Zhangjun,F,20;2052203120512027结构数组结
13、构数组stu在内存中的分配情况在内存中的分配情况stu0 stu1 stu2200020272054 num name sexage8.2.3 结构数组元素的引用结构数组元素的引用形式:结构体数组名下标成员名例如stu0.num=80101;strcpy(stu0.name,Lilin);例:统计全班男女生人数及1990年以后(含1990年)出生的人数。#include string.h#include stdio.hvoid main()struct stud /*定义一个结构stud,包含3个成员*/char name20;/*姓名*/char sex;/*性别*/int year;/*出
14、身年份*/;struct stud class100;/*定义一个结构数组class*/int m_num=0,f_num=0,total90=0,class_num,i;printf(Please enter class_num:);scanf(%d,&class_num);/*输入班级人数*/for(i=0;iclass_num;i+)/*输入同学信息*/printf(nPlease enter name/sex/year:);scanf(%s%c%d,classi.name,&classi.sex,&classi.year);for(i=0;iclass_num;i+)/*输出班级同学信
15、息*/printf(n%-10s%c%6d,classi.name,classi.sex,classi.year);for(i=0;i=1990)total90+;/*统计90以后出生的人数*/printf(n number of boy:%d,m_num);printf(n number of girl:%d,f_num);printf(n number after of 1990:%d,total90);测试数据与运行结果:输入:Please enter class_num:3Please enter name/sex/year:Zhanglin m 1988Please enter na
16、me/sex/year:Wangpin f 1990Please enter name/sex/year:Liutao M 1989输出:Zhanglin m 1988Wangpin f 1990Liutao M 1989number of boy:2number of girl:1number after of 1990:18.3 结构指针结构指针指向结构体变量的指针指向结构体变量的指针形式:struct 结构体名*结构指针名;例:static struct student*p;结构指针在定义时也可以初始化。例:struct student long int num;char name20;
17、char sex;int age;float score;stu1,*p=&stu1;用指针引用结构体成员的一般形式:(*结构指针名).成员名或结构指针名-成员名设有类型、变量声明及初始化如下:struct date int day;char month4;int year;birthday,*sp=&birthday;则(*sp).day、(*sp).month、sp-day、sp-month均是合法。其中 (*sp).day和sp-day等效 (*sp).month和sp-month等效。例:#includestdio.h#includestring.hvoid main()struct
18、stud char*num;char name20;float score;struct stud stu1,*sp;sp=&stu1;sp-num=04780601;strcpy(*sp).name,Liling);stu1.score=90.0;printf(nstudent No.:%snname:%snscore:%.1f,sp-num,sp-name,sp-score);printf(nstudent No.:%stname:%stscore:%.1f,(*sp).num,(*sp).name,(*sp).score);printf(nstudent No.:%stname:%sts
19、core:%.1f,stu1.num,stu1.name,stu1.score);04780601Liling90.0sp指向结构体变量的指针指向结构体变量的指针注意:(1)*sp两侧的括号不可省,因为成员运算符“.”优先于“*”运算符,*sp.num就等价于*(sp.num)了。(2)由于运算符“-”、“.”、“()”和“”的优先级最高,其结合性相同。例如:+sp-num等价于:+(sp-num)即成员值加1。(+sp)-num:先执行sp=sp+1,再执行sp-num(注意sp的值已经改变)。sp+-num或(sp+)-num:先存取sp-num,再执行 sp=sp+1。sp-num+:先
20、存取sp-num,再使成员值加1。8.3.2 指向结构数组的指针指向结构数组的指针#includestruct student long int num;char name20;char sex;int age;stu3=80101,Lilin,M,18,80102,Yanglan,F,19,80103,Zhangjun,F,20;void main()struct student*p;/*p是指向struct student型数据的指针变量*/printf(nNo.tNamettsextagen);for(p=stu;pnum,p-name,p-sex,p-age);运行结果:No Name
21、 sex age 80101 Lilin M 18 80102 Yanglan 19 80103 Zhangjun 20pppstu2stu1stu0指向结构数组的指针及其移动示意指向结构数组的指针及其移动示意8.3.3 结构体变量做函数参数结构体变量做函数参数1用结构体变量的成员作参数。例如,用stu1.num或stu2.name作函数实参,将实参值传给形参,“值传递”方式。2用结构体变量作实参。采用“值传递”方式,将结构体变量所占的内存单元的内容全部顺序传递给形参。例:有一个结构体变量stu1,内含学生学号、姓名、数学和英语两门课的成绩。要求在main函数中赋值,在函数print中将它们打
22、印输出。#include#includestruct student long int num;char name20;float math;float eng;void main()void print(struct student);struct student stu1;stu1.num=80601;strcpy(stu1.name,Liling);stu1.math=80.5;stu1.eng=90;print(stu1);void print(struct student stu)printf(%ldn%sn%.1fn%.1fn,stu.num,stu.name,stu.math,s
23、tu.eng);3.结构变量(或数组)的地址作为实参传递给形参例:将上例改用指向结构体变量的指针作实参。#include#include#define FORMAT%ldn%sn%.1fn%.1fnstruct student long int num;char name20;float math;float eng;void main()struct student stu1=80601,Liling,80.5,90,*sp=&stu1;void print(struct student*);/*形参类型修改成指向结构体的指针变量*/print(sp);/*也可表示为 print(&stu1
24、);实质都一样即实参为stu1的起始地址*/void print(struct student*p)/*形参类型修改了*/printf(FORMAT,p-num,p-name,p-math,p-eng);/*用指针变量调用各成员之值*/printf(n);stu1num name math engspp结构体指针作函数参数结构体指针作函数参数8.4 结构数组应用举例结构数组应用举例例:候选人得票的统计。设有3个候选人,要选择其中的一人当班长。从键盘上输入得票的候选人的名字,输出最终的得票结果。#includestdio.h#includestring.hstruct personchar na
25、me10;int count;leader3=Chen,0,Yang,0,Zhou,0;void main()int i,j;char name20;/*存放被选中候选人的姓名*/for(i=1;i=10;i+)scanf(%s,name);for(j=0;j3;j+)if(strcmp(name,leaderj.name)=0)leaderj.count+;printf(n);for(i=0;i成员名#includestdio.hunion mydata int i;char ch;float f;data1,*p=&data1;main()data1.i=20;printf(%d,%d,%
26、dn,data1.i,p-i,(*p).i);data1.ch=M;printf(%c,%c,%cn,data1.ch,p-ch,(*p).ch);data1.f=80.5;printf(%f,%f,%fn,data1.f,p-f,(*p).f);8.5.2 使用共用体变量应注意的使用共用体变量应注意的问题问题(1)参与运算或操作的是共用体变量的某个成员,不能是共用体变量整体例如:printf(%d,data1);是错误的。应写成“printf(”%d“,data1.i);”或 “printf(%c,data1.ch);”等。(2)同一个内存段可以用来存放几种不同类型的成员,但在每一瞬时只能存
27、放其中一种,而不是同时存放几种。例如:data1.i=20;data1.ch=M;data1.f=80.5;在完成以上3个赋值运算以后,只有data1.f是有效的(3)共用体变量的地址和它的各成员的地址都是同一地址(4)不能在定义共用体变量时对它初始化,也不能对共用体变量名赋值。例如,下面这些都是不对的:union int i;char ch;float f;a=2,m,6.5;/*不能初始化*/a=2;/*不能对共用体变量赋值*/(5)不能把共用体变量作为函数参数,也不能使函数带回共用体变量,但可以使用指向共用体变量的指针(与结构体变量这种用法相仿)。8.6 枚举枚举8.6.1 枚举类型的概
28、念及其定义枚举类型的概念及其定义 枚举类型的概念 列举出所有可能的取值的一种数据结构。枚举类型的定义 l enum枚举名枚举元素1,枚举元素2,枚举元素n;如:enum weekdaysun,mon,tue,wed,thu,fri,sat;enum weekday weekend,workday;或:enum weekdaysun,mon,tue,wed,thu,fri,satworkday;或:enum sun,mon,tue,wed,thu,fri,satworkday;枚举类型变量的赋值和使用(1)枚举值是常量,不是变量;sun=5;mon=2;sun=mon;均是错误的。(2)枚举类型
29、是有序数据类型;如:weekday中,sun为0,mon为1,sat为6。再如:main()enum weekday sun,mon,tue,wed,thu,fri,sata,b,c;a=sun;b=mon;c=tue;printf(“%d,%d,%d”,a,b,c);运行结果为:0,1,2(3)可改变枚举元素的值;enum weekdaysun=7,mon=1,tue,wed,thu,fri,satworkday;则 tue=2,wed=3,.Sat=6。(4)枚举元素可比较;如默认时:monsun(5)只能将枚举值赋予枚举变量,不能把元素的数值赋予枚举变量 如:a=sun;b=mon;是正
30、确的;而 a=0;b=1;是错误的。但 a=(enum weekday)2 或 b=(enum weekday)(5-3)是正确的。(6)枚举元素不是字符串常量,使用时不要加单引号或双引号。(7)由于C编译程序将枚举量作为整型数来处理,所以在程序中任何可使用常数的地方,都可以使用枚举常量符号名。如:enum colorred,green,yellow col;switch(col)case red:printf(“redn”);break;case green:printf(“greenn”),break;case yellow:printf(“yellown”),break;default:
31、printf(“undefinedn”);break;(8)同一作用域内,枚举常量与变量必须互不相同。8.7 用用typedef为类型定义别名为类型定义别名 typedef可完成为类型取别名 typedef的一般形式 typedef 类型名 新类型名;如:typedef float real;real a,f;再如:typedef char *pointer;pointer p,string=“This is a example.”;甚至还可用typedef为更为复杂的结构类型、联合类型、枚举类型规定一个别名等。如:typedef struct tnode char*word;int count;struct tnode*left;struct tnode*right;treenode;treenode p;相当于:struct tnode p;