《程序设计课件-结构体与共用体.ppt》由会员分享,可在线阅读,更多相关《程序设计课件-结构体与共用体.ppt(63页珍藏版)》请在三一办公上搜索。
1、结构体与共用体,用户定义类型结构体,突破C 语言提供的基本类型(如整形、实形、字符形),用户可以自己定义数据类型,结构数据类型的特点,特点:从不同的侧面描述某个数据对象,不同侧面所需的数据类型可能是不相同的。如:关于学生student的记录,它是从不同侧面来描述学生的,有:学号(整形)名字(字符串形)性别(字符形)年龄(整形)成绩(浮点形)地址(字符串形),num name sex age score addr,结构类型的定义与变量的声明,类型定义格式(注意最后的分号):struct 结构名 成员列表;,struct student int num;char name20;char sex;f
2、loat score;,注意:成员列表内的元素可以是基本类型,也可以是结构类型;甚至其它构造类型.,先定义结构类型名,再声明变量名;,结构变量的声明,struct student boy1,boy2;,结构类型名,结构体变量名,boy1boy2,结构变量的声明,定义结构名的同时,声明变量;,struct student int num;char name20;char sex;float score;boy1,boy2;,一般形式为:,struct 结构名 成员表列变量名表列;,成员也可以是结构体变量,struct date int month;int day;int year;struct
3、int num;char name20;char sex;struct date birthday;float score;boy1,boy2;,结构变量的引用,格式:格式变量名.成员名如果成员本身又是一个结构,则通过多个“.”找最低成员。对结构的成员引用,可以像对一般的成员引用。,boy1.num 即第一个人的学号boy2.sex 即第二个人的性别boy1.birthday.month 第一个人的出生月,main()struct stu/*定义结构*/int num;char name20;char sex;float score;boy2,boy1=102,Zhang ping,M,78.
4、5;boy2=boy1;printf(Number=%dnName=%sn,boy2.num,boy2.name);printf(Sex=%cnScore=%fn,boy2.sex,boy2.score);,结构变量的初始化,main()struct stu int num;char name20;char sex;float score;boy1,boy2;boy1.num=102;strcpy(boy1.name,Zhang ping);printf(input sex and scoren);scanf(%c%f,结构变量的赋值,结构变量的赋值就是给各成员赋值。可用输入语句或赋值语句来完
5、成。,结构数组,数组的元素也可以是结构类型的。可以构成结构型数组。结构数组的每一个元素都是具有相同结构类型的下标结构变量。在实际应用中,经常用结构数组来表示具有相同数据结构的一个群体。如一个班的学生档案,一个车间职工的工资表等。,struct stu int num;char*name;char sex;float score;boy5;定义了一个结构数组boy,共有5个元素,boy0boy4。每个数组元素都具有struct stu的结构形式。,结构数组,struct stu int num;char*name;char sex;float score;boy5=101,Li ping,M,4
6、5,102,Zhang ping,M,62.5,103,He fang,F,92.5,104,Cheng ling,F,87,105,Wang ming,M,58,;,main()int i,c=0;float ave,s=0;for(i=0;i5;i+)s+=boyi.score;if(boyi.score60)c+=1;printf(s=%fn,s);ave=s/5;printf(average=%fncount=%dn,ave,c);,【例】计算学生的平均成绩和不及格的人数,指向结构变量的指针,一般形式为:struct 结构名*结构指针变量名,如:struct stu*pstu;,赋值是
7、把结构变量的首地址赋予该指针变量,不能把结构名赋予该指针变量。如果boy是被说明为stu类型的结构变量,则:pstu=&boy;,结构指针变量能更方便地访问结构变量的各个成员,使用结构变量指针访问结构变量成员,一般形式为:(*结构指针变量).成员名或为:结构指针变量-成员名例如:(*pstu).num或者:pstu-num,main()pstu=,struct stu int num;char*name;char sex;float score;boy1=102,Zhang ping,M,78.5,*pstu;,pstu,指向结构数组的指针,指针变量指向一个结构数组,结构指针变量的值是整个结构
8、数组的首地址。设ps为指向结构数组的指针变量,则ps也指向该结构数组的0号元素,ps+1指向1号元素,ps+i则指向i号元素。,【例】用指针变量输出结构数组,struct stu int num;char*name;char sex;float score;boy5=101,Zhou ping,M,45,102,Zhang ping,M,62.5,103,Liou fang,F,92.5,104,Cheng ling,F,87,105,Wang ming,M,58,;,main()struct stu*ps;printf(NotNametttSextScoretn);for(ps=boy;ps
9、num,ps-name,ps-sex,ps-score);,跳过动态内存分配,动态存储分配,语言提供了一些内存管理函数,这些内存管理函数可以按需要动态地分配内存空间,也可把不再使用的空间回收待用,为有效地利用内存资源提供了手段。,调用形式:(类型说明符*)malloc(size)功能:在内存的动态存储区中分配一块长度为size字节的连续区域。函数返回值为该区域的首地址。“类型说明符”表示把该区域用于何种数据类型。(类型说明符*)表示把返回值强制转换为该类型指针。“size”是一个无符号数。例如:pc=(struct stu*)malloc(sizeof(struct stu);强制转换为字符数
10、组类型,函数的返回值为指向该字符数组的指针,把该指针赋予指针变量pc。,分配内存空间函数malloc,调用形式:(类型说明符*)calloc(n,size)功能:在内存动态存储区中分配n块长度为“size”字节的连续区域。函数的返回值为该区域的首地址。例如:ps=(struet stu*)calloc(2,sizeof(struct stu);按stu的长度分配2块连续区域,强制转换为stu类型,并把其首地址赋予指针变量ps。,分配内存空间函数 calloc,调用形式:free(void*ptr);功能:释放ptr所指向的一块内存空间,ptr是一个任意类型的指针变量,它指向被释放区域的首地址。
11、被释放区应是由malloc或calloc函数所分配的区域。,释放内存空间函数free,main()struct stu int num;char*name;char sex;float score;*ps;ps=(struct stu*)malloc(sizeof(struct stu);ps-num=102;ps-name=Zhang ping;ps-sex=M;ps-score=62.5;printf(Number=%dnName=%sn,ps-num,ps-name);printf(Sex=%cnScore=%fn,ps-sex,ps-score);free(ps);,【例】分配一块区域
12、,输入一个学生数据,链表,链表是一种常见的重要的数据结构它是动态地进行存储分配的一种结构链表必须利用指针变量才能实现,一个存放学生学号和成绩的结点应为以下结构:struct student int num;float score;struct student*next;前两个成员项组成数据域,后一个成员项next构成指针域,它是一个指向stu类型结构的指针变量。,链表,a结点,b结点,c结点,a.next=,b.next=,num,score,next,声明如下结构体变量:struct student a,b,c,链表,链表的操作,建立链表 遍历链表 删除结点 插入结点,建立如下图的简单静态链
13、表,链表的操作 建立静态链表,a结点,b结点,c结点,num,score,next,head=,a.next=,b.next=,c.next=NULL;,#include struct student int num;float score;struct student*next;Void main()struct student a,b,c;struct student*head,*p;a.num=10101;a.score=89.5;b.num=10103;b.score=90;c.num=10107;c.score=85;,head=,链表的操作 创建动态链表,在程序执行过程中从无到有地
14、建立起一个链表,即一个一个地开辟结点和输入各结点数据,并建立起前后相链的关系。,动态链表,例:写一函数建立一个有3名学生数据的单向动态链表(当输入的学号为0时结束创建),创建单向动态链表算法,#include#include#define LEN sizeof(struct student)struct student long num;float score;struct student*next;int n;,void main()struct student*pt;pt=creat();printf(“nnum:%ldnscore:%5.1fn”,pt-num,pt-score);,st
15、ruct student*creat(void)struct student*head,*p1,*p2;n=0;p1=p2=(struct student*)malloc(LEN);scanf(“%ld,%f”,链表的操作 创建动态链表,链表的操作 创建动态链表,链表的操作-遍历链表,/输出链表函数printvoid print(struct student*p)printf(nThese%d records are:n,n);if(p!=NULL)do printf(%ld%5.1fn,p-num,p-score);p=p-next;while(p!=NULL);,链表的操作删除结点,链表的
16、操作删除结点,欲删除的结点不存在。被删除结点是第一个结点。这种情况只需使head指向第二个结点即可。被删结点不是第一个结点,这种情况使被删结点的前一结点指向被删结点的后一结点即可。,考虑,链表的操作插入结点,链表的操作插入结点,原表是空表,只需使head指向被插结点即可。插入在第一结点之前。这种情况下使head指向被插结点,被插结点的指针域指向原来的第一结点则可。在其它位置插入。这种情况下,使插入位置的前一结点的指针域指向被插结点,使被插结点的指针域指向插入位置的后一结点。在表末插入。这种情况下使原表末结点指针域指向被插结点,被插结点指针域置为NULL。,考虑,共用体类型,用同一段内存单元存放
17、不同类型的变量。使几个不同的变量共享同一段内存的结 构,称为“共用体”类型的结构。,共用体类型,定义共用体类型变量的一般形式union共用体名 成员表列变量表列;,union Data int i;char ch;float f;union Data a,b,c;,union Data int i;char ch;float f;a,b,c;,“共用体”与“结构体”的定义形式相似,含义不同。结构体变量所占内存长度是各成员占的内存长度之和,每个成员分别占有其自己的内存单元。共用体变量所占的内存长度等于最长的成员的长度。,共用体类型,共用体类型,引用共用体变量的方式,不能引用共用体变量只能引用共用
18、体变量中的成员,如左侧的定义,则a.i a.ch a.f,union Data int i;char ch;float f;a,b,c;,共用体类型数据的特点,共用体类型,同一个内存段可以用来存放几种不同类型的成员,但在每一瞬时只能存放其中一个成员,而不是同时存放几个。可以对共用体变量初始化,但初始化表中只能有一个常量。共用体变量中起作用的成员是最后一次被赋值的成员共用体变量的地址和它的各成员的地址都是同一地址。不能对共用体变量名赋值,也不能企图引用变量名来得到一个值。,例 有若干个人员的数据,其中有学生和教师。学生数据:姓名、号码、性别、职业、班级。教师数据:姓名、号码、性别、职业、职务。要
19、求用同一个表格来处理。,共用体类型,共用体类型,struct int num;char name10;char sex;char job;union int clas;char position10;category;person2;,union Categ int clas;char position10;struct int num;char name10;char sex;char job;union Categ category person2;,枚举类型,如果一个变量只有几种可能的值,则可以定义为枚举类型所谓“枚举”就是指把可能的值一一列举出来,变量的值只限于列举出来的值的范围,声明
20、枚举类型,/声明一个枚举类型enum Weekdayenum Weekday sun,mon,tue,wed,thu,fri,sat;/用此类型定义变量 enum Weekday workday,weekend;,枚举元素按常量处理,称枚举常量。不是变量,不能赋值。例如:sun=0;mon=1;错误 每一枚举元素都代表一个整数,按定义时的顺序默认值为0,1,2,3,4,5 sun的值为0,mon的值为1,sat的值为6 如果有赋值语句:workday=mon;相当于:workday=1;可人为指定枚举元素的数值 enum Weekdaysun=7,mon=1,tue,wed,thu,fri,s
21、atworkday,week_end;,枚举类型,枚举类型,枚举元素可以用来作判断比较 if(workday=mon)if(workdaysun)枚举元素的比较规则是按其在初始化时指定的整数来进行比较的。如果定义时未人为指定,则按上面的默认规则处理,即第一个枚举元素的值为,故 monsun,satfri,例 口袋中有红、黄、蓝、白、黑5种颜色的球若干个。每次从口袋中先后取出3个球,问得到3种不同颜色的球的可能取法,输出每种排列的情况。,枚举类型,输出n种取法 分解,用typedef声明新类型名,typedef 是一种在计算机编程语言中用来声明自定义数据类型,配合各种原有数据类型来达到简化编程的
22、目的的类型定义关键字。typedef 并不创建新的类型,仅仅为现有类型添加一个同义字。,声明一个新的类型名的方法 先按定义变量的方法写出定义体(int i;)将变量名换成新类型名(将i换成COUNT)在最前面加typedef(typedef int COUNT)用新类型名定义变量,用typedef声明新类型名,用typedef声明新类型名,声明数组类型:先按定义数组变量形式书写:int a100;将变量名a换成自己命名的类型名:int NUM 100;在前面加上typedef,得到 typedef int NUM 100;用来定义变量:NUM a;相当于定义了:int a100;,声明字符指针
23、类型 char*p;char*STRING;typedef char*STRING;STRING p;,用typedef声明新类型名,用typedef声明新类型名,typedef struct int month;int day;int year;DATE;DATE birthday;DATE*p;,声明结构体类型名:,struct date int month;int day;int year;struct date birthday;,用typedef声明新类型名,说明:(1)以上的方法实际上是为特定的类型指定了一个同义字(synonyms)。例如typedef int NUM100;NU
24、M a;NUM是int 100的同义词typedef int(*POINTER)();POINTER p1;POINTER是int(*)()的同义词,说明:(2)用typedef只是对已经存在的类型指定一个新的类型名,而没有创造新的类型。(3)用typedef声明数组类型、指针类型,结构体类型、共用体类型、枚举类型等,使得编程更加方便。(4)typedef与#define表面上有相似之处,用typedef声明新类型名,说明:(5)当不同源文件中用到同一类型数据时,常用typedef声明一些数据类型。把所有的typedef名称声明单独放在一个头文件中,在需要的文件中用#include指令把它们包含到文件中。这样编程者就不需要在各文件中自己定义typefef名称了。(6)使用typedef名称有利于程序的通用与移植,用typedef声明新类型名,