ImageVerifierCode 换一换
格式:PPT , 页数:242 ,大小:707KB ,
文档编号:8095466      下载积分:15 文币
快捷下载
登录下载
邮箱/手机:
温馨提示:
系统将以此处填写的邮箱或者手机号生成账号和密码,方便再次下载。 如填写123,账号和密码都是123。
支付方式: 支付宝    微信支付   
验证码:   换一换

优惠套餐
 

温馨提示:若手机下载失败,请复制以下地址【https://www.163wenku.com/d-8095466.html】到电脑浏览器->登陆(账号密码均为手机号或邮箱;不要扫码登陆)->重新下载(不再收费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录  
下载须知

1: 试题类文档的标题没说有答案,则无答案;主观题也可能无答案。PPT的音视频可能无法播放。 请谨慎下单,一旦售出,概不退换。
2: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
3: 本文为用户(momomo)主动上传,所有收益归该用户。163文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(点击联系客服),我们立即给予删除!。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

1,本文(《C语言与程序设计教程》课件第7章.ppt)为本站会员(momomo)主动上传,163文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。
2,用户下载本文档,所消耗的文币(积分)将全额增加到上传者的账号。
3, 若此文所含内容侵犯了您的版权或隐私,请立即通知163文库(发送邮件至3464097650@qq.com或直接QQ联系客服),我们立即给予删除!

《C语言与程序设计教程》课件第7章.ppt

1、第第7章章 结构体结构体 7.1 结构体类型定义与结构体变量7.2 结构体数组及指向结构体的指针变量7.3 链表 7.4 共用体7.5 典型例题精讲 7.1 结构体类型定义与结构体变量结构体类型定义与结构体变量7.1.1 结构体类型的定义结构体类型的定义在数据的处理中,一组数据往往具有不同的数据类型。例如在学生登记表中,姓名为字符数组型,年龄为整型,性别为字符型,而成绩可为整型或实型;显然不能使用一个数组来存放这组数据,因为数组中各元素的类型必须一致。为了解决这个问题,C语言给出了一种新的构造数据类型结构体类型,它相当于其他高级语言中的记录类型。结构体类型是一种构造类型,即将其他数据类型组合在

2、一起构造成一个结构体类型。因此,结构体类型是由若干成员组成的,每一个成员可有不同的名字及数据类型。与数组类似的是,结构体也是一些相关数据的集合;但与数组不同的是,结构体中各成员的数据类型可以不同。结构体类型既然是一种构造类型,也即C语言并无像int等类型那样事先构造好的结构体类型,因此在使用之前必须先定义结构体类型,然后才可能像int等类型一样,用该结构体类型来定义所需要的结构体变量。一个结构体类型定义的一般形式为:struct 结构体名结构体成员表;其中,struct是关键字,称为结构体定义标识符,结构体名是结构体类型标志,struct与结构体名一起构成了一个新的类型名。花括号“”内的结构体

3、成员表由若干个成员组成,每个成员都是该结构体的一个组成部分,并且对每个成员必须进行类型说明,其形式为:类型标识符 成员名;结构体名和成员名的命名应符合标识符的书写规定。例如,描述学生登记表的结构体类型定义如下:struct studentchar name20;int age;char sex;int math,phys,english;float average;其中,student是一个自定义的结构体名,它与struct一起构成了一个新的类型名(准确地说是一个新的结构体类型名)。此后就可以像使用int、char和float等简单类型名一样使用struct student这一新类型名了,而n

4、ame、age、sex、math、phys、english和average则是该结构体中的成员。在以往的变量定义中,各个变量之间彼此相互独立,没有任何内在的联系。而结构体类型却不同,如上述结构体类型定义就包含着name、age、sex等各项内容,这些内容共同表达了一个学生的有关信息。结构体类型定义时用花括号“”将这些彼此有关的变量(即每一个结构体成员)括起来,表示它们之间存在着联系。所以,结构体类型可以看做是对彼此相关变量的一种定义。结构体类型定义从另一个角度来说类同于表格的描述,表格中的各项都有自己的名字,每项内容都可以归到某种数据类型下。在结构体类型定义中则表现为:表格中的每一项都对应结构

