C程序设计教程(第二版式)1-6.ppt_第1页
C程序设计教程(第二版式)1-6.ppt_第2页
C程序设计教程(第二版式)1-6.ppt_第3页
C程序设计教程(第二版式)1-6.ppt_第4页
C程序设计教程(第二版式)1-6.ppt_第5页
已阅读5页,还剩72页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第6章 结构体等构造数据类型,6.1 结构体 6.2 结构体与数组 6.3 结构体与指针 6.4 结构体与函数 6.5 联合体与枚举 6.6 类型定义 6.7 程序举例,6.1 结构体,6.1.1 问题的提出,可以用四个平行数组分别存储了上表中的每 一列元素,因为每一列数据是由一组类型相同的 数据构成的。 但是,这四个平行数组并不是没有关系的, 每个数组中下标相等的数据表示的是同一支股票 的信息,例如,四个数组中下标为0的元素代表 了股票代码为000096、昨天收盘价6.80、今天收 盘价7.20、涨幅5.88(%)这支股票的数据。 分割了数据之间有一定的逻辑关系。例如, 在主函数中调用读数据

2、的函数时,必须将四个数 组名同时作为参数,,结构体类型的数据由若干称为“成员”的数据组成,每一个成员既可以是一个基本数据类型的数据,也可以是另一个构造类型的数据。 结构体实际上是C编译没有提供的数据类型,可以由程序员根据实际情况来自己构造的一种新的数据类型。,6.1.2 结构体的说明 为了描述起来简单,我们要先定义一 个结构体类型:date 。date是日期,2004年 3月5日是一个日期数据,当然我们可 以用三个整型变量来表示一个日期, int year,month,day; 但是,不能表示三个变量之间的逻辑关 系。,我们把时间说明为DATE ,而DATE 含有小时、分、秒三个成分,则DAT

3、E的结 构体说明是: struct DATE int year; int month; int day; ;,其中struct 是关键字, DATE是结构体 的类型名,它实际上规定了一种新的复杂数 据类型。 于是在随后的程序中就可以使用DATE 定义结构体变量了。 struct DATE start_day ;,结构体的说明方式: struct 结构体名 成员表; ; 其中成员表可以由一个或几个成员组 成,要说明每个成员的类型和名称,注意 最后用分号结束。,结构体变量的定义方式: struct 结构体名 结构体变量表; 结构体说明要注意下面几点: (1)结构体说明并不引起存储分配,结构体 变量

4、的定义才引起存储分配。存储分配时, 通常按照各成员在结构体说明中出现的先 后顺序依次排列。结构体成员的数据类型 可以是C语言的基本数据类型,也可以 是数组和指针类型。,(2) 结构体成员还可以是另一个结构体类型,结构体说明可以嵌套。 struct OBJECT struct TASK long plan; long start; long finish; ti,tj; int count; ; OBJECT中嵌套定义了另外一个结构体 TASK。,(3) 当结构体成员是另一个结构体类型时,还可以采用嵌套的说明方式。 struct DATE int year; int month; int day

5、; struct TIME int hour; int minute; int second; time; ; DATE中嵌套定义了TIME类型。,(4) 结构体说明不允许递归,也就是不允 许在一个结构体说明中嵌套对自己的定义。 struct WRONG struct WRONG a; /*错误 */ int count; ;,6.1.3 结构体变量的定义 结构体变量定义有三种方法。 第一种方法就是上面用过的:先说明结构体,再定义结构体变量。 第二种方法是在说明结构体类型的同时定 义结构体变量。 例如: struct TIME int hour; int minute; int second;

6、 audit_begin,audit_end;,这种方法的语法格式是: struct 结构体名 成员表; 结构体变量表;,第三种方法是在说明结构体时直接定义 结构体变量,并且不用指定结构体名。 struct int hour; int minute; int second; audit_begin,audit_end; 这种形式的语法为: struct 成员表; 结构体变量表;,不能混淆结构体名和结构体变量这两 个概念。结构体名实际上标识了程序员定 义的一种新的数据类型,编译系统不可能 为结构体名分配内存空间。只有当变量被 说明为这种由程序员自己定义的数据类型 的结构体时,编译系统才会为结构体

