收藏 分享(赏)

c语言教程第8章-结构体.ppt

上传人:cjc2202537 文档编号:1005938 上传时间:2018-05-16 格式:PPT 页数:65 大小:478.50KB
下载 相关 举报
c语言教程第8章-结构体.ppt_第1页
第1页 / 共65页
c语言教程第8章-结构体.ppt_第2页
第2页 / 共65页
c语言教程第8章-结构体.ppt_第3页
第3页 / 共65页
c语言教程第8章-结构体.ppt_第4页
第4页 / 共65页
c语言教程第8章-结构体.ppt_第5页
第5页 / 共65页
点击查看更多>>
资源描述

1、第8章 结构体,结构体,共用体,思考一个问题,在程序里表示一个人的信息(姓名、年龄、性别、),怎么表示?表示多个人呢?如何用计算机程序实现下述表格的管理?,表8-1 某学校学生成绩管理表,数组的解决方法,int studentId30; /* 最多可以管理30个学生, 每个学生的学号用数组的下标表示*/charstudentName3010;charstudentSex302;int timeOfEnter30; /*入学时间用int表示*/int scoreComputer30;/*计算机原理课的成绩*/int scoreEnglish30; /*英语课的成绩*/int scoreMath3

2、0; /*数学课的成绩*/int scoreMusic30; /*音乐课的成绩*/,数组的解决方法,int studentId30 = 1,2,3,4,5,6;charstudentName3010 = 令狐冲,林平之, 岳灵珊,任莹莹;charstudentSex302 = 男,男,女,女;int timeOfEnter30 = 1999,1999,1999,1999;int scoreComputer30 = 90,78,89,78;int scoreEnglish30 = 83,92,72,95;int scoreMath30 = 72,88,98,87;int scoreMusic30

3、 = 82,78,66,90;,数组的解决方法,数据的内存管理方式,数组的解决方法,分配内存不集中,寻址效率不高 对数组进行赋初值时,容易发生错位 结构显得比较零散,不容易管理,希望的内存分配图,结构体的解决方法,struct STUDENT int studentID; /*每个学生的序号*/ char studentName10;/*每个学生的姓名*/ char studentSex4; /*每个学生的性别*/ inttimeOfEnter; /*每个学生的入学时间*/ intscoreComputer; /*每个学生的计算机原理成绩*/ intscoreEnglish; /*每个学生的英

4、语成绩*/ intscoreMath; /*每个学生的数学成绩*/ intscoreMusic; /*每个学生的音乐成绩*/ ;,struct STUDENT是一个类型struct STUDENT students4;students0.studentNamestudents0.Sex它们都是变量,一般称为结构的成员变量,8.1 结构体的定义,结构体类型的定义 结构体类型变量的引用 结构体变量的初始化,struct studentint num; char name20; char sex; int age; char addr30;;,是数据类型,不是变量名,对各成员都要进行类型说明;成员名

5、定名规则与变量名同。,一、结构体类型的定义,一般形式为:,struct 结构体名 成员表列 ;,方法一:先定义结构体类型再定义变量名struct studentint num; char name20; char sex; int age; char addr30;;struct student student1, student2;,定义studet1和sudent2为struct student类型变量,结构体类型变量的定义,有时,可用符号常量代表一个结构体类型 ,如:,#define STUDENT struct studentSTUDENTint num; char name20; c

6、har sex; int age; char addr30;,这样,可直接用STUDENT定义变量,如:STUDENT student1, student2;此时,不必再写关键字struct,方法二:在定义类型的同时定义变量,struct studentint num; char name20; char sex; int age; char addr30; student1, student2;,一般形式是:struct 结构体名 成员列表 变量名列表;,方法三:直接定义结构类型变量。,其一般形式是:struct 成员表列 变量名表列;,此时,不出现结构体名,typedef 的用法,功能:定

7、义新类型,即为C语言中已有的数据类型 名定义一个新名字。,定义格式: typedef 标识符1 标识符2,struct student int num; char name20; char sex; int age; float score; char addr30; ;typedef struct student STUD;STUD student1,student2;,用typedef为已存在的类型定义新名字,用STUD代替 struct student类型;,几点说明:,1. 类型与变量是不同概念,不要混淆;2. 结构体中的成员,可以单独使用,其作 用与地位相当于普通变量;3. 成员名可