5、体中的一个成员,并且各个成员的数据类型可以不同。结构体类型定义实质上是将一张表格的各项内容转化为结构体成员来描述的,而结构体类型定义中的花括号“”则相当于一张表格的开始和结束。例如,上述结构体类型定义与学生登记表表格的对照如图7-1所示。图7-1 表格与结构体类型定义对照定义结构体类型时应注意以下几点:(1)结构体类型定义与其他变量的定义一样,也是用一条说明语句实现。因此必须用分号“;”标识语句的结束,也就是说结构体类型定义时在花括号“”之后要有分号“;”这一点与复合语句的花括号“”后无分号“;”是不同的。(2)结构体成员可以是任何一种基本数据类型的变量,也可以是指针变量或者像数组这样的构造类

6、型变量。由于结构体成员可以是一个构造类型变量,那么它当然也可以是一个结构体类型变量,从而形成结构体类型的嵌套定义。例如:struct studentchar name20;int age;char sex;struct dateint year,mouth,day;birthday;int math,phys,english;float average;在此,结构体成员birthday变量的类型又属于结构体类型struct date。也可以采用下面的形式进行定义:struct dateint year,mouth,day;struct student char name20;int age;c

7、har sex;struct date birthday;int math,phys,english;float average;(3)结构体类型的定义除指针外不允许递归定义。例如:struct stuchar name10;int score;struct stu a;在结构体类型struct stu的定义中,又定义了一个类型为struct stu的成员a,这种定义方式是错误的。但可以在结构体类型的定义中,用结构体类型来定义一个指向该结构体类型变量的指针变量。例如:struct nodechar ch;struct node*next;在结构体类型struct node的定义中,用结构体类型

8、struct node定义了一个指针变量next(next可以指向类型为struct node类型的变量);这种定义方式是正确的。(4)同一结构体内的各成员名不能相同;在结构体类型嵌套定义中,不同层的成员名可以相同;此外,结构体成员名也可以与普通变量同名。7.1.2 结构体变量结构体变量1.结构体变量的定义定义了一个结构体类型,只是描述了该结构体的组织形式:有几个成员,每个成员具有什么类型。这个结构体类型就象int类型一样,仅表明又多了一种可以使用的数据类型。要注意的是,就如同int是类型不是变量一样,结构体类型本身也不是结构体变量,因此系统并不为结构体类型分配存储空间。只有在依据结构体类型定

9、义了一个结构体变量之后,系统才为这个结构体变量分配存储空间(即为该结构体变量的每一个成员分配对应的存储空间);这样,才能够在程序中使用这个结构体变量。一个结构体变量的定义可以采用下面三种方法:(1)定义了结构体类型后再定义结构体变量。一般形式为:struct 结构体名结构体成员表;struct 结构体名 变量名列表;例如:struct studentchar name20;int age;char sex;float score;struct student stu1,stu2;这里,“struct student”表示类型名,而stu1和stu2则是类型为“struct student”的结

10、构体变量。(2)定义结构体类型的同时定义该类型的结构体变量。一般形式为:struct 结构体名结构体成员表;变量名列表;例如:struct student char name20;int age;char sex;float score;stu1,stu2;(3)缺省结构体名的直接定义结构体变量。一般形式为:struct结构体成员表;变量名列表;例如:struct char name20;int age;char sex;float score;stu1,stu2;第(3)种方法与第(2)种方法的区别在于省去了结构体名,因此也就不存在这个结构体类型的名字。如果需要在程序的其他地方再定义这种结构

11、体类型变量时,则因无结构体类型名而不能定义。而第(1)种和第(2)种方法在程序的任何地方都可以通过结构体类型名struct student去定义新的结构体变量。上述三种方法对结构体变量stu1分配的存储空间分配示意如图7-2所示。图7-2 结构体变量stu1内存分配示意下面嵌套形式结构体类型所定义的变量stu1、stu2,其stu1存储空间分配示意如图7-3所示。struct studentchar name20;int age;char sex;struct int year,mouth,day;birthday;float average;图7-3 嵌套形式下结构体变量stu1内存分配示意

