《C语言程序设计及应用》课件第9章结构体_第1页
《C语言程序设计及应用》课件第9章结构体_第2页
《C语言程序设计及应用》课件第9章结构体_第3页
《C语言程序设计及应用》课件第9章结构体_第4页
《C语言程序设计及应用》课件第9章结构体_第5页
已阅读5页,还剩54页未读 继续免费阅读

下载本文档

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

文档简介

第9章结构体、共用体和枚举类型9.1结构体类型与结构体变量9.2结构体数组9.3向函数传递结构体数据9.4结构指针变量的说明和使用9.5链表9.6共用体9.7枚举类型9.8用户自定义类型9.9应用举例9.1结构体类型与结构体变量9.1.1结构体类型的定义9.1.2结构体变量的定义9.1.3结构体变量的初始化9.1.1结构体类型的定义“结构”相当于其他高级语言中的记录。“结构”是一种构造类型,它是由若干“成员”组成的。每个成员可以是一个基本数据类型或者又是一个构造类型。使用之前必须先定义它。定义一个结构的一般形式为:

struct结构名{成员列表};成员列表由若干个成员组成。对每个成员也必须作类型说明,其形式为:

类型说明符

成员名;成员名的命名应符合标识符的书写规定。9.1.1结构体类型的定义例如:structstu{intnum;charname[20];charsex;floatscore;};9.1.2结构体变量的定义说明结构体变量有以下三种方法:(1)先定义结构,再说明结构变量。(2)在定义结构类型的同时说明结构变量。(3)直接说明结构变量。如果用前面定义的stu结构为例,三种方法中说明的结构变量都具有下图所示的结构。9.1.2结构体变量的定义成员也可以又是一个结构,即构成了嵌套的结构。如下图所示为具有嵌套的结构。9.1.3结构体变量的初始化结构体类型的变量存储类型可分为自动的、静态的和外部的,按照ANSIC标准的规定,各种存储类型的结构体类型的变量都可以初始化。 形式如下:

struct

结构体名 {

数据类型

成员名1; ......

数据类型

成员名n; }变量名

{初始化数据}如果结构体类型已定义,也可用以下方式初始化:

struct结构体名

变量名

{初始化数据}9.2结构体数组9.2.1结构体数组的定义9.2.2结构体数组的初始化9.2.1结构体数组的定义一个结构体里可以存放一组数据(如一个学生的学号、姓名、年龄等)。如果有10个学生的数据需要参加运算,显然需要用到数组,这就是结构体数组。结构体数组与以前介绍过的数执行数组的不同之处在于结构体数组中每个数组元素都是一个结构体类型的数据,它们都分别包括各个成员量。9.2.2结构体数组的初始化结构体数组可以初始化,但是只能对全局或静态存储类别的数组初始化。定义结构体数组时,元素个数可以不指定,编译时,系统会根据给出初值的结构体常量的个数来确定数组元素的个数。9.2.2结构体数组的初始化【例9-2】计算学生的平均成绩和不及格的人数。structstu{intnum;char*name;charsex;floatscore;}boy[5]={/*定义了一个外部结构数组boy*/{101,"Liping",'M',45},/*初始化赋值*/{102,"Zhangping",'M',62.5},{103,"Hefang",'F',92.5},{104,"Chengling",'F',87},{105,"Wangming",'M',58},};9.2.2结构体数组的初始化main(){inti,c=0;floatave,s=0;for(i=0;i<5;i++){s+=boy[i].score; /*逐个累加各元素 的score成员值存于s之中*/

if(boy[i].score<60)c+=1;}printf("s=%f\n",s);ave=s/5; /*计算平均成绩*/

printf("average=%f\ncount=%d\n",ave,c); /*输出全班总分,平均分及不及格人数*/}9.2.2结构体数组的初始化【例9-2】程序运行结果如下图所示。9.3向函数传递结构体数据把结构体传递给函数有三种方法:传递单个成员,传递整个结构传递指向结构的指针。传递结构变量的地址可以实现结构的传引用调用,和其他数组一样,结构体数组也是自动以传引用调用的。9.4结构指针变量的说明和使用9.4.1指向结构变量的指针9.4.2指向结构数组的指针9.4.3结构指针变量作函数参数9.4.1指向结构变量的指针一个指针变量当用来指向一个结构变量时,称之为结构指针变量。结构指针变量中的值是所指向的结构变量的首地址。结构指针变量说明的一般形式为:

