C语言程序设计ppt-第10章-02.ppt

上传人:本田雅阁 文档编号:3479494 上传时间:2019-09-01 格式:PPT 页数:78 大小:170.02KB
返回 下载 相关 举报
C语言程序设计ppt-第10章-02.ppt_第1页
第1页 / 共78页
C语言程序设计ppt-第10章-02.ppt_第2页
第2页 / 共78页
C语言程序设计ppt-第10章-02.ppt_第3页
第3页 / 共78页
C语言程序设计ppt-第10章-02.ppt_第4页
第4页 / 共78页
C语言程序设计ppt-第10章-02.ppt_第5页
第5页 / 共78页
点击查看更多>>
资源描述

《C语言程序设计ppt-第10章-02.ppt》由会员分享,可在线阅读,更多相关《C语言程序设计ppt-第10章-02.ppt(78页珍藏版)》请在三一文库上搜索。

1、2019/9/1,华中科技大学计算机学院,1,C语言程序设计,The C Programming Language,华中科技大学计算机学院 曹计昌,2019/9/1,华中科技大学计算机学院,2,*10.7 联 合 10.7.1 联合类型的定义,与结构类似,联合类型也是一种构造类型。一个联合类型中包含有多个成员,这些成员共享共同的存储区域,但这些成员并不同时存在;联合存储区域的大小由各个成员中所占字节数最大的成员决定;在任何时刻,各个成员中只能有一个成员拥有该存储。 除了用关键字union取代struct之外,联合类型的定义、联合变量的声明、以及联合成员的引用在语法上与结构完全相同。,2019/

2、9/1,华中科技大学计算机学院,3,如果有3个不同数据类型(char, short, long )的变量要分时共用一个共同的存储区域,则可以定义如下的联合类型:,union chl char c; short h; long l; ; 这里chl是所定义的联合类型的联合名(tag) , 它与union一起形成一个union chl的联合类型。c、h、l是联合类型的成员。,2019/9/1,华中科技大学计算机学院,4,10.7.2 联合变量的声明、初始化及联合成员的引用,定义了union chl的联合类型后,可以通过: union chl u; 来声明一个union chl类型的变量。 也可以在

3、定义union chl联合类型的同时来声明相应的联合变量。如: union chl char c; short h; long l; v=9; 它在定义union chl联合类型的同时声明了联合类型的变量v,并且对其进行了初始化。 在不产生二义的情况下,往往简称联合类型的变量为联合。,2019/9/1,华中科技大学计算机学院,5,联合变量的声明、初始化,值得注意的是,联合变量的初始化与结构的初始化在形式上相同,都应该用花括号界定初值,但联合是一种特殊形式的构造类型的数据,在同一时刻它只拥有其中的一个成员。 因此,初始化时只能对联合的第1个成员进行初始化。换言之,初值表中只能包含与第1个成员数据

4、类型相同的一个初值。 如上面例子中的v=9。也可以: union chl v=9,w=a;,2019/9/1,华中科技大学计算机学院,6,例10.12 通过例子对联合的特性进行进一步分析。,#include “stdio.h“ union chl char c; short h; long l; ; void show(union chl *pu); void show_memoy(union chl *pu);,2019/9/1,华中科技大学计算机学院,7,void main(void) union chl u; printf(“size of u is %dn“,sizeof(u); u.