12、2.结构体变量的初始化结构体变量初始化的一般形式为:结构体类型 结构体变量名=初始化值表;初始化值表给出的初始值将依次赋给结构体变量中顺序出现的每一个成员,给出的初始化数据必须与这个数据的成员类型一致,且个数不得多于结构体变量中的成员个数;如果提供的初始值项数少于成员个数,则与数组类似,没有赋值的成员自动初始化为0值。如果定义时没有给结构体变量提供初始值,则系统对结构体变量的处理与普通变量一样,外部和全局变量用0初始化;局部变量不初始化,故其各成员的值不确定。结构体变量的初始化也有如下两种方式:(1)定义结构体类型之后,在进行结构体变量定义时的初始化。例如:struct studentchar

13、 name20;int age;char sex;float score;struct student stu1=Li min,21,M,86(2)在定义结构体类型的同时定义结构体变量并初始化。例如:struct studentchar name20;int age;char sex;float score;stu1=Li min,21,M,86,stu2=Wang fang,20,F,82;3.结构体变量的引用一般情况下,不能将一个结构体变量作为一个整体来引用,而只能引用其中的成员;包括赋值、运算、输入和输出等都是通过结构体变量的成员来实现的。结构体变量中成员引用的一般形式为:结构体变量名.

14、成员名其中,“.”是结构体成员运算符,其优先级最高,结合性自左而右。通过成员运算符“.”就可以像引用简单变量一样引用结构体变量的每一个成员。注意,对结构体变量中的成员,可以像同类型的普通变量那样进行各种运算和操作。对结构体变量成员的引用,不能直接使用成员名,而是采用“由整体到局部”的层次方式,即先指明是哪个结构体变量,然后再通过成员运算符“.”指定某个成员,并且必须逐层找到最低层的成员才能使用。例如:struct student s1,s2;/*假定结构体类型定义同前,在此仅定义结构体变量*/scanf(%s,s1.name);/*输入姓名*/scanf(%f,&s1.score);/*输入成

15、绩*/printf(name=%s,score=%fn,s1.name,s1.score);/*输出姓名和成绩*/我们知道,一般情况下不能整体引用一个结构体变量,而只能引用其中的成员;但下面两种情况下可以对结构体变量赋值:(1)给结构体变量整体赋值。例如:struct student s1=Li min,21,M,86,s2;s2=s1;(2)取结构体变量地址。例如:struct student*p,s1=Li min,21,M,86;p=&s1;注意,结构体变量名是一个地址常量,其含义与数组名相同,但不能对结构体变量做整体运算和输入,输出。例7.1 给结构体变量赋值并输出其值。解 程序如下:

16、#includevoid main()struct studentchar name20;int age;char sex;float score;stu1,stu2;printf(Input name,age,sex,score:n);scanf(%s,%d,%c,%f,stu1.name,&stu1.age,&stu1.sex,&stu1.score);printf(Output:n);printf(name=%s,age=%dn,stu1.name,stu1.age);printf(sex=%c,score=%fn,stu1.sex,stu1.score);运行结果:Input name

17、,age,sex,score:ZhangHua,21,M,85Output:name=ZhangHua,age=21sex=M,score=85.000000例7.2 有以下程序:#includevoid main()struct STUchar name9;char sex;float score2;struct STU a=Zhao,m,85.0,90.0,b=Qian,f,95.0,92.0;b=a;printf(%s,%c,%2.0f,%2.0fn,b.name,b.sex,b.score0,b.score1);程序运行的结果是 。A)Qian,f,95,92 B)Qian,m,85,

18、90C)Zhao,f,95,92 D)Zhao,m,85,90 解 本题定义并初始化了两个STU结构体变量,由于相同类型的结构体变量可以直接整体赋值,因此,执行语句“b=a;”后,结构体变量b的内容已全部是结构体变量a中的内容,最后逐个输出b变量中各成员的值,实际上就是初始化时a的内容,故选D。例7.3 有以下程序:#includestruct Sint n;int a20;void f(int*a,int n);void main()int i;struct S s1=10,2,3,1,6,8,7,5,4,10,9;f(s1.a,s1.n);for(i=0;is1.n;i+)printf(%

