第9章 结构体与共用体.pdf

上传人:wj151****6093 文档编号:72503942 上传时间:2023-02-11 格式:PDF 页数:32 大小:975.81KB
返回 下载 相关 举报
第9章 结构体与共用体.pdf_第1页
第1页 / 共32页
第9章 结构体与共用体.pdf_第2页
第2页 / 共32页
点击查看更多>>
资源描述

《第9章 结构体与共用体.pdf》由会员分享,可在线阅读,更多相关《第9章 结构体与共用体.pdf(32页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、第第 9 9 章章 结构体与共用体结构体与共用体前面已经介绍了基本数据类型(如整型、实型、字符型),也介绍了一种构造类型数据数组,数组中的各元素属于同一个类型。但只有这些数据类型是不够的。有时需要将类型不同的而又相关的数据项组织在一起,统一管理。如一个学生的基本信息包括:学号、姓名、性别、年龄、成绩、家庭住址等。这些信息各项的类型不同,不能用数组表示,也不能将各项分别定义成互相独立的变量,这样不仅是程序混乱,也体现不出各项数据间的逻辑关系。为此,在C 语言中提供了另一种构造数据类型 结构体(structure),它将不同类型的数据项组织在一起。9.19.1 结构体类型的定义结构体类型的定义结构

2、体由若干成员组成,各成员可以是不同的类型。在程序中使用结构体类型,必须先对结构体的组成进行描述(定义)。例如,学生信息可用结构体定义为:struct studentint num;char name20;char sex;int age;float score;char addr30;其中,关键字 struct 是结构体类型的标志。struct 之后的 student 是结构体名,用花括号括起来的是各个成员的描述(定义)。上例定义的结构体类型 struct student 有 6 个成员,分别为 num、name、sex、age、score 和 addr。这 6 个成员分别表示学生的学号、姓名

3、、性别、年龄、成绩和家庭住址,显然他们的类型是不同的。结构体类型定义的一般形式为:struct 结构体名成员表列;其中 struct 是关键字,结构体名用合法的标识符表示,成员表列的说明形式为:类型名成员名;如前例所示。结构体类型定义要注意以下几点:(1)结构体类型定义只是指定了一种类型(同系统已定义的基本类型,如 int、float、char 等一样),无具体的数据,系统不分配实际内存单元。(2)结构体类型的成员可以是任何基本数据类型、数组、指针等,而且可以是已定义的结构体类型。例如,以下定义一个表示日期的结构体类型:struct date int year;int month;int da

4、y;以下定义一个表示学生信息的结构体类型:struct stu int num;char name20;char sex;struct date birthday;/*成员 birthday 为结构体类型 struct date*/float score3;char addr30;注意:结构体类型定义最后的分号不能省略。9.29.2 结构体类型变量结构体类型变量9.2.19.2.1 结构体类型变量的定义结构体类型变量的定义结构体类型定义后,表示增加了一种结构体类型,不能象变量一样使用。必须用结构体类型定义相应的变量才能使用。定义结构体类型变量,有以下三种方法:1 1先定义结构体类型,再定义变量

5、先定义结构体类型,再定义变量这种定义方法的一般形式为:struct 结构体名成员表;struct 结构体名 变量名表列;如前面已定义了一个结构体类型 struct stu,可以用它来定义变量。例如:struct stu s1,s2;定义 s1 和 s2 为 struct stu 类型的变量,即他们是具有 struct stu 类型的结构体变量。定义结构体变量后,系统为他们分配内存单元。系统为结构体变量分配的内存单元是连续的,一个结构体变量所占的内存空间为它的各成员所占字节数之和。例如,以上结构体变量 s1 的内存空间分配如图 9.1 所示。-180-s1地址numname20sexbirthd

6、ayscore3addr30图 9.1 结构体变量 s1 的内存空间分配可以用 sizeof(变量)或 sizeof(类型标识符)求出该变量或该种类型的变量所占的存储空间的字节数。例如表达式“sizeof(s1)”或“sizeof(struct stu)”的值为 71(按 Turbo C标准)。2 2在定义结构体类型的同时定义变量在定义结构体类型的同时定义变量这种定义方法的一般形式为:struct 结构体名成员表变量名表列;例如:struct st int num;char name20;float score;s1,s2;它在定义了结构体类型 struct st 的同时定义了两个该类型的变量

7、 s1 和 s2。3 3直接定义结构体类型变量直接定义结构体类型变量这种定义方法的一般形式为:struct成员表变量名表列;例如:struct int num;char name20;float score;s1,s2;即在结构体定义时不出现结构体类型名,这种形式虽然简单,但不能在再需要时,使用定义的结构体类型。建议读者使用前两种方法定义结构体类型变量。-181-9.2.29.2.2 结构体变量的引用结构体变量的引用在对结构体变量引用时,一般只能对其成员进行直接操作,而不能对结构体变量整体进行操作。引用结构体变量成员的一般形式为:结构体变量名.成员名运算符“.”为成员运算符,其结合性是自左至右

8、。例如:struct date int year;int month;int day;struct example int num;char name20;struct date bir;s1,s2;各成员的引用形式如下:s1.num=101;s2.num=s1.num+1;strcpy(s1.name,”wang”);如果成员本身又属于一个结构体类型,则要用若干个成员运算符,一级一级地找到最低一级的成员。如:s1.bir.year=1985;结构体变量和其它变量一样,可以在定义变量的同时进行初始化。结构体变量初始化的一般形式如下:结构体类型结构体变量名=初始值表;例如:struct stud

9、entchar name10;float score3;stu=“wang_li”,81,77,96;这样,结构体变量 stu 各成员依次被赋初值:name 为“wang_li”,数组 score 各元素分别为 81、77、96。【例 9.1】输入某学生的姓名、年龄和 5 门功课成绩,计算平均成绩并输出。#include void main()struct student char name10;int age;-182-float score5,ave;stu;int i;stu.ave=0;scanf(%s%d,stu.name,&stu.age);for(i=0;i5;i+)scanf(

10、%f,&stu.scorei);stu.ave+=stu.scorei/5.0;printf(%s%4dn,stu.name,stu.age);for(i=0;i5;i+)printf(%6.1f,stu.scorei);printf(average=%6.1fn,stu.ave);程序运行情况:wang_li 2182 77 91 68 85wang_li2182.077.091.068.085.0 average=80.6程序说明:在语句“scanf(%s%d,stu.name,&stu.age);”中,由于 name 是数组名,stu.name表示地址常量,前面不需要加地址运算符“&”,