5、l=0x31323334L; show( ,2019/9/1,华中科技大学计算机学院,8,void show(union chl *pu) printf(“char format: %cn“,(*pu).c); printf(“int format: %hxn“,pu-h); printf(“long format: %lxn“,(*pu).l); void show_memoy(union chl *pu) char *p=(char *)pu; int i=0; while(i4) printf(“addr %dth byte of u is 0x%pt“,i,p+i); printf(“

6、the ASCII in %dth byte of u is %cn“,i,*(p+i); i+; ,2019/9/1,华中科技大学计算机学院,9,程序的运行结果如下: size of u is 4 char format: 4 int format: 3334 long format: 31323334 addr 0th byte of u is 0xFFD8 the ASCII in 0th byte of u is 4 addr 1th byte of u is 0xFFD9 the ASCII in 1th byte of u is 3 addr 2th byte of u is 0x

7、FFDA the ASCII in 2th byte of u is 2 addr 3th byte of u is 0xFFDB the ASCII in 3th byte of u is 1 char format: 8 int format: 3638 long format: 31323638 addr 0th byte of u is 0xFFD8 the ASCII in 0th byte of u is 8 addr 1th byte of u is 0xFFD9 the ASCII in 1th byte of u is 6 addr 2th byte of u is 0xFF

8、DA the ASCII in 2th byte of u is 2 addr 3th byte of u is 0xFFDB the ASCII in 3th byte of u is 1,2019/9/1,华中科技大学计算机学院,10,对程序和程序的运行结果可以做如下分析: 1) 联合的存储结构 从sizeof(u)的结果为4可以看出,联合u所占存储的大小为4个字节,这正好是长整型成员l所占存储的大小。这4个字节的存储是连续的,地址从0xFFD8至0xFFDB。u.l 的值为0x31323334L,u的存储描述为:,2019/9/1,华中科技大学计算机学院,11,2) 联合的指针,可以声明

9、联合类型的指针。如: union chl v,*pv= 说明了一个union chl类型的指针pv,并且取出v地址对pv进行初始化,使联合指针pv指向了联合变量v。 值得注意的是,联合所有成员的地址和联合变量的地址都是相同的。因为所有成员都是从同一存储空间的边界(低地址)开始存放。 但是,不同成员指针值(地址值)的类型是不相同的。因此,&u,&u.c,&u.h,&u.l的地址都相同。但&u的数据类型是union chl *。&u.c的数据类型是char *。&u.h的数据类型是int short *。&u.l的数据类型是long int *。,2019/9/1,华中科技大学计算机学院,12,3

10、) 联合成员的引用,可以通过联合变量和“.”操作符,以及指向联合变量的指针和“-”操作符来引用联合成员。从u.l,(*pu).c,pu-h三个表达式中可以归纳出对联合成员的引用形式为: (1)联合变量名.成员名。 (2)(*指向联合变量的指针).成员名。 (3)指向联合变量的指针-成员名。 例如:u.c 或(*pu).c 或pu-c 都表示引用联合成员c,类型是char。 u.h 或(*pu).h 或pu-h 都表示引用联合成员h,类型是short。 u.l 或(*pu).l 或pu-l 都表示引用联合成员c,类型是long。 而u.c=a,(*pu).h=0x3839,以及pu-l=0x31

11、323334L分别表示对联合u的成员c、h、l的赋值操作。,2019/9/1,华中科技大学计算机学院,13,4) 共享存储的特点,在main函数中,u.l=0x31323334L;赋值语句产生的存储可由表10-3描述,各字节的地址由高向低,依次存放0x31、0x32、0x33、0x34,联合u由成员l使用。 由show函数和相应的运行结果可以看出,此时如果按照(*pu).c解释,输出的只是共享存储的低字节的内容0x34或字符4。如果按照,pu-h解释,输出的只是共享存储的低端2个字节的内容0x33和0x34。 执行u.h=0x3638;语句之后,联合u由成员h使用。该语句修改了共享存储低端2个

12、字节的内容,但是高端2个字节的内容没有变化。,2019/9/1,华中科技大学计算机学院,14,5) 相容性操作,联合中允许存储不同类型的数据,对某个时刻存储的数据,其所允许的操作也有所不同,有些操作对该类型的数据是相容的,但有些操作却不相容(得不到正确结果)。 由于语法上合法,编译器对这种情况不会报错,但运算的结果却不正确。 假如在union chl中增加一个成员(其它都不变),如:float f;则在show函数中,如果执行语句为: printf(“float format: %fn“,pu-f); 则得到是不正确的结果0.00,而其他语句中操作却是相容的。,2019/9/1,华中科技大学计

13、算机学院,15,*10.8 字段结构,由多个相邻的二进制位可以组成结构或者联合中的整型或无符号整型成员,这些个相邻的二进制位被称为字段(bit field),对应的成员称为结构或联合的字段成员,以字段为成员的结构称为字段结构。 组成字段的二进制位的数目成为该字段的宽度,它是一个非负的整型常量表达式。 字段结构在操作系统,编译程序,嵌入式系统的C语言编程方面使用较多。 例如,stdio.h中关于文件状态成员flags的取值就规定了1为读状态,2为写状态,4为缓冲数据状态等等。这些数据都是一些值很小的整数,没有必要用int或char变量来存储每一个值。 通常对若干个特征中的每个特征按照取值的大小分