19、d,s1.ai);void f(int*a,int n)int i;for(i=0;in-1;i+)ai=ai+i;程序运行的结果是 。A)2,4,3,9,12,12,11,11,18,9,B)3,4,2,7,9,8,6,5,11,10,C)2,3,1,6,8,7,5,4,10,9,D)1,2,3,6,8,7,5,4,10,9,解 程序在调用函数f时,是将结构体变量s中的成员a数组的数组名a(a数组的首地址)传给了函数f的形参指针变量a,即这个形参指针变量a指向a数组的起始地址;同时将s中的另一成员n(其值为10)传给了函数f的另一形参n。函数f的功能是对形参指针变量a所指的数组元素a0an-

20、2分别自增08;即执行函数f后实现了对数组a中的a0a8元素分别自增08,因此结果选A。7.1.3 用用typedef定义类型标识符定义类型标识符在定义结构体变量时,由于定义过于麻烦,所以往往会出现这样的错误,如将“struct student stu1,stu2;”写成:struct stu1,stu2;或者student stu1,stu2;这都是受到形如“int a,b;”这种简单变量定义的影响;能否像简单变量那样定义结构体变量呢?C语言提供了这种方法,即允许用户自己定义新的类型标识符;也就是说,允许由用户为数据类型取“别名”,它是通过类型定义符typedef来实现的。typedef定义

21、的一般形式为:typedef 原类型名 新类型名;使用typedef时应注意以下两点:(1)typedef可以定义新的类型名,但不能用来定义变量。(2)typedef可以对已经存在的类型增加一个新的类型标识符(即同时存在两个类型名)。1.用typedef定义结构体类型标识符用typedef定义结构体类型标识符的方法有两种:(1)重新命名已有的结构体类型标识符。例如:struct studentchar name20;int age;char sex;float score;此时已有结构体类型标识符“struct student”,我们可以将这个类型标识符用typedef重新命名为另一个名字ST

22、U:typedef struct student STU;以后就可以按下面的方法来定义结构体变量stu1、stu2了。STU stu1,stu2;此时已有结构体类型标识符“struct student”,我们可以将这个类型标识符用typedef重新命名为另一个名字STU:typedef struct student STU;以后就可以按下面的方法来定义结构体变量stu1、stu2了。STU stu1,stu2;(2)在结构体类型定义时用typedef指定它的结构体类型名。这种方式的一般形式为:typedef struct结构体成员表;结构体类型名;或者:typedef struct 结构体名结

23、构体成员表;结构体类型名;请注意它与下面结构体类型定义的区别:struct 结构体名结构体成员表;变量名列表;即typedef开头定义的结构体类型中,其花括号“”后面是结构体类型名而不是结构体变量名,这一点要尤其注意。例如:typedef struct char name20;int age;char sex;float score;STU;STU stu1,stu2;由此例可以看出,以typedef开头的结构作类型定义中,STU是结构体类型名,因此可以用STU直接定义结构体变量stu1和stu2了。2.typedef与#define在定义结构体类型时的区别我们也可以用宏定义“#define”

24、(在第9章介绍)使用一个符号常量来表示一个结构体类型。例如:#define STU struct studentSTUchar name20;int age;char sex;float score;STU stu1,stu2;从形式上看,#define与typedef很相似,但是两者是有区别的。#define只能作简单的字符串替换,即将字符串“struct student”换成字符串“STU”,而不管struct student的含义如何,即“struct student”可以是一个常量名、变量名、类型标识符等都可以。而typedef的功能则是给已经存在的类型标识符起一个新的名字。此外,宏定

25、义是由预处理完成的;而typedef则是在编译时完成的,它更为灵活方便。例7.4 下面结构体类型及结构体变量定义中正确的是 。解 选项B的错误一是在“struct REC”中应去掉分号“;”,其二是在“REC t1,t2;”前加上struct即可。选项C的错误之一是在结构体类型定义中不能给成员赋初值,给成员赋初值只是针对结构体变量的;错误之二是在“struct”之前有“typedef”,因此“”后出现的只能是一个结构体类型名,而题中“”后的“t1,t2”其本意应是变量名,所以是错误的。选项D的错误是REC是一个结构体变量而不是结构体类型名,D正确的写法应为:structint n;char c