11、而在 stu.age 前必须加“&”。由于运算符“.”的优先级比运算符“&”高,故&stu.age 与&(stu.age)等价。在语句“scanf(%f,&stu.scorei);”中,运算符“”和“.”的优先级比运算符“&”高,所以&stu.scorei与&(stu.scorei)等价。/*输入 5 门功课成绩*/*计算平均成绩*/*输入学生姓名和年龄*/9.39.3 结构体数组结构体数组一个结构体变量中可以存放一组数据(如一个学生的学号、姓名、成绩等)。如果有 10 个学生的数据要进行运算,要用数组,这就是结构体数组。结构体数组中的每个元素都是一个结构体类型的变量,他们都分别包含各个成员项

12、。9.3.19.3.1 结构体数组的定义与初始化结构体数组的定义与初始化1 1结构体数组的定义结构体数组的定义-183-结构体数组的定义与结构体变量的定义方法类似,只需说明其为数组即可。如:struct student int num;char name20;char sex;int age;float score3;;struct student stu10;以上定义了一个数组 stu,其元素为 struct student 类型变量,数组有 10 个元素。2 2结构体数组的初始化结构体数组的初始化结构体数组的初始化与普通的二维数组的初始化类似。如:struct student int nu

13、m;char name15;char sex;int age;float score3;stu2=1101,”wang li”,M”,21,75,82,94,1102,”li ping”,F,20,82,79,90;定义数组 stu 时,数组长度可以不指定,即可写成如下形式:stu=.,.;编译时,系统会根据给出的结构体常量的个数来确定数组元素的个数。9.3.29.3.2 结构体数组的引用结构体数组的引用下面通过一个例子来说明结构体数组的引用。【例 9.2】输入 3 个复数的实部和虚部放在一个结构体数组中,根据复数模由小到大顺序对数组进行排序并输出。(注:复数的模=sqrt(实部*实部+虚部*

14、虚部)#define N 3#include#include void main()struct complexfloat x;float y;-184-/*定义复数结构体*/*x 表示实部*/*y 表示虚部*/float m;int i,j,k;/*m 表示模*/*定义结构体数组 a*/aN,temp;for(i=0;iN;i+)scanf(%f%f,&ai.x,&ai.y);for(i=0;iN-1;i+)k=i;for(j=i+1;jN;j+)if(ak.maj.m)k=j;temp=ai;ai=ak;ak=temp;/*输入复数的实部和虚部*/*计算复数的模*/*按模排序*/ai.m=

15、sqrt(ai.x*ai.x+ai.y*ai.y);for(i=0;i成员名其中,由于运算符“.”的优先级高于指针运算符“*”,所以中的圆括号不能省略。中的运算符“-”(由减号和大于号组成)称为指向运算符,其优先级与成员运算符“.”一样。可以用结构体指针变量修改例 9.2 的程序如下:#define N 3#include#include void main()struct complexfloat x,y,m;aN,temp,*p,*q,*k;-186-for(p=a;px,&p-y);p-m=sqrt(p-x*p-x+p-y*p-y);for(p=a;pa+N-1;p+)k=p;for(q

16、=p+1;qmm)k=q;temp=*p;*p=*k;*k=temp;for(p=a;px,p-y);程序说明:可以将一个结构体变量的值整体赋给另一同类型结构体变量,如temp=*p。9.59.5 结构体和函数结构体和函数在函数间传递结构体数据时,结构体变量、结构体变量的成员、指向结构体变量的指针都可以作为函数的参数传递。定义函数时,函数的返回值类型可以是结构体类型,也可以返回一个指向结构体的指针。9.5.19.5.1 结构体作函数参数结构体作函数参数1 1结构体变量作函数参数结构体变量作函数参数结构体变量的成员作函数参数与同类型的普通变量作函数参数一样。结构体变量作函数的参数,在函数调用时要

17、为形参结构体变量开辟存储单元,并将实参结构体变量的值复制到形参结构体变量中。请看下面的例子。【例 9.3】输入两个复数,比较这两个复数模是否相等。#include#includestruct comp float x,y;float m;/*定义结构体类型*/*x 表示实部,y 表示虚部*/*m 表示模*/-187-float compare(struct comp a,struct comp b)a.m=sqrt(a.x*a.x+a.y*a.y);b.m=sqrt(b.x*b.x+b.y*b.y);return(a.m-b.m);void main()struct comp a,b;scan

18、f(%f%f,&a.x,&a.y);scanf(%f%f,&b.x,&b.y);if(compare(a,b)=0)printf(Equaln);else printf(Unequaln);程序运行 1:122 1Equal程序运行 2:122 2Unequal/*参数为结构体类型*/*求复数 a 的模*/*模相等返回 0,否则非 0*/*输入 a 的实部和虚部*/*输入 b 的实部和虚部*/程序说明:程序中结构体类型(struct comp)被定义为外部类型,这样同一文件中的各个函数都可以用它来定义变量的类型。在 compare 函数中用 struct comp 定义形参变量 a 和 b,在

19、 main 函数中用 struct comp 定义实参变量 a 和 b。2 2结构体指针作函数参数结构体指针作函数参数用指向结构体变量的指针作函数的参数,函数调用时传递结构体变量的地址。请看下面的例子。【例 9.4】编写按复数模从小到大排序函数。#define N5#include#includestruct comp float x,y;float m;void sort(struct comp*p,int n)-188-/*p 为指向结构体的指针变量*/int i,j,k;struct comp t;for(i=0;in-1;i+)k=i;for(j=i+1;jm(p+j)-m)k=j;/

20、*p+k 指向 ak*/t=*(p+i);*(p+i)=*(p+k);*(p+k)=t;void main()struct comp aN;int i;printf(Input complex:n);for(i=0;iN;i+)scanf(%f%f,&ai.x,&ai.y);ai.m=sqrt(ai.x*ai.x+ai.y*ai.y);sort(a,N);/*调用 sort 函数*/printf(Output complex:n);for(i=0;im 为数组元素 ak的成员 m 的值。所以 sort 函数实际/*t 为结构体变量*/*a 为结构体数组*/*按 x+yi 格式输出*/-189-

21、上是对 main 函数中的数组 a 的各元素按成员 m 的值排序。9.5.29.5.2 返回结构体的函数返回结构体的函数1 1返回结构体数据的函数返回结构体数据的函数函数可以带回一个结构体类型的数据给主调函数。请看下面的例子。【例 9.5】输入一批复数,查找并输出模最大的复数。编写函数完成查找功能。#define N5#include#includestruct comp float x,y;float m;struct comp find(struct comp p,int n)int i,k=0;float t=p0.m;for(i=1;in;i+)if(tpi.m)void main()

22、struct comp aN,max;int i;for(i=0;iN;i+)scanf(%f%f,&ai.x,&ai.y);ai.m=sqrt(ai.x*ai.x+ai.y*ai.y);max=find(a,N);程序运行:11133-2/*函数返回值为结构体类型*/t=pi.m;k=i;/*返回模最大的复数*/return pk;/*调用 find 函数*/printf(max=%.1f%+.1fin,max.x,max.y);-190-5-379max=7.0+9.0i程序说明:find 函数的返回值为结构体类型(struct comp),在主调函数中用相同类型的变量 max 接收 fi

23、nd 函数的返回值。2 2返回结构体指针的函数返回结构体指针的函数在例 9.5 中,find 函数的返回值是结构体类型数据,函数返回时要带回结构体各成员值,影响程序的执行效率。可将函数的返回值修改为指针类型。例如:#define N5#include#includestruct comp float x,y;float m;struct comp*find(struct comp*p,int n)int i,k=0;float t=p0.m;for(i=1;in;i+)if(tm)void main()struct comp aN,*max;int i;for(i=0;ix,max-y);程序

24、说明:find 函数的返回值为结构体类型指针(struct comp*),在main 函数中用/*函数返回值为结构体指针*/t=(p+i)-m;k=i;/*返回复数模最大的数组元素地址*/return(p+k);/*max 为指针类型*/-191-于接收模为最大值的数组元素地址的变量max 也应定义为该结构体类型指针(structcomp*)。9.69.6 链表链表9.6.19.6.1 简单链表简单链表链表是一种常见的数据结构。它是动态地进行存储分配的一个结构。我们知道用数组存放数据,必须先定义数组的长度(即元素的个数)。比如,有的班级有 50 人,有的班级有 30 人,如果用同一个数组先后存

25、放不同班级的学生数据,就要定义长度为50 的数组。如果事先难以确定一个班级的最多人数,就要把数组定义的足够大,以便能存放任何班级的学生数据。显然这将浪费内存。链表则没有这种缺点,它根据需要在程序执行时开辟内存单元。图 9.3 表示最简单的一种链表(单向链表)的结构。head110182110267110396NULL图 9.3 链表结构示意图链表中的每一个元素称为节点,每个节点用一个结构体数据表示,包括若干个数据成员和一个指针成员(即指向同类型节点的指针变量)。图9.3 中的每个节点都包含两个数据成员(学号和分数)。节点中的指针成员指向下一个节点(即存放下一个节点的首地址)。最后一个节点的指针

26、成员为空指针(NULL),它表示不指向任何节点。下面通过一个例子来说明如何建立和输出一个简单链表。【例 9.6】建立一个如图 9.3 所示的简单链表,它由三个节点组成。#includestruct stu long int num;int score;struct stu*next;void main()struct stus1,s2,s3,*head,*p;head=&s1;s1.num=1101;s1.score=82;s1.next=&s2;s2.num=1102;s2.score=67;s2.next=&s3;s3.num=1103;s3.score=96;s3.next=NULL;p

27、=head;while(p!=NULL)-192-printf(%ld%dn,p-num,p-score);p=p-next;程序运行结果如下:110182110267110396程序说明:main 函数中定义的变量 s1,s2,s3 都是结构体变量,他们都含有 num、score、next 三个成员。变量 head 和 p 是指向 struct stu 结构体类型的指针变量,他们与结构体变量 s1、s2、s3 中的 next 类型相同。执行赋值语句后,head 中存放了 s1 变量的地址,变量 s1 的成员 s1.next 中存放了 s2 的地址,最后一个变量 s3 的成员 s3.next

28、中存放了 NULL,从而把同一类型的结构体变量 s1、s2、s3“链接”到一起,形成“链表”。在此例中,链表中的每个节点都是在程序中定义的,由系统在内存中分配固定的存储单元(不一定连续)。在程序执行过程中,不可能人为地再产生新的存储单元,也不可能人为地释放用过的存储单元。从这一角度讲,可称这种链表为“静态链表”。在实际中,使用更广泛的是一种“动态链表”。9.6.29.6.2 处理动态链表所需的库函数处理动态链表所需的库函数前面讲过,链表是一种动态分配存储空间的数据结构,即在需要时才开辟存储单元。C 语言编译系统提供了以下有关函数,他们的头文件为 stdlib.h。1 1mallocmalloc

29、 函数函数函数原型:void*malloc(unsigned int size);功能:在内存的动态存储区中分配一个长度为 size 的连续空间,若成功,则返回分配到的空间的起始地址;若不成功(如内存不足),则返回空指针(NULL)。使用方法:结构体指针变量=(结构体类型名*)malloc(size);其中,size 为无符号整型表达式,用来确定分配空间的字节数;由于 malloc 函数返回值类型是“void*”,即不确定的指针类型,所以要根据具体情况用强制类型转换将其转换成所需的指针类型。例如char*p;/*此时 p 的指向不明确*/*此时 p 指向包含 10 个字节的存储空间*/p=(c

30、har*)malloc(10);2 2calloccalloc 函数函数函数原型:void*calloc(unsigned int n,unsigned in size);-193-功能:在内存的动态存储区中分配 n 个长度为 size 的连续空间,若成功,则返回分配到的空间的起始地址(指针);若不成功(如内存不足),则返回空指针(NULL)。使用方法:结构体指针变量=(结构体类型名*)calloc(n,size);其中,n 和 size 均为无符号整型表达式,n 用来确定分配空间的个数,size 用来确定每个分配空间的字节数;其余和 malloc 函数的含义相同。3 3freefree 函数

31、函数函数原型:void free(void*p);功能:释放由 p 指向的内存空间,使这部分内存空间能被其它变量使用。p 只能是由动态分配函数(malloc 函数或 calloc 函数)所返回的值。使用方法:free(指针变量名);例如:free(p);9.6.39.6.3 单向链表的基本操作单向链表的基本操作对链表的基本操作包括建立链表、遍历链表、将节点插入到链表以及删除链表中的节点等。下面介绍链表的各项基本操作,仍以上面例 9.6 中的存放学生学号和成绩的结构体类型(struct stu)为例。1 1建立链表建立链表建立链表的过程是从无到有地将一个链表建立起来。具体步骤如下:(1)首先,定

32、义结构体类型指针变量:struct stu*head=NULL,*pnew,*pend;其中,head 用于指向链表的第一个节点,head 为 NULL 表示链表是空的;pnew 用于指向新申请的节点空间;pend 用于指向链表的最后一个节点。(2)在空链表中建立头节点(第一个节点):pnew=(struct stu*)malloc(sizeof(struct stu);scanf(“%ld%d”,&pnew-num,&pnew-score);head=pnew;pend=pnew;如图 9.4 所示。headheadNULLpnewpend数据(a)添加数据前(b)添加数据后图 9.4 在空

33、链表中建立头节点(3)在有节点的链表中添加新节点:pnew=(struct stu*)malloc(sizeof(struct stu);-194-scanf(“%ld%d”,&pnew-num,&pnew-score);pend-next=pnew;pend=pnew;如图 9.5 所示。head数据数据pend数据pnew数据(a)添加节点前head数据数据数据pend数据(b)添加节点后图 9.5 在已有节点后添加新节点重复执行这一步,直到所有的节点都添加到链表中。(4)将链表中尾节点(最后一个节点)的指针成员赋值为 NULL。pend-next=NULL;此时,链表建立完毕。head

34、指向链表的头节点,pend 指向链表的尾节点。可以从头指针 head 出发,访问链表中的每个节点。下面定义一个创建链表的函数 create。【例 9.7】编写函数(create)建立一个有 n 个节点的单向链表。/*函数 create 用于创建有 n 个节点的链表,函数返回新建链表的头指针*/struct stu*create(int n)int i;struct stu*head,*pnew,*pend;pnew=(struct stu*)malloc(sizeof(struct stu);scanf(%ld%d,&pnew-num,&pnew-score);head=pend=pnew;f

35、or(i=1;inum,&pnew-score);pend-next=pnew;pend=pnew;pend-next=NULL;return head;2 2遍历链表遍历链表/*建立头节点*/*置尾节点的指针成员为空*/-195-遍历链表就是从链表的头指针出发,访问链表的每一个节点,其操作步骤如下:(1)已知链表的头指针 head,使用语句“p=head;”使指针变量 p 也指向链表的头节点,如图 9.6 所示。headp数据数据数据数据NULL图 9.6 使 p 指向头节点(2)访问 p 所指向的节点的数据成员之后,使 p 指向下一个节点,例如:printf(“%ld%dn”,p-num,

36、p-score);p=p-next;执行语句“p=p-next;”后,指针变量 p 就指向下一个节点,如图 9.7 所示。head数据p数据数据数据NULL图 9.7 使 p 指向下一个节点重复这一步,可以访问链表的每一个节点,直到链表的尾节点(即指针p 的值为NULL)。下面的例子是定义遍历链表的函数 print。【例 9.8】编写遍历链表的函数 print,输出所有节点信息。/*函数 print 输出链表节点信息,形参 head 为链表头指针*/void print(struct stu*head)struct stu*p=head;while(p!=NULL)printf(%ld%dn,

37、p-num,p-score);p=p-next;下面的例子是利用前面定义的两个函数 create 和 print 编写的一个完整的程序。【例 9.9】输入 3 个学生的学号和成绩,并输出这些信息。#define N3#include#includestruct stu long int num;int score;struct stu*next;/*将函数 create 的定义写在此处*/*将函数 print 的定义写在此处*/void main()struct stu*head;/*N 表示节点个数*/-196-head=create(N);print(head);程序运行情况:990167

38、990292990383990167990292990383此例是将输入的节点(学生信息)链接到链表的尾部。有时需要将节点插入到链表的某个位置。例如,已有链表是有序的,即链表中的各节点是按照某个成员值排序(升序或将序)。这时插入一个新节点后,仍要保持链表是有序的。3 3在链表中插入节点在链表中插入节点假设对于前面介绍的学生链表,已按数据成员 score 降序排列(即高分在前),现要插入一个新的节点,要求插入后链表仍是有序的。操作步骤如下:(1)使指针变量 p1 指向头节点,建立要插入的新节点,并使指针变量 pnew 指向它,如图 9.8 所示。所用语句如下:p=head;pnew=(struc

39、t stu*)malloc(sizeof(struct stu);scanf(“%ld%d”,&pnew-num,&pnew-score);pnewhead数据p1数据数据数据NULL图 9.8 使 pnew 指向新节点(2)将 pnew 所指向的节点按序插入到链表中。若(pnew-score)(head-score)为真,表示新节点应插入到头节点之前(高分在前),如图 9.9 所示。将新节点插入到头节点之前所用语句如下:if(pnew-scorehead-score)pnew-next=head;head=pnew;headpnew数据p1数据数据数据NULL图 9.9 将 pnew 指向的

40、节点插入到头节点之前若(pnew-score)(head-score)为假,表示要插入的节点应在头节点之后,应继续寻找其在链表中的位置。从链表的头指针开始逐一比较各节点的成绩值与新节点的成绩值,并使p1 指向链表中每个要比较的节点,另外还要定义一个指针变量 p2,在 p1 指向下一个节点之前将-197-其值保存在p2 中(即 p2=p1;)。若找到了某一节点的成绩比新节点的成绩低,即(pnew-score)(p1-score)为真,则说明找到了新节点的插入位置,即要插入在 p1 和 p2所指的两个节点之间,如图 9.10 所示。p2数据p1数据pnew数据图 9.10 将新节点插入到链表中间若

41、在链表中找不到比新节点成绩低的节点,则说明新节点应插入在链表的末尾,此时 p1 的值为 NULL,执行语句“pnew-next=p1;”,使新节点成为链表的尾节点,与插入在链表中间无区别。将新节点插入到链表中间及末尾所用语句如下:while(p1!=NULL&pnew-scorescore)p2=p1;p=p-next;pnew-next=p1;p2-next=pnew;下面的例子定义了插入节点的函数 insert。【例 9.10】编写函数 insert,在有序的链表中插入给定的节点。struct stu*insert(struct stu*head)struct stu*pnew,*p1,*

42、p2;pnew=(struct stu*)malloc(sizeof(struct stu);scanf(%ld%d,&pnew-num,&pnew-score);p1=head;if(pnew-scorehead-score)pnew-next=head;head=pnew;else p2=p1;p1=p1-next;/*插入在链表中间或末尾*/while(p1!=NULL&pnew-scorescore)/*插入在头节点前*/*建立新节点*/*输入新节点数据*/pnew-next=p1;p2-next=pnew;return head;程序说明:函数 insert 用于在链表中插入一个节点

43、,如果原链表是空的,则应先建立有一个节点的链表,然后反复调用此函数,不断插入新节点,可创建一个按照节点的-198-某个成员排序的链表。【例 9.11】输入 n 个学生的学号和成绩建立一个链表,并使链表中的节点按成绩由高到低链接。#include#includestruct stu long int num;int score;struct stu*next;/*将函数 insert 的定义写在此处*/*将函数 print 的定义写在此处*/void main()int i,n;struct stu*head;printf(Input the number of nodes:n);scanf(%

44、d,&n);/*输入链表的节点数 n*/*建立有 1 个节点的链表*/head=(struct stu*)malloc(sizeof(struct stu);scanf(%ld%d,&head-num,&head-score);head-next=NULL;for(i=1;inext 赋给 head,如图 9.11(c)所示。最后要将 p1 所指向的节点释放。如果要删除的不是头节点,则将p1-next 赋给 p2-next,如图 9.11(d)所示。p2-next 原来指向 p1 指向的节点,现在 p2-next 改为指向 p1-next 所指向的节点。最后要将 p1 所指向的节点释放。在编写

45、程序时还要考虑到链表是空的和链表中找不到要删除的节点的情况。下面给出定义删除节点的函数的程序。【例 9.12】编写函数 del,删除链表中指定的节点。struct stu*del(struct stu*head,long int n)struct stu*p1,*p2;if(head=NULL)printf(list nulln);return head;p1=head;while(n!=p1-num&p1-next!=NULL)p2=p1;p1=p1-next;if(n=p1-num)if(p1=head)head=p1-next;else p2-next=p1-next;free(p1);

46、printf(delete:%ldn,n);-200-elseprintf(%ld not fondn,n);return head;程序说明:函数 del 的类型是指向 struct stu 类型的指针,其值是链表的头指针。函数参数为 head 和删除的节点的学号 n。head 的值可能在执行函数过程中被改变。【例 9.13】输入 n 个学生的学号和成绩建立一个链表,再输入一个学生的学号,从链表中删除所对应的节点。#include#includestruct stu long int num;int score;struct stu*next;/*将函数 create 的定义写在此处*/*将

47、函数 del 的定义写在此处*/void main()struct stu*head;int n;long int num;printf(Input the number of nodes:n);scanf(%d,&n);head=create(n);printf(Input delete the number:n);scanf(%ld,&num);del(head,num);程序运行情况:Input the number of nodes:3990182990256990391Input delete the number:9902delete:9902程序说明:程序中省略了函数 creat

48、e 和函数 del 的定义,参见例 9.7 和例 9.12。以上介绍的是单向链表的基本操作。结构体和指针的应用领域很广泛,除了单向链-201-表,还有环形链表、双向链表。此外还有队列、树、栈、图等数据结构。有关这方面的算法可以学习数据结构课程,在此不作介绍。9.79.7 共用体共用体共用体也是一种构造数据类型,它是将不同类型的变量存放在同一段内存区域内。共用体也称为联合体(union)。共用体的类型说明、变量定义及引用方式与结构体相似。不同的是,结构体变量的成员各自占有自己的存储空间,而共用体变量中的所有成员占有同一个存储空间。1 1共用体变量的定义共用体变量的定义共用体变量的定义与结构体变量

49、的定义相似,先定义共用体类型,再定义共用体变量。共用体类型定义的一般形式为:union 共用体名 共用体成员表;其中,union 是关键字,共用体名用标识符命名,共用体成员表是对各成员的定义,其形式为:类型说明符成员名;与定义结构体变量一样,定义共用体变量有三种方法:(1)先定义共用体类型,再定义共用体变量例如:union data int i;char ch;float f;union data a,b,c;(2)在定义公用体类型的同时定义变量例如:union data int i;char ch;float f;a,b,c;(3)不定义共用体类型名,直接定义变量例如:-202-union

50、int i;char ch;float f;a,b,c;定义了共用体变量,系统就给它分配内存空间。由于共用体变量中的各成员占用同一存储空间,所以系统分配给共用体变量的内存空间的大小为其成员中所占内存空间最大的字节数。共用体变量中各成员都从同一地址开始存放。例如上述例子中的共用体变量 a 的内存分配如图 9.12 所示,它占用 4 个字节的内存空间。a 的地址chif图 9.12 共用体变量 a 的内存空间分配2 2共用体变量的引用共用体变量的引用共用体变量的引用方式与结构体变量相同,可以使用以下 3 种形式之一:(1)共用体变量名.成员名。(2)指针变量名-成员名。(3)(*指针变量名).成员

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 应用文书 > 工作报告

本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知得利文库网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com