14、配合适的二进制位,然后将它们组织成为字段封装到一个int或char变量中。这样就可以通过字段名对相应的二进制位或位串进行操作,而不必采用前面章节介绍的位运算。,2019/9/1,华中科技大学计算机学院,16,10.8.1 字段结构类型的定义,字段结构也属于构造类型,因此要先定义字段结构类型,再声明字段结构变量,然后再对字段结构变量中的成员进行操作。 考虑十字路口的交通灯 .颜色枚举类型的声明如下: enum color OFF=0,RED=1,YELLOW=2,GREEN=3;,2019/9/1,华中科技大学计算机学院,17,struct traffic_light unsigned shor

15、t int east:2; /* 东组灯状态字段 */ unsigned short int south:2; /* 南组灯状态字段 */ unsigned short int west:2; /* 西组灯状态字段 */ unsigned short int north:2; /* 北组灯状态字段 */ unsigned short int reserve:8; /* 保留字段 */ unsigned short int east_on:4; /* 东组灯开通时间 */ unsigned short int south_on:4;/* 南组灯开通时间 */ unsigned short int

16、 west_on:4;/* 西组灯开通时间 */ unsigned short int north_on:4;/* 北组灯开通时间 */ ;,4组交通灯的字段结构类型的声明,2019/9/1,华中科技大学计算机学院,18,4组交通灯的字段结构类型的简略形式声明,struct traffic_light unsigned short int east:2,south:2,west:2,north:2,reserve:8; unsigned short int east_on:4,south_on:4,west_on:4,north_on:4; ; 上面声明了一个struct traffic_li

17、ght的字段结构类型,east、south、north_on为它的字段成员,字段成员往往也简称为字段。 冒号后面的整数说明了成员的字段宽度,字段宽度是一个非负的整型常量表达式。 上面定义中,其中字段宽度为2的四个成员用unsigned char更加简练,但Turbo C中不支持unsigned char,因此用unsigned short int。,2019/9/1,华中科技大学计算机学院,19,10.8.2 字段结构类型变量的声明及成员的引用,可以先定义字段结构类型,再声明字段结构类型的变量。如: struct traffic_light Jiedaokou; 它声明了struct traf

18、fic_light的字段结构类型变量Jiedaokou。 同时,还可以在声明字段结构类型的变量的同时对其进行初始化。如: struct traffic_light Jiedaokou=0,0,0,0,0,0,0,0,0; 它将east、north_on这9个字段成员都初始化为0。,2019/9/1,华中科技大学计算机学院,20,也可以在定义字段结构类型的同时声明字段结构变量并对其成员进行初始化。如:,struct traffic_light unsigned short int east:2,south:2,west:2,north:2,reserve:8; unsigned short in

19、t east_on:4,south_on:4,west_on:4,north_on:4; Jiedaokou=0,0,0,0,0,0,0,0,0,*p= 字段就是一个小整数,它可以出现在其它整数可以出现的任何地方。字段在参与运算时被自动转换为int或unsigned int类型的整数。 对一个字段结构中成员的引用与对一般结构变量中结构成员的引用方法相同,有“.”和“-”两种。如: Jiedaokou.west,Jiedaokou.west_on, p-north,p-north_on等。,2019/9/1,华中科技大学计算机学院,21,例10.13 字段结构变量的成员引用举例。,void ma

20、in(void) struct traffic_light Jiedaokou=0,0,0,0,0,0,0,0,0; Jiedaokou.west=GREEN;Jiedaokou.west_on=5; printf(“Jiedaokou.west=%ut“,Jiedaokou.west); printf(“Jiedaokou.west_on=%un“,Jiedaokou.west_on); printf(“Jiedaokou.east=%ut“,Jiedaokou.east); printf(“Jiedaokou.east_on=%un“,Jiedaokou.east_on); 程序的运行结果

