【文档说明】C语言课程第9章-结构体数据类型与链表课件.ppt,共(47)页,710.001 KB,由小橙橙上传
转载请保留链接:https://www.ichengzhen.cn/view-44573.html
以下为本文档部分文字说明:
第九章结构体与链表内容提要•结构体类型的定义•结构体类型变量•结构体类型数组•结构体类型指针•结构体与函数•链表上一页下一页结构体概述(1)•结构体–结构体是一种构造数据类型–用途:把不同类型的数据组合成一
个整体---自定义数据类型–结构体类型定义struct[结构体名]{类型标识符成员名1;类型标识符成员名2;…………….};成员类型可以是基本型或构造型struct是关键字,不能省略合法标识符可省:无名
结构体上一页下一页结构体概述(2)•定义结构体类型,描述下列数据–(1)学生情况:包含学生的学号、姓名、性别、年龄、C语言课程成绩:structstudent{intno;/*学号*/charname[10
];/*姓名*/charsex;/*性别*/intage;/*年龄*/floatscore;/*C成绩*/};注:‘;’不能省结构体类型定义描述结构的组织形式,不分配内存上一页下一页如考虑10门课程成绩,加上总成绩与平均成绩,可作如下定义:structst
udent{intno;/*学号*/charname[10];/*姓名*/charsex;/*性别*/intage;/*年龄*/floatscore[10];/*10门课程成绩*/floattcj,acj;/*总成绩,平均成绩*/};上一页
下一页•定义结构体类型,描述下列数据–(2)个人数据:包含姓名、性别、年龄、身高、体重、住址:structperson{charname[20];/*姓名*/charsex;/*性别*/intage;/*年龄*/floatheight;/*身高*/floatweigh
t;/*体重*/charaddr[50];/*住址*/};上一页下一页(3)日期结构体类型包括年、月、日:structdate{intyear;/*年*/month;/*月*/day;/*日*/};(4)如职工信息结构体类型:structperson{charname[20];/*姓名*/ch
araddress[40];/*地址*/floatsalary;/*工资*/floatcost;/*扣款*/structdatehiredate;/*聘任日期*/};结构体类型可以嵌套定义即一个结构体类
型中的某些成员又是其他结构体类型上一页下一页结构体类型变量的定义(1)•先定义结构体类型,再定义结构体变量一般形式:例structstudent{intnum;charname[20];charsex;intage;floatscore
;charaddr[30];};structstudentstu1,stu2;struct结构体名{类型标识符成员名;类型标识符成员名;…………….};struct结构体名变量名表列;例#defineSTUDENTstructstudentSTU
DENT{intnum;charname[20];charsex;intage;floatscore;charaddr[30];};STUDENTstu1,stu2;上一页下一页结构体类型变量的定义(2)•定义结构体类型的同时定义结构体变量一般形式:struct结构体名{类型标识符成员
名;类型标识符成员名;…………….}变量名表列;例structstudent{intnum;charname[20];charsex;intage;floatscore;charaddr[30];}st
u1,stu2;上一页下一页结构体类型变量的定义(3)•直接定义结构体变量一般形式:struct{类型标识符成员名;类型标识符成员名;…………….}变量名表列;例struct{intnum;charname[2
0];charsex;intage;floatscore;charaddr[30];}stu1,stu2;用无名结构体直接定义变量只能一次上一页下一页结构体类型声明的说明•说明结构体类型与结构体变量概念不同•类型:不分配内存;变量:分配内存•类型:不能赋值、存取、运算;变量
:可以结构体可嵌套结构体成员名与程序中变量名可相同,不会混淆结构体类型及变量的作用域与生存期例structdate{intmonth;intday;intyear;};structstudent{intnum;charname[20
];structdatebirthday;}stu;numnamebirthdaymonthdayyear例structstudent{intnum;charname[20];structdate{intmonth;intday;intyear;}birthday;}stu;numnam
ebirthdaymonthdayyear上一页下一页结构体变量的使用(1)•由结构体变量名引用其成员结构体变量不能整体引用,只能引用变量成员可以将一个结构体变量赋值给另一个结构体变量结构体嵌套时逐级引用引用方式:结构体变量名.成员名成员(分量
)运算符优先级:1结合性:从左向右例structstudent{intnum;charname[20];charsex;intage;floatscore;charaddr[30];}stu1,stu2;stu1.num=10;stu1.score=85.5
;stu1.score+=stu2.score;stu1.age++;例structstudent{intnum;charname[20];charsex;intage;floatscore;charaddr[30];}stu1,stu2;p
rintf(“%d,%s,%c,%d,%f,%s\n”,stu1);()stu1={101,“WanLin”,„M‟,19,87.5,“DaLian”};()例structstudent{intnum;charname[20];charsex;intage;
floatscore;charaddr[30];}stu1,stu2;stu2=stu1;()例structstudent{intnum;charname[20];structdate{intmonth;intday;inty
ear;}birthday;}stu1,stu2;numnamebirthdaymonthdayyearstu1.birthday.month=12;例structstudent{intnum;charname[20];charsex;intage
;floatscore;charaddr[30];}stu1,stu2;if(stu1==stu2)……..()上一页下一页结构体变量的初始化(1)•形式一:struct结构体名{类型标识符成员名;类型标识符成员名;…………….};struc
t结构体名结构体变量={初始数据};例structstudent{intnum;charname[20];charsex;intage;charaddr[30];};structstudentstu1={112,“WangLin”,„M‟,19,“200BeijingRoad”};上一页下
一页结构体变量的初始化(2)•形式二:struct结构体名{类型标识符成员名;类型标识符成员名;…………….}结构体变量={初始数据};例structstudent{intnum;charname[20];charsex;intage;
charaddr[30];}stu1={112,“WangLin”,„M‟,19,“200BeijingRoad”};上一页下一页结构体变量的初始化(3)•形式三:struct{类型标识符成员名;类型标识符成员名;…………….}结构体变量={初始数据};例struct{intnum;char
name[20];charsex;intage;charaddr[30];}stu1={112,“WangLin”,„M‟,19,“200BeijingRoad”};上一页下一页结构体变量存储分配示意图stru11000102010
0110231026name[20]sexagescore上一页下一页例9.1求某同学上学期8门课程的总成绩与平均成绩。程序如下:main(){inti;structst{charxm[8];floatcj[9];floattcj,acj;}stu;上一页下一页scan
f(″%s″,stu.xm);/*输入*/for(i=1;i<=8;i++)scan(″%f″,&stu.cj[i]);stu.tcj=0.0;/*求总成绩*/for(i=1;i<=8;i++)stu.
tcj+=stu.cj[i];stu.acj=stu.tcj[i]/8;/*求平均成绩*/printf(″%s总成绩=%6.2f,平均成绩=%6.2f″,stu.tcj,stu.acj);}输入数据:CHEN808679988872966
6运行结果:CHEN的总成绩=577.00,平均成绩=72.13上一页下一页结构体类型数组•结构体数组的定义三种形式:形式一:structstudent{intnum;charname[20];charsex;intage;};structstudents
tu[2];形式二:structstudent{intnum;charname[20];charsex;intage;}stu[2];形式三:struct{intnum;charname[20];charsex;intage;}stu[2];numnamesexagenumnamese
xagestu[0]stu[1]25B上一页下一页结构体数组初始化与引用•结构体数组初始化例struct{intnum;charname[20];charsex;intage;}stu[]={{……},{……},{……}};顺序初始化:structstudent{
intnum;charname[20];charsex;intage;};structstudentstu[]={100,“WangLin”,„M‟,20,101,“LiGang”,„M‟,19,110,“LiuYan”,„F‟,19};例structstudent{intnum;charn
ame[20];charsex;intage;}stu[]={{……},{……},{……}};分行初始化:structstudent{intnum;charname[20];charsex;intage
;};structstudentstu[]={{100,“WangLin”,„M‟,20},{101,“LiGang”,„M‟,19},{110,“LiuYan”,„F‟,19}};全部初始化时维数可省•结构体数组引用引用方式:结构体数组名
[下标].成员名structstudent{intnum;charname[20];charsex;intage;}str[3];stu[1].age++;strcpy(stu[0].name,”ZhaoDa”);上一页下一页例统计候选人选票structperson{charname
[20];intcount;}leader[3]={“Li”,0,“Zhang”,0,”Wang“,0};main(){inti,j;charleader_name[20];for(i=1;i<=10;i+
+){scanf("%s",leader_name);for(j=0;j<3;j++)if(strcmp(leader_name,leader[j].name)==0)leader[j].count++;}for(i=0;i<3;i++)printf("%5s:%d\n",leader[i]
.name,leader[i].count);}namecountLiZhangWang000上一页下一页指向结构体变量的指针•指向结构体变量的指针–定义形式:struct结构体名*结构体指针名;•例structstudent*p;•使用结构体指针变量引用成员形式存放结构体变量在内存的起始地址nu
mnamesexagestupstructstudent{intnum;charname[20];charsex;intage;}stu;structstudent*p=&stu;(*结构体指针名).成员名结构体指针名->成员名结构体变量名.
成员名指向运算符优先级:1结合方向:从左向右例指向结构体的指针变量main(){structstudent{longintnum;charname[20];charsex;floatscore;}stu_1,*
p;p=&stu_1;stu_1.num=89101;strcpy(stu_1.name,"LiLin");p->sex='M';p->score=89.5;printf("\nNo:%ld\nname:%s\nsex:%c\nscore:%f\n",(
*p).num,p->name,stu_1.sex,p->score);}例intn;int*p=&n;*p=10;n=10structstudentstu1;structstudent*p=&stu1;stu1.num=101;(*p).num=101上一页下一页总结:结
构体成员变量引用方式①结构体变量.成员名②(*p).成员名③p->成员名其中,->称为指向运算符•请分析下列几种运算:①p->n②p->n++③++p->n上一页下一页指向结构体数组元素的指针例指向结构体数组的指针structstudent{intnum;charname[20];c
harsex;intage;}stu[3]={{10101,"LiLin",'M',18},{10102,"ZhangFun",'M',19},{10104,"WangMin",'F',20}};main()
{structstudent*p;for(p=stu;p<stu+3;p++)printf("%d%s%c%d\n",p->num,p->name,p->sex,p->age);}numnamesexagestu[0]pstu
[1]stu[2]p+1上一页下一页结构体变量作为函数参数•用结构体变量的成员作参数----值传递•用指向结构体变量或数组的指针作参数----地址传递•用结构体变量作参数----多值传递,效率低上一页下一页structdata{i
nta,b,c;};main(){voidfunc(structdata);structdataarg;arg.a=27;arg.b=3;arg.c=arg.a+arg.b;printf("arg.a=%darg.b=%darg.c=%d\n",arg.a,a
rg.b,arg.c);printf("CallFunc()....\n");func(arg);printf("arg.a=%darg.b=%darg.c=%d\n",arg.a,arg.b,arg.c);}voidfunc(
structdataparm){printf("parm.a=%dparm.b=%dparm.c=%d\n",parm.a,parm.b,parm.c);printf("Process...\n");parm.a=18;parm.b=5;parm.c=parm.a*parm.b;
printf("parm.a=%dparm.b=%dparm.c=%d\n",parm.a,parm.b,parm.c);printf("Return...\n");}例用结构体变量作函数参数上一页下一页structdata
{inta,b,c;};main(){voidfunc(structdata*parm);structdataarg;arg.a=27;arg.b=3;arg.c=arg.a+arg.b;printf("arg.a=%darg
.b=%darg.c=%d\n",arg.a,arg.b,arg.c);printf("CallFunc()....\n");func(&arg);printf("arg.a=%darg.b=%darg.c=%d\n",arg.a,arg.b,arg.c);}
voidfunc(structdata*parm){printf("parm->a=%dparm->b=%dparm->c=%d\n",parm->a,parm->b,parm->c);printf("Process...\n");parm->a=18;parm->b=5
;parm->c=parm->a*parm->b;printf("parm->a=%dparm->b=%dparm->c=%d\n",parm->a,parm->b,parm->c);printf("Return...\n");}例用结构体指针变量作
函数参数上一页下一页结构体变量作为函数参数•总结注意:ANSIC允许用整个结构体作为函数的参数传递,但是必须保证实参与形参的类型相同把一个完整的结构体变量作为参数传递,虽然合法,但要将全部成员值一个一个传递,既费时间又费空间,开销大,因此一般不采用在函数中要结构体中成员变量的值,需
要传结构体指针变量或结构体地址上一页下一页函数的返回值为结构体类型structstudentinput(){/*输入一个学生的数据*/inti;structstudentstud;scanf(″%ld″,&
stud.no);/*输入学号*/gets(stud.name);/*输入学生姓名*/for(i=0;i<3;i++)/*输入学生的3门成绩*/scanf(″%f″,&stud.score[i]);returnstud;/*返回结构体数据*
/}函数的返回值可以是结构体类型。例如,定义了结构体数组:structstudentstud[100];数据输入可由如下形式的语句实现:for(i=0;i<100;i++)stud[i]=input(
);函数input()的功能是输入一个结构体数据,并将输入结构体数据作为返回值,返回给第i个学生记录,实现第i个学生的数据输入上一页下一页链表概述(1)•所谓链表是指若干个数据项(每个数据项称为一个“结点”)按一定的原则连接起来
。每个数据项都包含有若干个数据和一个指向下一个数据项的指针,依靠这些指针将所有的数据项连接成一个链表。上一页下一页链表概述(2)a1a2a3...an^headstructstudentdatanextaistructstudent{longnum;floatscore;sturct
student*next};structstudent*head;上一页下一页1620head李为2004101850586数据项A数据项C刘娜2004102933818数据项B张三2004125950162005863818一个简单链
表示例:上一页下一页内存动态管理函数•动态分配存储–根据需要开辟或释放存储单元•相关函数–malloc函数–calloc函数–free函数•说明–应包含malloc.h或stdlib.h上一页下一页malloc函数•函数原型–typ
edefunsignedsize_t;–void*malloc(size_tsize);•参数–size:分配存储空间的字节数•返回值–若成功,返回指向分配区域起始地址的指针–若失败,返回NULL上一页下一页calloc函数•函数原型–void*calloc(size_tn,size_tsiz
e);•参数–n:分配内存的项目数–size:分配内存的每个项目的字节数•返回值–若成功,返回指向分配区域起始地址的指针–若失败,返回NULL上一页下一页free函数•函数原型–voidfree(void*ptr);•参数–ptr:要释放的内存区地址•说明–释放prt指向的内存区–释放后的内存区能
够分配给其他变量使用上一页下一页realloc函数•函数原型–void*realloc(void*ptr,unsignedintsize)•参数–ptr:需要改变存储空间的内存区地址–size:将ptr所指的存储区的大小改为size个大小•
说明–用来使已分配的空间ptr改变大小,即重新分配上一页下一页链表的基本操作•链表的建立–从链尾到链头:新结点插入到链头–从链头到链尾:新结点插入到链尾•链表的插入操作–根据一定的条件,把新结点插入到指定位置•链表的删除操作–根
据一定的条件,删除一个或多个结点•链表的输出操作•链表的查找操作上一页下一页建立链表操作(从链尾到链头)headai-1...④head=p;②p=malloc(sizeof(structnode));p->data=a[i];①for(i=0;i<n;i++)pai③p->next=head;上
一页下一页建立链表操作(从链头到链尾)ai-1^...④p->next=q;②q=malloc(sizeof(structnode));q->data=a[i];①for(i=0;i<n;i++)ai^q③q->next=NULL;p⑤p=q;上一页下一页链表的
插入操作...aiai+1...④p->next=q;②q=malloc(sizeof(structnode));q->data=x;p①if(p满足插入条件)qx③q->next=p->next;上一页下一页链表的删除操作...ai-1aiai+1...③p->next=q->next;④fr
ee(q);②q=p->next;pq①if(p->next满足删除条件)上一页下一页链表的输出操作...ai-1aiai+1...③p=p->next;p①while(p)②printf("%d",p->data);上一页下一页链表的查找操作
...ai-1aiai+1...③p2=p1;p1=p1->nxet;p1①while(num!=p1->num&&p1!=NULL)②printf(″find:%ld%5.2f\n″,num,p1->score);p2上一页下一页再见!同学们:上一页下一页arga:27b:3c:30(ma
in)(func)parma:27b:3c:30copyarga:27b:3c:30(main)(func)parma:18b:5c:90arga:27b:3c:30(main)arga:27b:3c:30(main)
上一页下一页arga:18b:5c:90(main)arga:27b:3c:30(main)arga:27b:3c:30(main)(func)parm****arga:18b:5c:90(main)(func)parm****