26、;t1,t2;选项A中的REC为结构体类型名,因此是正确的,故选择A。例7.5 有以下程序:#include#includetypedef structchar name9;char sex;float score2;STU;void f(STU a);void main()STU c=Qian,f,95.0,92.0;f(c);printf(%s,%c,%2.0f,%2.0fn,c.name,c.sex,c.score0,c.score1);void f(STU a)STU b=Zhao,m,85.0,90.0;int i;strcpy(a.name,b.name);a.sex=b.sex;

27、for(i=0;i2;i+)a.scorei=b.scorei;程序的运行结果是 。A)Qian,f,95,92 B)Qian,m,85,90 C)Zhao,f,95,92 D)Zhao,m,85,90解 本题采用了typedef定义方式定义了一个结构体类型,请注意“STU”是结构体类型名而不是变量名,由于函数f调用时是将结构体变量c整体传给了结构体形参a,此后a与c就再无关系了,也即a内容的改变都不会影响到实参c,所以最终输出c的内容与初始化时的a相同,故选择A。7.2 结构体数组及指向结构体的指针变量结构体数组及指向结构体的指针变量 7.2.1 结构体数组结构体数组我们已经知道,可以用一个

28、结构体变量来描述一个学生登记表,但如果是一个班级的学生呢?由于每个学生都有同样的一张表格,因此必须采用数组的方式,即数组元素必须是结构体类型的变量(每个数组元素构成一张登记表),且每个数组元素的类型都相同(都是同样的表格);这样,就构成了结构体数组(整个结构体数组构成了全班的登记表)。结构体数组的每一个元素都是具有相同结构体类型的结构体变量,其构造方法与结构体变量相似,只需说明它为数组类型即可。因此,结构体数组既有结构体的特点,又有数组的特点:(1)结构体数组元素由下标标识,每个数组元素都是一个同类型的结构体变量。(2)结构体数组元素通过成员运算符“.”引用数组元素中的每一个成员。结构体数组的

29、定义方法和结构体变量相似,也有三种方式:(1)定义了结构体类型后再定义结构体数组。例如:struct studentchar name20;int age;char sex;float score;struct student stu50;即定义了一个结构体数组stu,共有50个元素stu0stu49,每个数组元素都具有struct student类型。(2)在定义结构体类型时同时定义结构体数组。例如:struct studentchar name20;int age;char sex;float score;stu50;(3)缺省结构体名,直接定义结构体数组。例如:struct char n

30、ame20;int age;char sex;float score;stu50;在定义了一个结构体数组后,系统就在内存为其开辟一个连续的存储区来存放它的每一个元素,结构体数组名就是这个存储区的起始地址;并且数组元素在内存中的存放仍然按顺序排列,所不同的是每一个元素所占用的内存大小是一个结构体类型数据存放空间的大小。对结构体数组中元素的操作与普通数组元素类似:(1)将一个数组元素赋给另一个数组元素,从而实现结构体变量之间的整体赋值。例如:stu1=stu10;(2)将一个结构体数组元素中的某个成员赋给另一个数组元素中同一类型的成员。例如:stu1.score=stu10.score;结构体数组

31、的初始化也有如下两种形式:(1)定义结构体类型之后,在定义结构体数组时进行初始化。struct结构体名结构体成员表;struct 结构体名 数组名大小=初值表;(2)在定义结构体类型的同时定义结构体数组并初始化。struct结构体名 结构体成员表;数组名大小=初值表;例7.6 下面程序中函数fun的功能是:统计person所对应的结构体数组中所有性别(sex)为M的数组元素个数,将其存入变量n中并作为函数值返回。请填空。#includestruct ssint num;char name10;char sex;int fun(struct ss person);void main()int n