21、如下: Jiedaokou.west=3 Jiedaokou.west_on=5 Jiedaokou.east=0 Jiedaokou.east_on=0,2019/9/1,华中科技大学计算机学院,22,字段成员的宽度问题,由于字段成员表示整数的范围有限,在对字段成员赋值时不要超出了它表示数的范围。如果超出了它表示数的范围,则数的高位部分将被丢弃。 如Jiedaokou.west_on的宽度为4,它能够表示数的范围是015。如果执行Jiedaokou.west_on=17(即0x11 或00010001B),编译时不会报错, 如果再执行: printf(“Jiedaokou.west_on=%

22、un“,Jiedaokou.west_on); 其输出为1。高位“1”被丢弃。,2019/9/1,华中科技大学计算机学院,23,可以通过指向字段结构变量的指针来操纵字段结构变量的成员。,如: struct traffic_light Jiedaokou=0,0,0,0,0,0,0,0,0,*p=,2019/9/1,华中科技大学计算机学院,24,10.8.3 字段结构与联合的应用,本节通过一个例子说明如何访问一个16位字中的高低字节和各二进制位。 例子中将字段byte0和byte1的宽度定义为8,用以表示一个16位字中的高字节和低字节; 将字段b0b15宽度定义为1,用以表示一个16位字中的各个

23、二进制位。 并且用联合使一个短整型变量、2个字节字段与16个位字段共享共同的存储。,2019/9/1,华中科技大学计算机学院,25,例10.14 用字段和联合访问一个16位字中的高低字节和各二进制位的应用举例。,#include “stdio.h“ #define CHAR_BIT 8 struct w16_bytes unsigned short byte0:8,byte1:8; /* byte0为低字节,byte1为高字节 */ ; struct w16_bits unsigned short b0:1,b1:1,b2:1,b3:1,b4:1,b5:1,b6:1,b7:1, b8:1,b9