7、变量 分配存储空间。在不引起混淆的情况下, 结构体变量可以简称为结构体。,6.1.4 结构体成员的引用 C语言中对结构体变量的使用是通过 对其成员的引用来实现的。一般不能对 结构体变量进行整体的引用。 引用的方法: 结构体变量名.成员名 符号“.”是依据结构体变量名存取结构体成员的运算符。,例6.1 用符号“.”引用结构体变量的成员。 #include stdio.h void main() struct DATE int year; int month; int day; ; struct DATE start_day; start_day.year=2004; /*为start_day的每

8、个成员赋值 */ start_day.month=3; start_day.day=5; printf(n Start date is:%02d/%02d/%02d, start_day.year,start_day.month, start_day.day); ,注意,对嵌套结构体的引用必须引用 到最末一级。 struct OBJECT struct TASK long plan; long start; long finish; ti,tj; int count; ob; 可以使用scanf(“%d”, 如果初始化数值的个数小于结构体成 员的个数,系统会自动将其它成员初始化 为0。,例6.

9、3 结构体变量的初始化。 #include stdio.h void main() struct DATE int year; int month; int day; ; struct DATE start_day=2004,3,5; /*初始化start_day */ printf(n Start date is:%02d/%02d/%02d, start_day.year,start_day.month, start_day.day); ,6.2.1结构体包含数组 由于结构体的成员可以是任何基 本数据类型和另外一个构造类型,所 以结构体的成员当然可以是数组。 下面我们说明一个可以描述一个股

10、票 信息的结构体:,6.2 结构体与数组,struct STOCK char stockname20; /*股票名称 */ char stockcode6; /*股票代码 */ float data3; /*昨天的收盘价、今天的收盘价、 涨幅 */ ;,例6.4 结构体中包含数组。 #include stdio.h void main() int i; struct STOCK char stockname16; /*股票名称 */ char stockcode7; /*股票代码 */ float data3; /*昨天的收盘价、今天的收盘价、涨幅*/ ;,struct STOCK gjny=

11、GuangJuNengYuan,000096,6.80,7.20; /*初始化结构体变量gjny*/ gjny.data2=( gjny.data1- gjny.data0)/ gjny.data0*100; /*计算涨幅*/ printf(n %s %s ,gjny.stockname,gjny.stockcode); /*输出股票名称和股票代码 */ for (i=0;i2;i+) /*输出昨天的收盘价、今天的收盘价*/ printf(%6.2f , gjny.datai); printf(%6.2f %, gjny.data2); /*输出涨幅*/ ,6.2.2 结构体数组 一个结构体变

12、量只能存放一个结 构体数据,假设有4个股票(或者更 多)的信息要描述,如何处理呢? 每一支股票用一个结构体变量来存储, 四个就要用四个结构体变量来存储,这四 个结构体变量的构成是完全一样的。 很容易想到用结构体数组: struct STOCK stock4;,定义结构体数组的语法: struct 结构体名 数组名长度; 访问结构体数组中的结构体成员 的方法是: 数组名下标.成员名,例6.5 输入四支股票的信息并输出。 #include stdio.h void main() int i,j; float temp1,temp2; struct STOCK char stockname16; /

13、*股票名称*/ char stockcode7; /*股票代码*/ float data3; /*昨天的收盘价、今天的收盘价、涨幅*/ ;,struct STOCK stock4; for (i=0;i4;i+) printf(Please enter stockname,stockcode and 2 price:n); /*输入提示*/ scanf(%s%s%f%f, stocki.stockname,stocki.stockcode, /*计算涨幅*/ ,for (i=0;i4;i+) printf(n %s %s , stocki.stockname, stocki .stockcod

14、e); /*显示股票名称和股票代码*/ for (j=0;j2;j+) /*输出昨天的收盘价、今天的收盘价*/ printf(%6.2f , stocki.dataj); printf(%6.2f%, stocki.data2); /*输出涨幅*/ ,6.3.1 指向结构体的指针 指针的用途是非常广泛的,指针变量可以指向基本数据类型的变量和数组,也同样可以指向结构体类型的存储单元。 定义指向结构体的指针变量的语法是: struct 结构体名 *结构体指针变量名;,6.3 结构体与指针,struct DATE int year; int month; int day; ; struct DATE

15、 begin,end,*b,*e; b和e被定义为指向DATE类型的指针变量。,通过语句b=就能使 b和e分别指向变量begin和 end。 注意,指向结构体的指针指向的是整 个结构体变量,不具体指向结构体的某个 成员。 可以通过指向结构体的指针存取结构 体的成员。,通过指针访问结构体成员的方法有两 种,一种是使用运算符“-”,另一种是使用 运算符“*”。 运算符“-”由“减号”和“大于号”构成。用 运算符“-”引用指针所指的结构体成员的 方法是: 结构体指针变量名-成员名 b- year 对应 begin. year , b- month 对应 begin. month b- day 对应

16、begin. day 。,使用“*”运算符也可以通过指向结构体变 量的指针访问结构体成员。用运算符“*”引 用指针所指的成员的方法是: (*结构体指针变量名).成员名 (*b).year 对应 begin. year , (*b). month 对应 begin. month , (*b). day 对应 begin. day 。,注意:必须用圆括号将*b括起来,因为 按照优先级和结合性, (*b.year)将解释为 *(b. year ),这是没有意义的。 两种方法中比较常用的是第一种,要注意 的是:“-”不是应用于结构体的,而是应 用于指向结构体的指针的。,例6.6 指向结构体变量的指针。

17、 #include stdio.h void main() struct DATE int year; int month; int day; *p; struct DATE start_day=2004,3,5; /*初始化start_day */ p= ,例6.7用国家代码、金牌数、银牌数、铜牌数和奖牌总数 表示各个国家获得奖牌的情况,编写程序将下表中的数 据作为初始化的数据,然后根据每个国家的获奖牌情况 计算各个国家的奖牌总数,同时计算这四个国家总共获 奖牌的数量,输出结果。,#include stdio.h #define SIZE 4 #define priline printf(n

18、-); void main() struct COUNTRY char name20; /*国家名称*/ int golden; /*金牌数*/ int silver; /*银牌数*/ int copper; /*铜牌数*/ int sum; /*奖牌总数*/ countrySIZE=PRC,32,17,14,USA,35,39,29,Russia, 27,27,38, Australia,17,16,16;,struct COUNTRY *ap; /*指向结构体的指针*/ int total=0; for (ap= country;apsum= ap-golden+ap-silver+ap-

19、copper; /*计算每个国家的奖牌总数 */ total=total+ ap-sum; /*计算每个国家的奖牌总数之和 */ printf(n Name Golden Silver Copper Sum); priline; for (ap= country;apname), (ap-golden),(ap- silver),(ap- copper),(ap- sum); priline; printf(n Total:%6d,total); ,6.3.2用结构体类型指针建立链表 结构体说明不能递归,也就是说结构体说明不能 包含自身的结构体作为成员。 例如: struct DATE int

20、 year; int month; int day; struct DATE begin; /*错误*/ ; 是非法的结构体说明,它试图在说明DATE 结构体的 同时将DATE 结构体类型作为自己的一个成员的类型。 但是,在C语言的结构体说明中,允许结构体成 员是指向它自身结构体的指针。,struct DATE int year; int month; int day; struct DATE *begin; /*正确*/ ; 是正确的的结构体说明,在说明DATE 结构体 时,可以将指向DATE 结构体类型的指针作为 自己的一个成员的类型。也就是说,begin是一 个指向DATE结构体变量的指

21、针。,例6.8 链接两个静态的结构体变量。 #include stdio.h #define priline printf(n-); void main() struct NATION char name20; /*国家名称*/ int golden; /*金牌数*/ struct NATION *next; /*指向一个象自己一样的结构体变量*/ *p,*q; static struct NATION nation_PRC=PRC,32; /*初始化数据中国金牌数32枚*/ static struct NATION nation_USA=USA,35; /*初始化数据美国金牌数35枚*/,p

22、= ,用指针将两个结构体变量链接起来以后,原来的结 构体变量的名字已经名存实亡了,通过指针就可以操作 到链接起来的结构体变量,并且两个结构体变量在内存 中的位置是无关紧要的。这就是所谓链表的基本概念了, 通过一个指向第一个结构体变量的指针可以访问到链表 中所有的结构体变量,注意,链表中的最后一个结构体 变量的next指针必须是空值。 在实际应用中,链表中的结点所占的空间是动态分 配的。,6.4.1 结构体数据作为函数的参数 结构体数据作为函数的参数分为两种情况: (1) 结构体变量的每个成员作为函数的实际参数 (2) 指向结构体的指针作为函数的实际参数 整个结构体变量一般不允许作为函数 的实际

23、参数(有些编译系统允许)。,6.4 结构体与函数,例6.9 修改例6.7将其模块化。 #include stdio.h #define SIZE 4 #define priline printf(n-); struct COUNTRY char name20; /*国家名称*/ int golden; /*金牌数*/ int silver; /*银牌数*/ int copper; /*铜牌数*/ int sum; /*奖牌总数*/ ; int count(struct COUNTRY *country,int size); void output(struct COUNTRY *country

24、,int size,int total);,void main() struct COUNTRY countrySIZE=PRC,32,17,14,USA,35,39,29, Russia,27,27,38,Australia,17,16,16; int total; total=count(country,SIZE); /*计算每个国家的奖牌总数和总奖牌数*/ output(country,SIZE,total); /*输出*/ ,int count(struct COUNTRY *country,int size) struct COUNTRY *ap; /*指向结构体的指针*/ int

25、total=0; for (ap= country;apsum= ap-golden+ap-silver+ap-copper; /*计算每个国家的奖牌总数 */ total=total+ ap-sum; /*计算每个国家的奖牌总数之和 */ return total; ,void output(struct COUNTRY *country,int size,int total) /*输出函数定义*/ struct COUNTRY *ap; /*指向结构体的指针*/ printf(n Name Golden Silver Copper Sum); priline; for (ap= count

26、ry;apname), (ap-golden), (ap- silver),(ap- copper),(ap- sum); priline; printf(n Total:%6d,total); ,6.4.2 返回指向结构体的指针的函数 函数能够返回指向结构体的指针。 若要函数返回指向结构体的指针,函 数定义的首部应定义为: struct 结构体名 *函数名(参数表),例6.10为例6.9增加一个查询函数,该查询函数的功能是在结构体数组中查询一个给定的国家名称,若该国家的数据存在,返回指向这个结构体的指针,否则返回空值。 struct COUNTRY *lookfor(struct COUNT

27、RY *country,int size,char *name) struct COUNTRY *ap; /*指向结构体的指针*/ for (ap= country;apname,name)=0) return ap; /*查询到,返回结构体变量的地址*/ return NULL; ,6.5 联合体与枚举 6.5.1 使用联合体与枚举的目的 联合体又称为公用体。使用联合体变量的 主要目的是节省空间。在编制一些比较高级的 程序时,有时需要把不同类型的变量放在同一 存储区域内。例如,我们要定义一个变量x,它 既可以用来存储一个单字符还可以存储一个浮点数或是一个整数,当然,在一个时间点,它 只能存放

28、其中的一种类型的数据,新的数据覆 盖老的数据,新的数据是什么数据类型,x变量 就是什么数据类型。,使用枚举变量的主要目的是提高程序的可 读性。所谓“枚举”就是把所有可能的取值情况 列举出来。例如,真和假表示了逻辑值的两种 情况,男和女是性别的两种取值,选修课成绩 有“优”、“良”、“中”、“及格”和“不及格”五种 取值等。,6.5.2 联合体与枚举的说明 联合体的说明格式为: union 联合体名 成员表; ; 例如, union mixed char c; float f; int i; ; mixed为联合体名,是新定义的一种数据类型。,枚举的说明除了关键字使用enum以外,还有 一点与说

29、明结构体不同,就是枚举说明中的每 个元素的前面不使用数据类型的说明。 枚举的说明格式为: enum 枚举名 枚举元素表(逗号分隔) ; 例如, enum COLOR red,green,blue,yellow,white ;,enum BOOL false,true ; COLOR和BOOL是枚举名,COLOR的枚 举元素red、green、blue、yellow、whitey 和BOOL 的枚举元素false、true前面都没 有数据类型的说明。原因是,枚举元素是 常量,有固定的数值,按说明枚举时的顺 序分别是整数0、1、2。,6.5.3 联合体变量与枚举变量的定义 联合体变量与枚举变量的定

30、义方法也 有三种。 (一) 先说明联合体或枚举 ,再定义联合体变量或 枚举 变量。 (二) 在说明联合体或枚举类型的同时定义联合体 或枚举变量。 (三) 直接定义联合体或枚举变量。 这三种方法与结构体变量的定义方法 几乎没有区别。,union mixed char c; float f; int i; ; union mixed x;,union char c; float f; int i; x;,union mixed char c; float f; int I x;,与结构体变量不同的是,联合体 变量在内存中所占的字节数是成员表 中最大的,而不象结构体变量是所有 成员所占字节数的总和。

31、 union mixed x=a; 这时,系统按成员c对第一个字 节赋值,其余单元的值为0。,枚举名和枚举变量也是两个概念。与 结构体变量和联合体变量都不同,枚举变 量在内存中只占一个整数的位置。枚举变 量的取值范围限定在枚举元素内,而枚举 元素是整数。,6.5.4联合体变量成员的引用 对于联合体变量成员的直接引 用是使用运算符“.”,语法是:联合 体变量名.成员名。 例如x.f,可以将x.f看成一个普通的浮点型数据进行存取。,注意: 不能对联合体变量x直接存取内 容。 x=15.00是错误的,只能对x的三 个成员进行操作,这三个成员是x.f、 x.i和x.c,并且这三个联合体成员不可 能同时

32、存在。,6.5.5 枚举变量的使用 枚举变量的使用与结构体变量和联合体完全 不同。 如果一个变量被定义为是一个枚举变量, 则它的取值只能取自对应的枚举元素,而不能是其它 任何数。 如果有定义 enum red,green,blue,yellow,white select,change; 则select=red;和change=white; 是正确的 而select=red_white是错误的。,下面的程序段就是一个很好的利用枚举类型增强程序可读性的片段。 enum BOOL false,true flag; if (flag=false) ,当然,如果一定想知道枚举变量的值,可以 按照整型数打

33、印枚举元素和枚举变量的值。但 是不能直接输出表示枚举元素的字符串标识符, 可以考虑使用switch或else if语句输出。 例如, enum BOOL false,true flag; flag=false; if (flag=false) printf(false); else printf(ture);,6. 5.6指向联合体变量的指针 通过指向联合体变量的指针也 可以对联合体变量进行存取,使用 指向联合体变量的指针存取联合体 变量成员的语法格式是: (*指向联合体变量的指针).成员名 指向联合体变量的指针-成员名,例6.11 使用指针引用联合体的成员。 #include stdio.h union NATION int golden; /*金牌数*/ char *name; /*国家名称*/ ; void main() union NATION china,*p= /*通过指针引用联合体变量的成员 */ ,6.5.7 联合体变量与函数 联合体变量的成员值可以作为函 数的参数,联合体变量不能作为函数 的参数,并且函数的返回类型也不能 是联合体;但是,指向联合体变量的 指针可以作为函数的参数,返回值也 可以是

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论