32、;struct ss w3=1,AA,F,2,BB,M,3,CC,M;n=fun(w);printf(n=%dn,n);int fun(struct ss person)int i,n=0;for(i=0;i3;i+)if(_=M)n+;return n;解 由第6章可知,数组名作为实参去调用被调函数时,是把实参数组w的首地址传给形参数组名person,使形参数组名指向实参数组w,所有对形参数组person的操作实际上都是对实参数组w进行的。在此,由于实参数组w是结构体数组,所以必须通过成员运算符“.”来引用数组元素中的各个成员。根据题目要求“统计性别(sex)为M的数组元素个数”,所以应通过

33、for循环来遍历结构体数组中的每一个数组元素,并判断该元素中的sex成员是否为M。由此可见,空缺处应填入“当前数组元素的sex成员”,也即填入:personi.sex。例7.7 输入某班30个同学的姓名、数学和英语成绩,计算并输出每位同学的平均成绩。解 程序如下:#includestruct studentchar name10;int math,english;float aver;void main()struct student s30;/*定义结构体数组s*/int i;for(i=0;i30;i+)printf(Input No.%d name math englishn,i+1);

34、scanf(%s%d%d,si.name,&si.math,&si.english);si.aver=(si.math+si.english)/2.0;printf(Output:n);for(i=0;i成员名二者完全等价。例如:(*p).sex或者p-sex要注意“(*p)”两侧的圆括号“()”不可少,因为成员运算符“.”的优先级高于“*”。如果去掉园括号“()”而写成“*p.sex”,则因相当于“*(p.sex)”而必然出错了。此外,还要注意引用一般结构体变量中的成员只能采用“结构体变量.成员名”和“指针变量-成员名”这两种方式。例7.8 分析下面程序的运行结果。#includestruc

35、t studentchar name10;char sex;float score;stu1=Zhang,M,81.5;void main()struct student*p=&stu1;printf(Name=%s,sex=%c,score=%fn,stu1.name,stu1.sex,stu1.score);printf(Name=%s,sex=%c,score=%fn,(*p).name,(*p).sex,(*p).score);printf(Name=%s,sex=%c,score=%fn,p-name,p-sex,p-score);运行结果:Name=Zhang,sex=M,scor

36、e=81.500000Name=Zhang,sex=M,score=81.500000Name=Zhang,sex=M,score=81.500000解 本程序定义了一个结构体类型struct student,同时定义了该类型的结构体变量stu1并进行了初始化赋值。在main函数中,定义了struct student类型的结构体指针变量p并被赋以stu1的地址,因此p指向结构体变量stu1;然后在printf语句中以三种形式输出stu1各成员的值。也即,程序的运行结果是分三行输出stu1各成员的值,也就是初始化时的内容。2.指向结构体数组的指针变量结构体指针变量还可以用来指向结构体数组或结构体

37、数组中的元素。由于在结构体数组中,一个数组元素其实就是一个结构体变量;因此,上面用于指向结构体变量的概念和方法都适用于结构体数组或结构体数组中的元素。并且,与前面所介绍的指向数组的指针变量方法相同,结构体指针变量加1将指向结构体数组中相继的下一个数组元素。例7.9 有以下程序:#includestruct Sint n;int a20;void f(struct S*p);void main()int i;struct S m=10,2,3,1,6,8,7,5,4,10,9;f(&m);for(i=0;im.n;i+)printf(%d,m.ai);void f(struct S*p)int

38、i,j,t;for(i=0;in-1;i+)for(j=i+1;jn;j+)if(p-aip-aj)t=p-ai;p-ai=p-aj;p-aj=t;程序运行后的输出结果是:。A)1,2,3,4,5,6,7,8,9,10,B)10,9,8,7,6,5,4,3,2,1,C)2,3,4,6,8,7,5,4,10,9,D)10,9,8,7,6,1,2,3,4,5,解 在程序中,函数f中的形参p是一个结构体指针变量,它接受实参结构体变量m的地址,即指向结构体变量m;所有对p所指结构体变量中成员的操作都是对结构体变量m中成员的操作。而函数f的功能可以很容易的看出是冒泡排序,即最终实现对p所指成员a数组由小