24、:1,b10:1,b11:1,b12:1,b13:1,b14:1,b15:1; ;,2019/9/1,华中科技大学计算机学院,26,union w16 /* 短整型变量、结构成员byte、结构成员bit共享共同的存储 */ short i; struct w16_bytes byte; struct w16_bits bit; ; void main(void) union w16 w=0;/* i为0;byte0和byte1也为0;b0至b15皆为0 */ void bit_print(short); w.bit.b9=1; /* 相当于byte1为2 */ w.bit.b10=1; /*

25、相当于byte1为6 */ w.byte.byte0=b; printf(“w.i=0x%xn“,w.i); /* 按整型解释、输出共享存储的内容 */ bit_print(w.i); /* 从高到低,逐位输出共享存储的各bit值 */ ,2019/9/1,华中科技大学计算机学院,27,void bit_print(short num) int i,shift=sizeof(short)*CHAR_BIT; int mask=1(shift-1); /* 掩码mask的最高位为1,其余15位为0* / for(i=1;i=shift;i+) putchar(num ,2019/9/1,华中科技

26、大学计算机学院,28,程序中mask最高位为1,其余15位为0,通常称为掩码,将它与短整型变量作按位与运算用以测试短整型变量的最高位是0还是1。 在bit_print函数中的for循环中,每循环一次,通过num=1将次高位移至最高位。w.bit.b9=1和w.bit.b10=1将i的高字节设成6,w.byte.byte0=b将i的低字节设成62(b的ASCII码)。 bit_print函数将num在内存中的值以二进制位的方式输出。 程序的运行结果如下: w.i=0x662 00000110 01100010,2019/9/1,华中科技大学计算机学院,29,*10.9 动态存储分配 10.9.1

27、 静态数据结构和动态数据结构,到目前为止,教材中介绍的各种基本类型和导出类型的数据结构都是静态数据结构。 静态数据结构指在变量声明时建立的数据结构。在变量声明时变量的存储分配也确定了,并且在程序的执行过程中不能改变。 动态数据结构是在程序运行过程中通过调用系统提供的动态存储分配函数,向系统申请存储而逐步建立起来的。在程序运行过程中,动态数据结构所占存储的大小可以根据需要调节,使用完毕时可以通过释放操作将所获得的存储交还给系统供再次分配。 由于系统提供的动态存储分配函数的返回值是指向分配存储的起始地址的指针,因此动态数据对象没有名字,对动态数据对象的访问只能通过指针进行。,2019/9/1,华中

28、科技大学计算机学院,30,10.9.2 C的动态存储分配函数,动态存储分配函数是C的标准函数,函数的原型声明在头文件中给出。 使用动态存储分配函数必须先使用#include 编译预处理命令。 C提供下列与动态存储分配相关的函数。 void * malloc(size_t size); void * calloc(size_t n, size_t size); void * realloc(void * p_block, size_t size); void free(void * p_block); 其中,size_t表示unsigned int,即无符号整型。它是在中通过typedef un

29、signed size_t;定义的。,2019/9/1,华中科技大学计算机学院,31,1) malloc函数的功能,malloc函数的原型为: void * malloc(size_t size); malloc函数的功能是向系统申请分配size个字节大小的存储。如果分配成功,返回新分配存储区域的首地址;如果分配失败(如内存容量不够),返回NULL。新分配存储区域未被初始化。 例如,下面的代码片断就利用了malloc函数动态创建一个有6个元素的整型数组。 int i,*p; p=(int *)malloc(6*sizeof(int); if(p) for(i=0;i6;i+) pi=i; el

30、se printf(“dynamic alloc failed!“);exit(-1);,2019/9/1,华中科技大学计算机学院,32,2) calloc函数的功能,calloc函数的原型为: void * calloc(size_t n, size_t size); calloc函数的功能是向系统申请分配n项,每项的大小为size个字节的存储。如果分配成功,返回新分配存储区域的首地址;如果分配失败,则返回NULL。新分配存储区域均被初始化为0。 例如,语句p=(int *)malloc(6*sizeof(int);可以用calloc函数实现为: p=(int *)calloc(6,size

31、of(int); 它向系统申请6个整型数据项,每个整型数据项的大小是sizeof(int)的存储区域。 值得注意的是:所分配的内存存储区域是连续的。所以,当指针p指向新分配存储区域的首地址后,可以用pi表示引用新分配存储区域中的第i个数据项。,2019/9/1,华中科技大学计算机学院,33,3) realloc函数的功能,realloc函数的原型为: void * realloc(void *p_block, size_t size); realloc函数的功能是对指针p_block所指向的已经动态分配的存储区域重新进行动态存储分配。p_block是指向已由malloc函数或calloc函数分

32、配的存储区域的指针(首地址),size是申请重新分配存储的字节数。如果分配成功,返回新分配存储区域的首地址;如果分配失败,则返回NULL。 另外,如果新分配的存储区比已分配的存储区小,则新分配的存储区中仍然是原来老区中的数据;如果称新分配的存储区比已分配的存储区大,则新分配的存储区中新增部分的区域未被初始化。 例如,在上面第1点的代码片断后面,增加下面重新进行动态存储分配的语句: realloc(int *)p, 3*sizeof(int); 此时,新分配的存储区比已分配的存储区小,指针p指向重新分配的3个整型单元, p0,p1,p2的值分别为0,1,2。 如果将realloc(int *)p

33、, 3*sizeof(int);改为: realloc(int *)p, 8*sizeof(int); 此时,新分配的存储区比已分配的存储区大,p0至p5的值0,1,2,3,4,5将保持不变;p6和p7则为随机值。,2019/9/1,华中科技大学计算机学院,34,4) free函数的功能,free函数的原型为: void free(void * p_block); free函数的功能是释放由指针p_block所指向的存储区,p_block是由malloc,calloc或realloc分配的存储区的指针,一旦释放,就不能再用p引用存储区中的数据。如果p_block为NULL,free函数无释放操

34、作。由于返回值的类型为void,free函数无返回值。,2019/9/1,华中科技大学计算机学院,35,*10.10 动态数组设计,动态存储分配函数创建动态数组 在没有学习存储分配之前,如果要设计某班的C语言课程成绩单,首先必须知道人数,并且要按照可能出现的最多人数进行相关数组的声明。并且象学号,姓名等数据项的长度也必须事先按照最长长度进行规定。但现在就可以根据各个班上的实际人数的多少,学号,姓名等数据项的实际长度来恰当的动态创建数组。,2019/9/1,华中科技大学计算机学院,36,例10.15 用动态存储分配方法设计某班的C语言课程成绩单。,#include “stdio.h“ #incl

35、ude “stdlib.h“ #include “string.h“ #include “assert.h“ 成绩单包含学号字符指针num和姓名字符指针name,它们将分别指向动态分配的学号存储区和姓名存储区。其优点是可以应用于不同长度的学号、姓名,并且根据学号、姓名实际长度分配存储,适应面广,且不会存在多余的空闲存储。 struct c_score_tab char *num; /* 学号 */ char *name; /*姓名 */ int c; /* C语言课程成绩 */ ;,2019/9/1,华中科技大学计算机学院,37,void dynamic_input(char *s1,char

36、 *s2) /*字符指针形参s1指向提示性的实参字符串 */ char *pc; int len; pc=(char *)malloc(40*sizeof(char); /* 动态分配40个字节,并由pc指向 */ assert(pc); /* 判断pc是否为空。为空,退出;否则顺序执行 */ printf(s1); /* 根据需要输出不同的提示 */ gets(pc); /* 从键盘接收输入的字符串 */ len=strlen(pc); /* 计算输入的字符串的长度 */ (*s2)=(char *)malloc(len*sizeof(char)+1); /*根据输入串长度适当分配存储*/

37、assert(*s2); strcpy(*s2),pc); /* 将输入串拷贝到动态申请的存储区 */ free(pc); /* 释放pc指向的动态存储区 */ ,2019/9/1,华中科技大学计算机学院,38,在dynamic_input函数中,pc指向40个字节长度的动态存储(实际上是有40个元素的动态字符数组),用于接收来自键盘输入的字符串。assert(pc)和assert(*s2)防止pc和(*s2)为空。dynamic_input函数先计算输入字符串的实际长度,再申请动态分配存储,并使(*s2)指向该存储,然后将pc指向的字符串拷贝到(*s2)指向的存储区域。调用时,字符指针形参s