8、以与程序中的变量名相同,二 者不代表同一对象。,struct date int month; int day; int year; ;,Struct studentint num;char name20;int age;struct date birthday;student1,student2;,4. 成员也可以是一个结构体变量;,例如:,规则:1. 不能将一个结构体变量作为一个整体进行赋值和输出;只能对其各个成员分别输出printf(“.”,student1); printf(“ %d”, student1.num);,错!,正确!,引用形式为:结构体变量名.成员名,二、结构体类型变量的引

9、用,3. 对成员变量可以象普通变量一样进行各种运算,如: sumage=student1.age+student2.age;4. 可以引用成员的地址,也可以引用结构体变量的地址,如 scanf(“%d”,错!,输入student1.num的值,输出student1的首地址,2 .若成员本身又属一个结构体类型,只能对最低级的 成员进行赋值或存取以及运算。 如:student1.birthday.year,(一)对外部存储类型的结构体变量初始化: struct studentlong int num; char name20; char sex; char addr20; a=9801,”Wang

10、 hong”,W,”2 Linggong Road”;main( )printf(“No.:%ldnname:%snsex:%cnaddress:%sn”,a.num,a.name,a.sex,a.addr);,运行结果为:No.:9801name:Wang hongsex:Waddress:2 Linggong Road,三、 结构体变量的初始化,main( )static struct student long int num; char name20; char sex; char addr20; a=9801,”Wang hong”,W,”2 Linggong Road”; print

11、f(“No.:%ldnname:%snsex:%cnaddress:%sn” , a.num,a.name,a.sex,a.addr);,(二)对静态存储类型的结构体变量初始化,(一)结构体数组的定义 struct studentint num; char name20; char sex; int age; char addr30; struct studnt stu3;,也可直接定义,如struct student int num; stu3;或struct int num; stu3;, 8.2 结构体数组(每个数组元素都是一个结构体类型的数据),struct studentint nu

12、m; char name20; char sex; int age; char addr30; stu3=111,”Li”,M,18,”Dalian”,;,结构体数组 初始化的一般形式是在定义数组后面加上:=初值表列;,也可采用:struct student int num; ; struct student stu=,;,(二)结构体数组的初始化(只能对全局的或静态存储 类别的数组初始化),struct person char name20; int count; leader3=“Li”,0 ,”zhang”,0,”Liu”,0;main( ) int i, j; char leader_

13、name20; for( i=1;i=10;i+) scanf(“%s”,leader_name); for(j=0;j3;j+) if(strcmp(leader_name,leaderj.name)= =0)leaderj.count+; for(i=0;i成员名,指向运算符。其优先级高于自增、自减运算符,试分析以下运算:,成员运算符,得到p指向的结构体变量中的成员n的值使其先加1,+ ( p-n),得到p指向的结构体变量中的成员n的值,用完后使它加1;,(p-n)+,得到p指向的结构体变量中的成员n的值,p-n,for (pt=stu; ptscoreComputer; sum1 = s

14、um1 + pt-scoreEnglish; sum2 = sum2 + pt-scoreMath; sum3 = sum3 + pt-scoreMusic; for (i=0; iscoreEnglish; sum2 = sum2 + pt-scoreMath; sum3 = sum3 + pt-scoreMusic; for (i=0; i4; i+) averagei = sumi/4; printf(%20s : %4.2fn, namei, *(average+i); ,1. 向函数传递结构体的单个成员单向值传递,函数内对结构内容的修改不影响原结构2. 用整个结构体变量作实参和形参,

15、向函数传递结构体的完整结构单向值传递,函数内对结构内容的修改不影响原结构,开销大, 8.4 结构体与函数,结构体参与函数运算的几种形式:,3. 向函数传递结构体的首地址 用结构体数组或者结构体指针做函数参数 除提高效率外,还可以修改结构体指针所指向的结构体的内容4、用结构体类型作为函数返回类型,一付扑克有52张牌,分为4种花色(Suit):黑桃(Spades)、红桃(Hearts)、草花(Clubs)、方块(Diamonds)每种花色有13张牌面(Face):A,2,3,4,5,6,7,8,9,10,Jack,Queen,King设计一个结构体表示一张牌,由两个成分组成:花色、牌面: stru

16、ct CARD char suit10; char face10; ; struct CARD card52; /*顺序存放扑克牌*/ int result52; /*存放洗牌发牌结果*/ char *suit = Spades,Hearts,Clubs,Diamonds; char *face = A,2,3,4,5,6,7,8,9, 10,jack,Queen,King;,例8.1 :洗牌和发牌模拟,发牌过程将52张牌按照随机的顺序存放算法步骤:产生051的随机数,将其放于resulti内。i=i+1如果i=51,则重复第2步,否则,结束循环输出结果存在一个致命的问题:在重复第2步时,产生

17、的随机数可能与以前产生的随机数相同,相同意味着52张牌中出现2张以上相同的牌,例8.1 :洗牌和发牌模拟,解决方法增加一步,判断新产生的随机数以前是否出现过如果出现过,则放弃;如果以前未出现过,则保留算法步骤:产生051的随机数m,将其放于resulti内。判断resulti在以前(result0resulti-1)是否出现过。如果出现过,则回到第2步;如果没出现过,则i=i+1如果i=51,则重复第23步,否则,结束循环输出结果,例8.1 :洗牌和发牌模拟,算法缺陷:随着随机数数量的增加,新的随机数与已经产生的随机数相同的可能性越来越大,有可能出现算法延迟问题 高效算法将按照花色与牌面的顺序

18、存放的牌(cardi)随机打乱每次循环,程序选择一个051的随机数j,然后将数组中当前的CARD结构cardi与随机选出的j所在的数组元素cardj结构进行交换,例8.1 :洗牌和发牌模拟,用结构体数组做函数参数void FillCard(struct CARD wCard,char *wFace,char *wSuit)inti;for (i=0; i52; i+)strcpy(wCardi.suit, wSuiti/13);strcpy(wCardi.face, wFacei%13);,例8.1 :洗牌和发牌模拟(P313),用结构体指针做函数参数void Shuffle(struct C

19、ARD *wCard)int i,j;struct card temp;for (i=0; i52; i+)j = rand()%52; /*j = random(52);TC的库函数*/temp = wCardi; wCardi = wCardj;wCardj = temp; /* 洗牌过程 */,例8.1 :洗牌和发牌模拟(P313),用结构体指针做函数参数void Deal(struct CARD *wCard) int i;for (i=0; ipt1.xrt-pt1.x,实验九 结构体编程练习在屏幕上模拟显示一个数字式时钟,定义一个时钟结构体类型:struct clock int h

20、our; int minute; int second;typedef struct clock CLOCK;,void update(CLOCK *t) t-second+; if (t-second=60) t-second=0; t-minute+; if (t-minute=60) t-minute =0; t-hour+; if (t-hour=24) t-hour=0;,void display(CLOCK *t) printf(%2d:%2d:%2dr, t-hour, t-minute, t-second);,实验九 结构体编程练习在屏幕上模拟显示一个数字式时钟,内存动态分配函

21、数 C语言提供以下几个动态存储分配函数:,malloc(size)calloc(n, size)free(ptr), 8.5用指针处理链表,1. malloc(size) 功能:在内存的动态存储区分配一个长度为size的连续空间。,此函数的返回值是一个指针,它的值是该分配区域的起始地址。若此函数未能成功地执行,则返回值为0。,2. calloc(n, size) 功能:在内存的动态存储区中分配n个长度为size的连续空间。,3. free(ptr)功能:释放由ptr指向的内存区。ptr是最近一次调用malloc或calloc函数时返回的值。,函数返回分配域的起始地址;若分配不成功,返回0。,m

22、alloc(size)与calloc(n, size)的区别 malloc(size)不能初始化所分配的内存空间 calloc(n, size) 能初始化所分配的内存空间,如果由malloc(size)函数分配的内存空间 原来没有被使用过,则其中的每一位都可能是0;如果这部分内存空间曾经被分配、释放和重新分配,则其中可能遗留各种各样的数据。,calloc(n, size)函数会将所分配的内存空间 的每一位都初始化为0,malloc(size)与calloc(n, size)的返回值处理,malloc(size)与calloc(n, size)的返回值都是 void类型的指针,具有一般性,是抽象

23、类型的数据若将函数调用的返回值赋予某指针,则应先根据该指针的基类型,对返回的指针进行强制类型转换。,链表的概念链表是一种常见的重要的数据结构。它是动态地进行存储分配的一种结构。链表有一个“头指针”变量,它存放一个地址,该地址指向链表中的第一个元素。如下图所示:,链表中每一个元素称为“结点”,每个结点都应包括两个部分:,数据域:用户需要用的实际数据,指针域:下一个结点的地址,结点1,结点2,结点n,可以看出: 头指针head指向第一个元素; 第一个元素又指向第二个元素;.直到最后一个元素,该元素不再指向其它元素,它称为“链尾”, 其地址部分存放一个“NULL”(表示“空地址”)。链表到此结束。

24、对于两个相邻的结点p1、p2, p1是p2的直接前驱结点, p2是p1的直接后继结点,由此可以看出:链表中结点必须是结构体类型,其中一个成员是指针类型,这个指针类型指向它所在的结构体类型。,其中next是成员名,是指针类型,它指向 struct link 类型数据,例如:struct link int data; struct link *next; ;,前面只是定义了一个struct link类型,并未实际分配存储空间,可用前述方法在需要时动态地开辟和释放存储单元。例如:#include “stdlib.h” p=(struct link *)malloc(sizeof(struct lin

25、k );if(p!= NULL) p-data=10;p-next=NULL;,其中sizeof( )的功能是测试某种类型的变量在内存中所占用的字节数。例如,sizeof(float)的值是4,它表示float型变量在内存中占4个字节。,free (p);,struct Link int data; Struct Link *next; ;,线性表的链式存储结构可用C语言中的“结构指针”来描述,带头结点的线性链表,不带头结点的线性链表,1、动态链表的建立(新结点链接在链尾),初态,第一次插入,第n次插入,2、在头指针为h 的单链表中查找结点 x,Struct link * dlbcz( Str

26、uct link * h, int x ) Struct link * p; p=h ; while(p!=NULL ,struct Link int data; Struct Link *next; ;,3 、单链表的插入运算(后插),void dlbhcr (struct Link *p, int x) struct Link *s ; s=(struct Link *)malloc(sizeof(struct Link); if(s!=NULL)s-data=x;s-next=p-next;p-next=s; else printf(“unsucess!”);,Void dlbsc (s

27、truct Link *p) struct Link *q ; if( p-next !=NULL) q=p-next ; p-next=q-next ; free(q); ,4、单链表的删除运算 (在单链表中删除 p 结点的直接后继结点 q ),5、单链表中直接插入或删除某个结点p,插入某个结点p时需考虑:1. 插入点p在第一个结点之前,应修改头指针head及其指向 即:p - next=head; head=p;2. 插入点p在链表中间,应修改插入点前pr结点的指向 即: p - next=pr - next; pr - next =p;3. 插入点p在链尾,应修改原链表最后一个结点pr指

28、针域的指向,并将新插入的结点p的指针域赋为NULL. 即: p - next=NULL; pr - next =p;,删除某个结点p时需考虑:1. 欲删除的结点p是第一个结点,应修改头指针head及其指向 即: head = p - next; free(p);2. 欲删除的结点p在链表中间或链尾,应修改欲删除的结点p之前pr结点的指向 即: pr - next = p - next; free(p);,动态数组(一般了解) 用calloc(n, size)函数开辟的存储单元相当于一个一维数组 第一个参数n决定了一维数组的大小 第二个参数size决定了数组元素的类型 函数的返回值就是数组的首地

29、址, 8.7 共 用 体(联合体),一、共用体类型的定义,一般形式为:,union 共用体名 成员表列 ;,例: union number int x ; float y ; ;,二、共用体变量的定义,例: union number int x ; float y ; s1, s2 ;,变量s1的存储空间为:,S1.y,S1. x,三、共用体变量的引用,注意:不能引用共用体变量,仅能引用共用体变量中的成员。 如:printf(“%d”,s1); 错 printf(“%d,%d”,s1.x,s1.y); 对,1. 同一段内存允许有多种类型的成员,某一时刻仅 一个成员起作用。2.共用体使用覆盖技术

30、,起作用的是最后一次存放的成员。 如: s1.x=1;s1.y=3.5;s1.y有效3. 变量及各成员的地址相同。4. 不能对共用体变量名赋值。5. 共用体变量初始化时,只能对第一个成员的数据类型初始化。6.两个共用体变量不能进行比较操作,四、对共用体变量的有关说明,与结构体的异同:相同之处:类型说明形式、变量定义方式与结构体相同。 不同之处:结构体变量中各成员有独立的存 储空间,而共用体中所有成员共用同一存储空间。,struct person char name20; char sex; int age; union int single; struct char spouseName20; int child; married; struct date divorcedDay; marital; int marryFlag;,共用体的应用,这一章我们学习了,两种新的数据类型结构体和共用体 几种重要的应用结构体数组结构体指针用结构体指针做函数参数用结构体指针实现动态数据结构,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 教育学

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报