struct

结构名*结构指针变量名结构指针变量也必须要先赋值后才能使用。赋值是把结构变量的首地址赋予该指针变量,不能把结构名赋予该指针变量。结构名只能表示一个结构形式。9.4.1指向结构变量的指针有了结构指针变量,就能更方便地访问结构变量的各个成员。 其访问的一般形式为: (*结构指针变量).成员名 或为:结构指针变量->成员名9.4.1指向结构变量的指针【例9-5】structstu /*定义一个结构stu*/{intnum;char*name;charsex;floatscore;}boy1={102,"Zhangping",'M',78.5},*pstu;

/*定义stu类型结构变量boy1并作了初始化赋值*/main(){pstu=&boy1; /*pstu被赋予boy1的地址*/ /*用三种形式输出boy1的各个成员值*/9.4.1指向结构变量的指针printf("Number=%d\nName=%s\n",boy1.num,);printf("Sex=%c\nScore=%f\n\n",boy1.sex,boy1.score);printf("Number=%d\nName=%s\n",(*pstu).num,(*pstu).name);printf("Sex=%c\nScore=%f\n\n",(*pstu).sex,(*pstu).score);printf("Number=%d\nName=%s\n",pstu->num,pstu->name);printf("Sex=%c\nScore=%f\n\n",pstu->sex,pstu->score);}9.4.1指向结构变量的指针【【例9-5】程序运行结果如下图所示。9.4.2指向结构数组的指针指针变量可以指向一个结构数组,这时结构指针变量的值是整个结构数组的首地址。结构指针变量也可指向结构数组的一个元素,这时结构指针变量的值是该结构数组元素的首地址。应该注意的是,一个结构指针变量虽然可以用来访问结构变量或结构数组元素的成员,但是,不能使它指向一个成员。9.4.3结构指针变量作函数参数用结构指针变量作函数参数进行传送。这时由实参传向形参的只是地址,从而减少了时间和空间的开销。【例9-7】计算一组学生的平均成绩和不及格人数。用结构指针变量作函数参数编程。structstu{intnum;char*name;charsex;floatscore;}boy[5]={9.4.3结构指针变量作函数参数{101,"Liping",'M',45},{102,"Zhangping",'M',62.5},{103,"Hefang",'F',92.5},{104,"Chengling",'F',87},{105,"Wangming",'M',58},}; /*定义为外部结构数组*/main(){structstu*ps;voidave(structstu*ps);ps=boy; /*使ps指向boy数组*/

ave(ps);/*以ps作实参调用函数ave*/}9.4.3结构指针变量作函数参数

voidave(structstu*ps) /*定义函数ave,

其形参为结构指针变量ps*/{intc=0,i;floatave,s=0;for(i=0;i<5;i++,ps++){s+=ps->score;if(ps->score<60)c+=1;}printf("s=%f\n",s);ave=s/5;printf("average=%f\ncount=%d\n",ave,c);}9.4.3结构指针变量作函数参数【例9-7】程序运行结果如下图所示。9.5链表9.5.1动态存储结构9.5.2链表概念9.5.3链表操作9.5.1动态存储结构C语言提供了一些内存管理函数,这些内存管理函数可以按需要动态地分配内存空间,也可把不再使用的空间回收待用,为有效地利用内存资源提供了手段。常用的内存管理函数有以下三个。1.分配内存空间函数malloc