38、1指向提示性的实参字符串,使printf(s1)可以根据需要输出不同的提示。用gets(pc)可以接收带空格的字符串(如:Peter Jolly)。 s2是双重字符指针,当实参为 只有将s2声明为双重字符针,才能够使主函数中的(p+i)-num和(p+i)-name指向在dynamic_input函数中动态分配的存储区域。,2019/9/1,华中科技大学计算机学院,39,void main(void) int n,i; struct c_score_tab *p; printf(“input the number of students please!n“); scanf(“%d“, /* 释

39、放成绩单占据的存储 */ ,2019/9/1,华中科技大学计算机学院,40,*10.11 链 表,链表是一种常用的动态数据结构,它由一系列包含数据域和指针域的结点组成。 如果结点的指针域中只包含一个指向后一个结点指针,这种链表称为单向链表。 如果结点的指针域包含两个指针,且一个指向前一个结点,另一个指向后一个结点,这种链表称为双向链表。 如果结点的指针域包含两个指针,且一个指向后一个结点,另一个指向另外一个链表,这种链表称为十字交叉链表。,2019/9/1,华中科技大学计算机学院,41,10.11.1 自引用结构,如果一个结构类型中包含一个该结构类型的指针,称该结构类型为自引用结构类型,对应的

40、结构变量称为自引用结构变量,自引用结构变量常常简称为自引用结构。 自引用结构的指针成员是一个指向该自引用结构的指针。 因此,关于自引用结构的定义也可以表示为:如果一个结构中包含一个指向该结构自身的指针,该结构称为自引用结构。,2019/9/1,华中科技大学计算机学院,42,自引用结构,struct s_list int data; struct s_list *next; node1=1,NULL; 由于struct s_list结构类型中,next是指向struct s_list结构类型变量的指针(称为指向自身的指针),因此struct s_list结构类型是自引用结构类型。而node1是自

41、引用结构变量(自引用结构)。,2019/9/1,华中科技大学计算机学院,43,自引用结构变量(自引用结构),执行下面语句: struct s_list node2,node3; node2.data=2; node3.data=3; node2.next=node3.next=NULL; 则node1,node2,node3的存储结构如图所示。 node1 node2 node3,2019/9/1,华中科技大学计算机学院,44,例10.16 以自引用结构node1、node2和node3为“结点”构建“链表”。,#include “stdio.h“ struct s_list int data

42、; struct s_list *next; node1=1,NULL; void main(void) struct s_list node2,node3; struct s_list *head=NULL,*p; node2.data=2; node3.data=3; node2.next=node3.next= NULL; head=,node1.next= ,2019/9/1,华中科技大学计算机学院,45,程序中head称为头指针,head=&node1使head指向了node1;node1.next=&node2使node1指向了node2;node2.next=&node3使nod

43、e2指向了node3。 p称为遍历指针, p=p-next使p指向了下一个自引用结构。对“结点”和“链表”加一个引号,表明上面程序创建的各个自引用结构之间的指向关系与实际链表一致,但存储分配是静态而不是动态的。 程序的运行结果如下: FFD4 0194 0194 1 FFCC FFCC 2 FFD0 FFD0 3 0000,2019/9/1,华中科技大学计算机学院,46,10.11.2 动态创建结点,可以通过(结点指针类型)malloc(sizeof(结点类型)的方式来动态创建结点。 如: p=(struct s_list *)malloc(sizeof(struct s_list) 它通过动

44、态存储分配创建一个struct s_list的自引用结构变量作为结点,并将返回值的类型强制转换为自引用结构类型的指针并赋给指针p。,2019/9/1,华中科技大学计算机学院,47,例1017 从头指针开始,动态创建三个结点,并使用头指针head访问后继三个结点。相关解释以注释的方式给出。,struct s_list int data; struct s_list *next; ; void main(void) struct s_list *head=NULL,*p; head=(struct s_list *) malloc(sizeof(struct s_list); head-data=

45、1; head-next=(struct s_list *) malloc(sizeof(struct s_list); head-next-data=2;,head-next-next=(struct s_list *) malloc(sizeof(struct s_list); head-next-next-data=3; head-next-next-next=NULL; p=head; while(p) printf(“%pt%dt%pn“, p,p-data,p-next); p=p-next; ,2019/9/1,华中科技大学计算机学院,48,10.11.3 单向链表,在单向链表中

46、,结点的指针域中只包含一个指向其自身的指针,用于指向后继结点。 头指针指向链表中称为链头的第一个结点,从第一个结点开始,每个结点的指针成员都指向其后继结点,最后一个称为链尾的结点的指针域为空指针NULL。 struct s_list结构中由于数据域内只有一个整型数据,以此为结点构成的链表一般都称为整数链表。 设所讨论的结点为当前结点,则它前面的一个结点称为直接前驱结点(简称前驱);它后面的一个结点称为直接后继结点(简称后继)。,2019/9/1,华中科技大学计算机学院,49,例10.18 给定一批整数,以0作为结束标志且不作为结点,将其建成一个先进先出的链表,先进先出链表的指头指针始终指向最先

47、创建的结点(链头),先建结点指向后建结点,后建结点始终是尾结点。,结点自引用结构类型的声明和创建链表函数原型的声明如下: #include “stdio.h“ #include “stdlib.h“ struct s_list int data; /* 数据域 */ struct s_list *next; /* 指针域 */ ; void create_list_v1(struct s_list *headp,int *p);,2019/9/1,华中科技大学计算机学院,50,1用循环方式建立先进先出链表 建立一个非空先进先出链表相关算法步骤如下: (1)声明头指针,尾指针。 struct s

48、_list * loc_head=NULL,*tail; (2)创建第一个结点。包括: (2-1)给第一个结点动态分配存储并使头指针指向第一个结点。 loc_head=(struct s_list *)malloc(sizeof(struct s_list); (2-2)给第一个结点的数据域中成员赋值。 loc_head-data=*p+; (2-3)使尾指针也指向第一个结点。 tail=loc_head; (3)循环建立后续结点 (3-1)如果没遇到结束标志0,进行下列操作: (3-1-1)给后继结点动态分配存储并使前驱结点的指针指向后继结点。 tail-next=(struct s_lis

49、t *)malloc(sizeof(struct s_list); (3-1-2)使尾指针指向新建立的后继结点 tail=tail-next; (3-1-3)给后继结点的数据域中成员赋值。 tail-data=*p+; (3-1-4)转(3-1) (4)给尾结点(最后一个结点)的指针赋NULL值。 tail-next=NULL;,2019/9/1,华中科技大学计算机学院,51,根据算法步骤设计的创建链表函数的如下: void create_list_v1(struct s_list *headp,int *p) struct s_list * loc_head=NULL,*tail; if(p0=0) /* 相当于*p=0 */ ; else /* loc_head指向动态分配的第一

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

当前位置:首页 > 其他


经营许可证编号:宁ICP备18001539号-1