39、到大的排序。因此,最终结果应选A。对于自增和自减运算,我们是将i+的“+”操作看做运算级别最低的操作,而将+i的“+”操作看做运算级别最高的操作。将这种自增和自减运算的概念应用于结构体指针变量p所指向的结构体变量中成员p-n,则有:(1)p-n+引用p指向的结构体变量中成员n的值,然后使n增1。(2)(p+)-n 引用p指向的结构体变量中成员n的值,然后使p增1。(3)+p-n 使p指向的结构体变量中成员n的值先增1,然后再引用n值。(4)(+p)-n 使p的值先增1,然后再引用p指向的结构体变量中成员n的值。例7.10 给出下面程序的运行结果。#includevoid main()struc

40、t spint a;int*b;*p;int d3=10,20,30;struct sp t3=70,&d0,80,&d1,90,&d2;p=t;printf(%d,%dn,+(p-a),*+p-b);解(1)printf语句中的输出表达式是由右向左进行计算,然后由左向左顺序输出。(2)+p-b是给指针变量b加1(即b由指向d0改为指向d1),而不是给p加1(即认为p由指向t0改为指向t1是错误的)。因此,+p-b指向d1,即*+p-b的值为20。(3)由于p仍指向t0,故p-a的值为70,而+(p-a)的值即为:71。分析示意见图7-4,程序输出结果为:71,20。图7-4 程序执行分析示意

41、7.3 链表链表 7.3.1 链表的概念链表的概念如果结构体指针变量所指的结构体变量中,除了存储数据的成员外,还有一个成员作为指针变量来指向下一个具有同样结构体类型的结构体变量,而这下一个结构体变量中的成员指针变量又继续再指向另一个同样结构体类型的结构体变量;就好像一条链一样,形成了一种我们称之为“链表”的数据结构。由于链表中的每一个成员(称为结点)至少要包含数据和指针(变量)这两种不同类型的信息,所以链表中的每个结点只能是一个结构体变量。下面的程序就是一个链表的例子:#includestruct node int x;struct node*t;*p;struct node a4=20,a+

42、1,15,a+2,30,a+3,17,0;void main()int i;p=a;for(i=1;ix);p=p-t;printf(n);程序的执行结果如下:20 15 30 17结构体数组a的存储示意如图7-5所示。图7-5 数组a存储示意程序执行的过程是:首先通过语句“p=a;”使指针变量p指向链表的第一个结点a0,然后由语句“printf(%4d,p-x);”输出a0中成员x的值20;接着由语句“p=p-t;”取出a0中的成员t值“a+1”(即a1的地址)赋给p,此时p的指针值移至链表的第二个结点a1处;然后继续重复上面的输出和移动p的指针值过程,直到第四个结点a3的成员x值17输出为

43、止。由程序可知,链表结点的类型可以如下定义:struct nodeint data;struct node*next;即在“struct node”类型中,除了数据成员data外,还要有一个指针成员*next并且它所指的变量类型也是“struct node”这种结构体类型。一般链表结点中的成员与上面的定义大致相同,只不过数据成员或指针成员可能有多个。由图7-5可知,一个链表必须具备以下几点:(1)一个用于指示链表第一个成分的头指针变量,简称头指针(在此,数组名a兼做头指针);(2)每个链表结点的成员中要有能够指向后继链表结点的指针成员;(3)最后的链表结点要有表示链表结束的标志,即其指针成员的

44、值为NULL(在不知道链表结点个数的情况下就不能采用上述程序中i值由14的控制方式了)。为了能够访问链表,就得有一个指针变量(称为头指针)始终指向链表的第一个结点,否则将无法找到这个链表。链表还要有结束的标志,以便作为查找或遍历链表的结束条件。链表也可以为空,头指针的值为NULL(NULL又可以表示为0或0)时表示一个空链表。7.3.2 动态存储分配动态存储分配实际使用的链表是一种动态链表。所谓动态链表是指在程序执行过程中从无到有建立起一个链表来,也就是一个一个的创建(动态生成)链表结点,创建的同时给结点的数据成员输入数据并使指针成员建立起结点间的链接关系。如何动态地创建和回收一个链表结点呢?