调用形式:(类型说明符*)malloc(size)功能:在内存的动态存储区中分配一块长度为“size”字节的连续区域。函数的返回值为该区域的首地址。9.5.1动态存储结构2.分配内存空间函数calloccalloc也用于分配内存空间。调用形式:(类型说明符*)calloc(n,size)功能:在内存动态存储区中分配n块长度为“size”字节的连续区域。函数的返回值为该区域的首地址。9.5.1动态存储结构3.释放内存空间函数free调用形式:

free(void*ptr);功能:释放ptr所指向的一块内存空间,ptr是一个任意类型的指针变量,它指向被释放区域的首地址。被释放区应是由malloc或calloc函数所分配的区域。9.5.2链表概念链表是一种常见的重要的数据结构。它是动态地进行存储分配的一种结构。链表是用指针链在一起的自引用结构(称为“节点”)的线性组合,如下图所示。9.5.3链表操作链表的基本操作对链表的主要操作有以下几种:(1)建立链表。(2)结构的查找与输出。(3)插入一个结点。(4)删除一个结点。9.5.3链表操作例如:建立一个三个结点的链表,存放学生数据。为简单起见,假定学生数据结构中只有学号和年龄两项。可编写一个建立链表的函数create。#defineNULL0#defineTYPEstructstu /*用TYPE表 示structstu*/#defineLENsizeof(structstu)structstu

{intnum;intage;structstu*next;};9.5.3链表操作

TYPE*create(intn)

/*建立一个有n个结点的链表*/{

structstu*head,*pf,*pb;

/*定义三个stu结构的指针变量*/

inti;for(i=0;i<n;i++){

pb=(TYPE*)malloc(LEN);

/*pb为后一结点的指针变量*/9.5.3链表操作

printf("inputNumberandAge\n");scanf("%d%d",&pb->num,&pb->age);if(i==0)pf=head=pb; /*pf为指向两相邻结点的 前一结点的指针变量*/

elsepf->next=pb;pb->next=NULL;pb=pf;}return(head);}9.6共用体9.6.1共用体类型的定义9.6.2共用体变量使用9.6.1共用体类型的定义同一区域可供不同类型的数据使用(但不在同一时刻),这些不同的数据,可以形成一种新的数据构造类型,它被称之为共用体。共用体类型定义的一般形式为:

union共用体名 {

数据类型

成员名1;

数据类型

成员名2; ........

数据类型

成员名N; }共用体用来使相关变量共享存储空间而不是把空间浪费给并不使用的变量。9.6.2共用体变量使用共用体类型变量以及指向共用体类型变量的指针变量的定义方法与结构体变量的和结构类型变量和指向结构体类型的指针变量的定义方法是十分相似的。可以用以下的说明语句定义这种类型的变量和指向这种类型变量的指针变量:

unionsempunivar,*uniptr;

例如:

uniondata {inti;

charc; floatf;}a,b,c;9.7枚举类型9.7.1枚举类型和枚举变量的定义9.7.2枚举类型变量使用9.7.1枚举类型和枚举变量的定义1.枚举的定义枚举类型定义的一般形式为:

enum

枚举名{枚举值表};在枚举值表中应罗列出所有可用值。这些值也称为枚举元素。2.枚举变量的说明枚举变量也可用不同的方式说明,即先定义后说明,同时定义说明或直接说明。9.7.2枚举类型变量使用枚举类型在使用中有以下规定:(1)枚举值是常量,不是变量。不能在程序中用赋值语句再对它赋值。(2)枚举元素本身由系统定义了一个表示序号的数值,从0开始顺序定义为0,1,2…。9.7.2枚举类型变量使用【例9-10】main(){enumweekday{sun,mon,tue,wed,thu,fri,sat}a,b,c; /*定义三个枚举类型变量*/

a=sun;b=mon;c=tue;printf("%d,%d,%d",a,b,c);}9.7.2枚举类型变量使用【例9-10】程序运行结果如下图所示。9.8用户自定义类型C语言不仅提供了丰富的数据类型,而且还允许由用户自己定义类型说明符,也就是说允许由用户为数据类型取“别名”。类型定义符typedef即可用来完成此功能。

typedef定义的一般形式为:

typedef

原类型名

