《第7讲结构体与指针ppt课件.ppt》由会员分享,可在线阅读,更多相关《第7讲结构体与指针ppt课件.ppt(49页珍藏版)》请在三一办公上搜索。
1、1,复习:(1)结构体变量的定义与引用(2)结构体数组,新内容:(1)指向结构体变量的指针(2)指向结构体数组的指针(3)结构体指针作为函数参数(4)用指针处理链表,第7讲 结构体与指针,2,复习:结构体变量的定义与引用,注意不要忘了分号,结构体类型定义形式:,struct 结构体类型名 数据类型 成员名1;数据类型 成员名2;:数据类型 成员名n;,关键字,用户定义的标识符,3,2.定义结构体类型同时定义变量 struct student char name10;int age;int s1,s2;st1,st2;,1.先定义结构体类型,再定义变量 struct student char n
2、ame10;int age;int s1,s2;struct student st1,st2;,复习:结构体变量的定义与引用,结构体变量的定义,结构体类型定义,结构体 变量定义,结构体变量占用的字节数可用 sizeof 运算符算出,printf(“%dn”,sizeof(struct student);printf(“%dn”,sizeof(st1);,4,复习:结构体变量的定义与引用,例:struct date int year;int month;int day;struct stud char name10;struct date birthday;int s1,s2;,结构体类型可以嵌
3、套定义,或:struct stud char name10;struct date int year;int month;int day;birthday;int s1,s2;,5,复习:结构体变量的定义与引用,应用typedef定义结构体类型,struct student char name10;int age;int s1,s2;struct student st1,st2;,typedef struct student char name10;int age;int s1,s2;SD;SD st1,st2;,优点:书写简单,使程序具有更好的移植性,6,复习:结构体变量的定义与引用,引用结
4、构体变量中的成员(点记法)格式:结构体变量名.成员名,struct student char name10;int age;int s1,s2;st1,st2;,strcpy(st1.name,“Mary”);st1.age=21;scanf(“%d%d”,相同类型的结构体变量可以进行整体赋值,只能对结构体变量的成员进行输入和输出,st2=st1;,7,11.6.1 指向结构体数据的指针,定义指向结构体变量的指针 typedef struct student char name20;int age;int s1,s2;SD;SD x,stu,*p;p=,成员的引用格式(1)结构体变量名.成员名
5、 stu.name,例:scanf(“%s”,x.name);scanf(“%d”,(2)(*指针变量名).成员名(*p).age,(3)指针变量名-成员名 p-s1,8,赋值语句 p=,指针变量p指向结构体变量student,引用结构体中的成员变量:(*p).成员名 或 p-成员名,相当于,student.成员名,9,说明:和成员运算符一样,“-”为指向运算符,是运算 优先级最高的运算符。由于成员运算符“.”的运算优先级高于运算符“*”,因此(*p).成员名中()不能少。,*p.成员名,p=,不能用指向某个结构体变量的指针指向该结构体变量的某个成员。,10,对结构体数组及其元素可以用指针来指
6、向,例如:struct struct_name char name10;int num;float score;/*定义结构体类型标识符*/struct struct_name std30,*p;,11.6.1 指向结构体数组的指针,11,赋值语句 p=std;/*p指向一个结构体数组std*/,/*指针变量p存放的是数组std的首地址*/,引用:p-name;p-num;p-score;,12,思考:赋值语句 p=std+1;和p+;分别代表指针p指向哪里?,p-name;p-num;p-score;代表的信息发生了什么变化?,13,注意:以下赋值语句都是错误的:,p=,(不能指向数组元素的
7、成员变量),p=,(数组名本身就代表该数组的首地址,因此不能使用地址运算符&),14,结构体变量作为函数参数1.函数实参和形参都用结构体变量,参数之间为值传递实参结构体变量各成员的值依次传给形参结构体变量,2.返回结构体类型值的函数 定义格式:结构体类型名 函数名(形参表)函数体;例:struct student funct(int x,float y)函数体;,注意:结构体类型是已经定义好的,11.6.3 结构体指针作为函数参数,15,#include#define N 5struct stud char name10;int s3;int sum,ave;,struct stud coun
8、t(struct stud x)int j;x.sum=0;for(j=0;j3;j+)x.sum=x.sum+x.sj;x.ave=x.sum/3;return(x);,例:求学生成绩的总分和平均分(结构体变量作参数),/定义学生的结构体类型,/计算学生三门课的总分,/返回学生的全部信息,/结构体变量作参数 返回结构体类型的值,16,void main()struct stud aN;int j;for(j=0;jN;j+)scanf(“%s%d%d%d”,aj.name,/函数调用,将aj的值传给count函数 的参数x,并将返回值赋给aj,/输入N个学生的信息,/定义结构体数组a,存放N
9、个学生的信息,17,struct stud count(struct stud*p)int j;p-sum=0;for(j=0;jsum=p-sum+p-sj;p-ave=p-sum/3;return(p);,例:求学生成绩的总分和平均分(指向结构体的指针作参数),#include#define N 5struct stud char name10;int s3;int sum,ave;,/指向结构体的指针作参数返回结构体类型的值,18,void main()struct stud aN;int j;for(j=0;jN;j+)scanf(“%s%d%d%d”,aj.name,19,void
10、main()struct stud aN,*q;int j;q=a;for(j=0;jname,20,课后作业题,定义一个结构体用于存储年、月、日数据,并定义函数用于求两个日期之间的天数。,21,11.7 用指针处理链表,链表:是可以动态地进行存储分配的一种数据结构 它是由一组动态数据链接而成的序列,结点:链表中的每一个动态数据称为一个结点,表头结点,表尾结点,NULL为空地址 表示链表到此结束,中间结点,22,一.、基本概念1.动态存储分配:根据需要临时分配内存单元用以存放数据,当数据不用时可以随时释放内存单元2.链表:是可以动态地进行存储分配的一种数据结构 它是由一组动态数据链接而成的序列
11、3.结点:链表中的每一个动态数据称为一个结点,4.结点类型:是一个包含指针项的结构体类型 一般由两部分组成:(1)数据成员:存放数据(2)指针成员:存放下一个结点的地址,23,struct sd int num;int score;struct sd*next;,链表的基本概念,24,链表的基本概念,链表的每个结点存放在内存中的不同位置,只有找到第1个结点,才能通过第1个结点的指针成员找到第2个结点 因此我们将第1个结点的地址存放在头指针中,头指针,链表的长度是不固定的,可以随时添加结点,如果将一个结点添加到链表的尾部,则新结点成为表尾结点,它的指针成员必须赋为NULL,而原来的表尾结点则成为
12、中间结点,3692,25,静态简单链表,#include typedef struct stud int num,score;struct stud*next;SD;,2010,1428,1570,2010,1951428,2861570,382NULL,2010,1428,1570,NULL,void main()SD a,b,c,*head,*p;head=,26,动态链表的建立,建立链表的方法表尾添加法:新结点作为表尾结点表首添加法:新结点作为表头结点,2010,2010,1428,1570,2010,1428,27,处理动态链表所需的函数(需用头文件)1.malloc 函数 原型:vo
13、id*malloc(unsigned int size)作用:在内存中开辟一个长度为 size 的连续存储空间,并将此存储 空间的起始地址带回,注意:(1)函数返回值是指针,但该指针是指向void类型的,因此在 使用时希望这个指针指向其他类型需要用强制类型转换(2)如果内存缺少足够大的空间进行分配,则 malloc 函数 返回值为“空指针”(即NULL),例:struct sd*p;p=(struct sd*)malloc(sizeof(struct sd);,强制类型转换,结构体类型占用的字节长度,28,2.free函数 原型:void free(void*ptr)作用:将指针变量ptr指向
14、的存储空间释放,注意:ptr的值不是任意的地址,必须是程序中执行malloc 函数所返回的地址(2)模型中ptr是void型,但调用free函数时,参数可能是 其他类型,计算机系统会自动进行转换,例:struct sd*p;p=(struct sd*)malloc(sizeof(struct sd);free(p);,4200,4200,29,动态链表的建立,表尾添加法建立链表,#include#includetypedef struct student int num;int score;struct student*next;ST;#define LEN sizeof(ST)int n;,
15、定义ST,以后书写简单,求出结构体类型占用的字节数,全局量n 表示结点的个数,30,ST*creat(void)ST*p1,*p2,*head=NULL;n=0;p1=(ST*)malloc(LEN);if(p1=NULL)printf(n No enough memory!n);exit(0);scanf(%d%d,/产生一个新结点,/输入新结点的数据成员,/结点个数加1,/让指针p2指向p1所指向的结点,/表尾结点的指针成员赋为空,/释放p1所指向的结点空间,/p1指向新产生的结点,/若n等于1,则p1当前所指向的是表头结点,31,表尾添加法建立链表的过程演示,ST*creat(void)
16、ST*p1,*p2,*head;head=NULL;n=0;p1=(ST*)malloc(LEN);scanf(%d%d,2010,1428,1570,NULL,3264,2010,2010,195,1428,2010,1428,286,382,00,1428,1570,NULL,1570,1570,3264,0,1,2,3,32,动态链表的遍历(输出),输出链表void list(ST*head)ST*p;p=head;while(p!=NULL)printf(“%d,%dn”,p-num,p-score);p=p-next;,2010,1428,1570,2010,1951428,2861
17、570,382NULL,2010,1428,1570,NULL,输出:1,95,2,86,3,82,void main()ST*h=NULL;h=creat();list(h);,33,链表的删除结点操作,删除表头结点,让头指针指向链表的第2个结点,1428,step1:让指针变量p指向要删除的结点即表头结点,step2:重新给头指针赋值,使它指向第2个结点,head=p-next;,step3:释放删除的结点空间,free(p);,p=head;,34,链表的删除结点操作,删除表尾结点,将链表的倒数第2个结点的指针成员赋为NULL,step1:让指针变量p指向要删除的结点即表尾结点 让指针变
18、量q指向要删除结点的前一个结点,step2:将删除结点的前驱结点的指针成员赋空值,step3:释放删除的结点空间,free(p);,q-next=NULL;,NULL,35,链表的删除结点操作,删除中间结点,step1:让p指向要删除的结点,让q指向要删除结点的前驱结点,step2:前驱结点的指针成员赋为要删除结点的指针成员值,step3:释放删除的结点空间 free(p);,q-next=p-next;,让要删除结点的前驱结点指向要删除结点的后继结点,1570,36,ST*del(ST*head,int num)ST*p,*q=NULL;p=head;while(num!=p-num),ty
19、pedef struct student int num;int score;struct student*next;ST;,链表的删除结点操作,删除结点函数,令p指向要删除的结点,q指向其前驱结点,/删除结点为表头结点,/删除结点为表尾结点或中间结点,/释放已删除的结点空间,/链表的结点个数减1,/返回链表的头指针,37,ST*p,*q=NULL;p=head;while(num!=p-num),设num=3,2010,1428,1428,1570,让p指向要删除的结点,让q指向其前驱结点,链表的删除结点操作,38,链表的插入结点操作,插入的结点作表头结点,2010,让p0指向新结点即要插入
20、的结点,让p1 指向插入位置上的结点即表头结点,head=p0;p0-next=p1;,2106,39,插入的结点作表尾结点,让p0指向新结点即要插入的结点,让p1 指向插入位置上的结点即表尾结点,NULL,3652,链表的插入结点操作,p1-next=p0;p0-next=NULL;,40,插入的结点作中间结点,链表的插入结点操作,让p0指向新结点即要插入的结点,让p1 指向插入位置上的结点,p2指向p1的前驱结点,2374,1570,p2-next=p0;p0-next=p1;,41,链表的插入结点操作,插入结点函数,ST*insert(ST*head)ST*p0,*p1,*p2;p1=h
21、ead;p0=(ST*)malloc(LEN);scanf(“%d%d”,/如果是空链表,则新结点是链表的表头结点,/找到要插入结点的位置,/插入结点作表头结点,/插入结点作中间结点,/插入结点作表尾结点,/链表的结点个数加1,42,链表的插入结点操作,(1)插入链表的第一个结点ST*insert(ST*head)ST*p0,*p1,*p2;p1=head;p0=(ST*)malloc(LEN);scanf(“%d%d”,386,1428,NULL,1428,NULL,1,43,链表的插入结点操作,ST*insert(ST*head)ST*p0,*p1,*p2;p1=head;p0=(ST*)
22、malloc(LEN);scanf(“%d%d”,1428,2,2010,1428,195,(2)插入结点作表头结点,1428,2010,44,链表的插入结点操作,ST*insert(ST*head)ST*p0,*p1,*p2;p1=head;p0=(ST*)malloc(LEN);scanf(“%d%d”,(3)插入结点作表尾结点,582,NULL,2010,2010,1428,3,1570,45,练 习 题,建立一个链表并输出;根据用户要求删除链表中第n个结点;根据用户要求在第n个结点后插入一个结点;输出改变的链表;main函数调用各函数.,46,#include#includetyped
23、ef struct student int num;int score;struct student*next;ST;#define LEN sizeof(ST)int n=0;,ST*creat(void)ST*p1,*p2,*head=NULL;p1=(ST*)malloc(LEN);if(p1=NULL)printf(n No enough memory!n);exit(0);scanf(%d%d,47,void list(ST*head)ST*p;p=head;while(p!=NULL)printf(“%d,%dn”,p-num,p-score);p=p-next;,ST*del(ST*head)ST*p,*q;p=head;int i,num;printf(“delete n:”);scanf(“%d”,48,ST*insert(ST*head)ST*p,*q,*p0;p=head;int i,num;printf(“insert n:”);scanf(“%d”,49,void main()ST*h=NULL;h=creat();list(h);h=del(h);list(h);h=insert(h);list(h);,