45、C语言提供了以下三种库函数:1)malloc函数(分配内存空间函数)一般调用形式为:(类型标识符*)malloc(size)其功能是:在内存的动态存储区中分配一块长度为size字节的连续内存单元,然后函数返回指向所分配区域的起始地址;类型标识符表示该连续内存单元是用于何种数据类型的,而“(类型标识符*)”则表示把返回的起始地址值强制转换为指向类型标识符这种数据类型的指针值;size是一个无符号数。例如:int*p;p=(int*)malloc(sizeof(int);即“sizeof(int)”表示按int类型数据的存储字节数分配一块连续的内存单元,也即生成一个动态整型变量(由于是动态生成的,

46、所以没有名字),并将该内存单元的首地址通过“(int*)”强制转换为指向int类型的指针值并赋给指针变量p(p所指的数据类型必须是整型),此时指针变量p就指向这个动态变量。2)calloc函数(分配内存空间函数)用于分配连续的nsize个字节空间,主要用于动态数组,calloc的使用已在6.5节中介绍过。3)free函数(回收内存空间函数)一般调用形式为:free(void*ptr);其功能是:释放并回收指针变量ptr所指向的内存空间,free的使用也已在6.5节中介绍过。例如:int*p;p=(int*)malloc(sizeof(int);free(p);执行“free(p);”语句就将刚

47、分配的一块大小为int类型数据长度的内存空间(由指针变量p所指向)收回。使用上述库函数要注意,上述函数的原形在“stdlib.h”和“malloc.h”中定义,因此在程序中必须包括这两个头文件中的一个。例7.11 分配一块内存区域并输入一个学生有关数据,然后将输入的数据输出。解 程序如下:#include#include#includevoid main()struct stuchar name15;int age;char sex;float score;*p;p=(struct stu*)malloc(sizeof(struct stu);strcpy(p-name,Zhang ming)

48、;p-age=21;p-sex=M;p-score=98;printf(Name=%snAge=%dn,p-name,p-age);printf(Sex=%cnScore=%fn,p-sex,p-score);free(p);运行结果:Name=Zhang mingAge=21Sex=MScore=98.0000007.3.3 动态链表的建立与查找动态链表的建立与查找我们以下面的结构体类型为例,来介绍动态链表的建立与查找方法。struct nodeint data;struct node*next;*head,*p,*q;1.链表的建立通常需要三个指针变量来完成一个链表的建立。例如,我们用指针

49、变量head指向链表的第一个结点(表头结点),指针变量q指向链表的链尾结点,指针变量p则指向新产生的链表结点。并且,新产生的链表结点*p总是插入到链尾结点*q的后面而成为新的链尾结点。因此,插入结束时要使指针变量q指向这个新的链尾结点(即q始终指向链尾结点)。链表建立的过程如下:(1)表头结点的建立p=(struct node*)malloc(sizeof(struct node);/*动态申请一个结点存储空间*/scanf(%d,p-data);/*给结点中的数据成员输入数据*/p-next=NULL;/*置链尾结点标志*/head=p;/*第一个产生的链表结点即为头结点*/q=p;/*第一

50、个产生的链表结点同时也是链尾结点*/(2)其他链表结点的建立p=(struct node*)malloc(sizeof(struct node);/*动态申请一个结点存储空间*/scanf(%d,p-data);/*给结点中的数据成员输入数据*/p-next=NULL;/*置链尾结点标志*/q-next=p;/*将这个新结点链接到原链尾结点的后面*/q=p;/*使指针变量q指向这个新的链尾结点*/由于指针变量head总是指向链表的表头结点(第一个链表结点),所以表头结点的建立过程与其他链表结点的建立是有区别的;另外,新产生的链表结点*p同时又是链尾结点,故除了给结点*p的数据成员赋值之外,还应

侵权处理QQ:3464097650--上传资料QQ:3464097650

【声明】本站为“文档C2C交易模式”,即用户上传的文档直接卖给(下载)用户,本站只是网络空间服务平台,本站所有原创文档下载所得归上传人所有,如您发现上传作品侵犯了您的版权,请立刻联系我们并提供证据,我们将在3个工作日内予以改正。


163文库-Www.163Wenku.Com |网站地图|