新类型名其中原类型名中含有定义部分,新类型名一般用大写表示,以便于区别。9.8用户自定义类型例如,可把整型说明符用typedef定义为:

typedefintINTEGER

这以后就可用INTEGER来代替int作整型变量的类型说明了。例如:

INTEGERa,b;它等效于:

inta,b;9.9应用举例【例9-12】使用结构Card(如下图所示)来描述一张牌,用随机函数来模拟人工洗牌的过程。编程思想:(1)说明Card结构:(2)初始化一副牌。(3)模拟人工洗牌过程。9.9应用举例源程序:#include"stdlib.h"#include"time.h"typedefstruct{ intpips; /*从1到13。 1:A,11:J,12:Q,13:K*/ charsuit;

/*花色。C:梅花

D:

方块

H:红心

S:黑桃*/}Card;9.9应用举例/*初始化一副牌*/Carddeck[]={ {1,'C'},{2,'C'},{3,'C'},{4,'C'},{5,'C'},{6,'C'},{7,'C'}, {8,'C'},{9,'C'},{10,'C'},{11,'C'},{12,'C'},{13,'C'}, {1,'D'},{2,'D'},{3,'D'},{4,'D'},{5,'D'},{6,'D'},{7,'D'}, {8,'D'},{9,'D'},{10,'D'},{11,'D'},{12,'D'},{13,'D'}, {1,'E'},{2,'E'},{3,'E'},{4,'E'},{5,'E'},{6,'E'},{7,'E'}, {8,'E'},{9,'E'},{10,'E'},{11,'E'},{12,'E'},{13,'E'}, {1,'F'},{2,'F'},{3,'F'},{4,'F'},{5,'F'},{6,'F'},{7,'F'}, {8,'F'},{9,'F'},{10,'F'},{11,'F'},{12,'F'},{13,'F'}};9.9应用举例/*交换两张牌*/voidswapcard(Card*p,Card*q){ Cardtemp; temp=*p; *p=*q; *q=temp; /*交换两张牌*/

return;} /*模拟人工洗牌的过程*/voidshuffle(Carddeck[]){ inti,j; srand((unsigned)time(NULL)); /*调用函数 对随机函数初始化*/9.9应用举例for(i=0;i<52;i++) { j=rand()%52;/*从52张纸牌中随机选 择一张牌与第i张牌进行交换*/

swapcard(&deck[i],&deck[j]);/*以结构 数组中元素的地址为实参*/ }

return;}main(){ inti; shuffle(deck); for(i=0;i<52;i++)9.9应用举例if(i%13==0) printf("\nNo.%d:",i/13+1); else

printf("%c%2d,",deck[i].suit,deck[i].pips); getchar();}【例9-12】程序运行结果如下图所示。9.9应用举例【例9-13】用链表再解约瑟夫问题。约瑟夫问题是十七世纪的法国数学家加斯帕在《数目的游戏问题》中讲的一个故事:15个基督教徒和15个异教徒在海上遇险,必须将一半的人投入海中,其余的人才能幸免遇难,于是想了一个办法:30个人围成一个圈,从第一个人开始报数,每数到第九个人就将它扔近大海,如此循环进行直到尽余15人为止。问怎样排法,才能使每次投入大海的都是异教徒。9.9应用举例(1)题目中30个人围成一圈,因而启发用一个循环的链表来表示。如下图所示。(2)main函数实现过程。①创建并初始化链表环。②通过链表环,对约瑟夫问题求解(利用for循环15次,取出15人扔进大海)。③释放链表环内存。④输出排序结果。编程思想:9.9应用举例源程序:/*定义结构*/typedefstructnode{ node*nextp; /*指向下一个元素的指针*/

intno_out; /*是否被扔下海的标志1:没有 被扔下海0:已被扔下海*/}Person;main(){ printf("Theoriginalcircleis(+:pagandom,@:christian):\n"); /*创建并初始化链表*/

Person*head=newPerson;9.9应用举例/*初始化头结点*

温馨提示

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

评论

0/150

提交评论