




已阅读5页,还剩26页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
181第6章 结构体与共用体第6章 结构体与共用体u 本章重点1. 结构体类型的定义及结构体变量的定义。2. 结构体变量占用的内存空间。3. 结构体变量对结构体成员的引用方法。4. 结构体指针变量对结构体变量、结构体数组的应用。5. 结构体变量作为函数的参数。6. 链表:堆栈与队列。 7. 共用体的应用。u 本章难点1. 正确理解结构体类型与结构体变量的关系。2. 结构体数组变量对结构体成员的引用,指向结构体变量的指针对结构体成员的不同引用方法。3. 结构体变量的输入输出。4. 结构体变量作为函数的参数。5. 结构体的嵌套,堆栈与队列的应用。结构体(struct)和共用体(union)是C语言中程序员自定义的数据类型,它是一种常用的数据类型。结构体能把若干不同类型的变量组织到统一的名字之下,也称聚合数据类型,而通过共用体允许把同一片内存定义成多种不同类型的变量。6.1 结构体的基本概念以前各章所讨论的数据是单一的数据类型,而在实际应用中所涉及到变量的属性是各种基本数据类型的组合,因而在C语言程序设计中引入了结构体类型的概念。结构体类型是C语言的一种构造数据类型,它用于描述具有多个数据成员且每个数据成员具有不同数据类型的数据对象。例如描写一个学生的基本情况,涉及到学号、姓名、性别、两门课的成绩,分别用int num;char name8;char sex;float score2表示,要描写这样一个由不同数据类型构成的对象,需要定义一个结构体类型。1结构体类型定义结构体类型的定义格式为:struct 结构体类型名 类型 数据类型成员名 1; 类型 数据类型成员名 2; 类型 数据类型成员名 3; 类型 数据类型成员名 n; ;例如要描写上述学生的基本情况,需定义的结构体类型为:struct student int num ; char name8; char sex; float score2;注意(1)此定义仅仅是结构体类型的定义,它说明了结构体类型的构成情况,C语言并没有为之分配存储空间。(2)结构体中的每个数据成员称为分量或域,它们并不是变量,在实际应用中还需定义结构变量。2结构体变量的定义定义了结构体类型以后,可以进行结构体变量的定义,其形式为:struct 结构体类型名 结构体变量表;结构体的变量也可以是数组或指针。定义结构体变量时,C语言会为每个变量分配存储空间。结构体变量的定义的方法可以与结构体类型同时定义或分开定义,分开定义是指先定义结构体类型,再定义结构体变量。定义结构体时,我们实际上声明了一种复杂的数据类型,并未生成任何变量。声明该变量之前,不存在任何此种类型的变量。为了声明student类型的变量stu,可写成如下形式:struct student stu;这样就定义了struct student类型的结构体变量stu。student描述结构体类型,称为结构体类型。stu是结构体类型的实例或对象,称为结构体类型变量或结构体变量。定义了结构体变量(stu)之后,C编译程序自动为结构体变量的所有成员分配足够的内存,如图6.1所示。num name sex score0 score1 4Byte8Byte1B8Byte8Byte低地址 高地址图6.1 在Visual C+环境下结构体变量stu占用内存情况 定义结构体的同时可定义一个或多个结构体变量。例如:struct student int num ; char name8; char sex; float score2;stu1,stu2,stu3;定义结构体类型student,同时声明该类型变量stu1,stu2,stu3。每个结构体变量都包含各自的结构体成员的副本。例如,stu1中的sex成员和stu2中的sex成员是彼此独立的,改变stu1中的sex,不会影响stu2中的sex。如在定义结构体类型与结构体变量时,结构体标记还可省略。例如:struct int num ; char name8; char sex; float score2;这里直接按结构体类型说明了结构体变量。3结构体变量对结构体成员的引用通过圆点(.)操作符可访问结构体中的成员。访问一个结构体成员的一般形式为:结构体变量名.成员名;它表示结构体变量对具体成员的引用,以下代码把2001赋给结构体变量stu1的成员num:stu1.num=2001;在屏幕上显示stu的成员num所含的学号值,应写为:printf(%d,stu.num);同理,从键盘读入的语句是:scanf(“%d”,&stu.num);4结构体变量的赋值(1)结构体变量可在声明时直接进行初始化。初始化数据应放在大括号中,并根据成员变量的声明次序排列,同时数据之间的类型应一致。例如:struct student stu1=2001,张华,M,86.00,92.2;或:struct student int num ; char name8; char sex; float score2;stu1=2001,张华,M,86.00,92.2;例6.1 结构体变量初始化的实例。#includestruct student int num ; char name8; char sex; float score2;stu1=2001,张华,M,86.00,92.2;void main( )printf(%dt%st%ct%ft%fn,stu1.num,,stu1.sex,stu1.score0,stu1.score1);(2)对结构体变量的数据成员成员进行逐个赋值例6.2 结构体变量的数据成员进行逐个赋值。#include#includestruct student int num ; char name8; char sex; float score2;stu1;void main( )stu1.num=2001;strcpy(,张华);stu1.sex=M;stu1.score0=86.00;stu1.score1=92.2;printf(%dt%st%ct%ft%fn,stu1.num,,stu1.sex,stu1.score0,stu1.score1);(3)可用单赋值语句把一个结构体变量的全部内容赋给另一个同类结构体变量,而不必逐个成员地多次赋值。以下程序描述结构体赋值:例6.3 结构体变量之间的赋值。#includestruct student int num ; char name8; char sex; float score2;stu1=2001,张华,M,86.00,92.2;void main(void)struct student stu2;stu2=stu1;printf(%dt%st%ct%ft%fn,stu2.num,,stu2.sex,stu2.score0,stu2.score1);(4)从键盘中逐个读入结构体数据成员。例6.4从键盘中逐个读入结构体数据成员的实例。#includestruct student int num ; char name8; char sex; float score2;stu1;void main( ) scanf(%d%s%c%f%f,&stu1.num,,&stu1.sex,&stu1.score0,&stu1.score1);printf(%dt%st%ct%ft%fn,stu1.num,,stu1.sex,stu1.score0,stu1.score1);6.2 结构体数组6.2.1 结构体数组的定义结构体的最常见用法就是结构体数组(array of structures)。例如,描述一个班级的学生。用结构体类型中不同类型的成员变量描述学生的具体属性,用数组类型描述拥有相同属性的一个班级的学生,以便使用循环对数组元素进行统一处理,优化算法。定义结构体数组时,必须先定义结构体,然后再定义该类结构体的数组。例如,定义前述结构体的数组时,可写成:struct student stu40;或:struct student int num ; char name8; char sex; float score2;stu40;6.2.2 结构体数组初始化结构体数组的初始化与其他类型的数组类似。如:struct student int num ; char name8; char sex; float score2;stu2=4001,Liu,M,86.5,97.3,4002,Zheng,F,78.4,86.5;下面用一个简单例子来说明结构体数组的定义、初始化及引用。例6.3 候选人得票统计程序。设有3个候选人,每次输入一个得票候选人的名字,共10张选票,不考虑弃权情况,要求最后输出各人得票结果。程序定义一个全局结构体类型person,它有二个成员name(姓名)和count(得票数)。结构体数组在main函数中定义并初始化。字符数组l_name代表每次输入的被选人的姓名,在每次输入后,与候选人的名字相比,相同则相应候选人的得票数加1。输入统计结束后,输出3个候选人及相应的得票数。程序如下:#include#include struct personchar name20;int count;int main(void)int k,t;char l_name20;struct person leader3=AA,0, BBB,0, AABBB,0;for(k=1;k=10;k+)scanf(%s,l_name);for(t=0;t3;t+)if(strcmp(l_name,)=0) leadert.count+;printf(nNow the results is:n);for(t=0;t成员名例如在图6.2中:p-num、p-name、p-sex、p-score0、p-score1等。符号-由减号和大于号拼接而成。例如有一结构体及结构体变量的定义如下:struct studentchar *name; int age;int *m; char sex2; float salary;char address30;stu3, * p; p = stu ;指针变量对成员age、name的引用表示为:page、pname 或(*p).age、(*p).name应注意以下式子的含义:(1)page+和+page 都使结构体成员age加1。(2)(+p)age、(-p)age使指针p下移或上移,然后再访问age。(3)pname为指针p所指的name地址,*(pm)+相当于*pm+,表示先访问m所指地址上的内容,然后此内容再增加1。例:有数据及结构定义如下: N0. Namesex age1010 LiLin M 1810102 ZhangFun M 1910104 WangMin F 20struct student int num;char name20;char sex ;int age;stu3,*p;p=stu;在TC中,p+1意味着向下移25个字节,而在VC中此结构体占用空间为29个字节,p+1意味着向下移29个字节。(+p)num指转向p的下一结构变量的起始地址,然后取得成员num的值。(p+)num先得到pnum的值,然后p指向下一结构变量的起始地址。(4)p只能指向一个结构体类型数据,即地址类型应相同。p=malloc(sizeof(struct student)是错的。应该把申请到的地址强制转换成结构类型,所以应写成:p=(struct student *)malloc(sizeof(struct student)例6.5 请输入学生学号和3门课成绩,学号为0时表示数据输入结束,程序设计如下:#include #include struct student int num;float score3;void main( )int i=0,n=0; struct student *ptr200;printf(请输入学生学号和3门课成绩,学号为0表示数据输入结束n);do ptri=(struct student *)malloc(sizeof(struct student);scanf(%d%f%f%f,&ptri-num,&ptri-score0,&ptri-score1,&ptri-score2); if(ptri-num=0)break;i+;n+;while(1);free(ptri);for(i=0;inum,ptri-score0,ptri-score1, ptri-score2);6.4 结构体变量作为函数的参数结构体变量可以作为函数的参数。6.4.1 向函数传递结构体变量结构体变量用作函数的参数时,把结构体变量的所有成员传递给被调用函数。此时实际参数为结构体变量的地址或指向结构体变量的指针,形式参数最好为结构体类型的指针变量。例如有一结构体变量定义:struct student *p , stu , s10;p=&stu ;或p=s;函数调用语句为:函数名(p);或: 函数名(&stu); 或:函数名(s);函数定义为: 返回值类型 函数名(struct student *p) 通过以下简单程序,可以了解结构体变量作为函数参数的用法。例6.6 结构体变量作为函数参数的例子。#includestruct pen int i; double j;void count(struct pen *p) double x; x=p-i; x*=p-j; printf(x=%fn,x);void main( ) static struct pen d=3,1.23; count(&d);例6.7 有4个学生,包括学号、姓名、成绩。要求找出成绩最高者的姓名和成绩。#includestruct student int num ; char name20; int score; ;void input(struct student *stu ) int i;for(i=0;i4;i+)scanf(%d %s%d,&stui.num, &,&stui.score);void findmax(struct student *stu) struct student *p;int i,temp=0;float max;for(max=stu0.score,i=0;imax) max=stui.score;temp=i;p=stu+temp;printf(nThe maximum score:n);printf(No:%d name:%s score %4dn,p-num, p-name,p-score);void main( ) struct student stu4,*p=stu; input(stu); findmax(p);程序执行时调用函数input(stu)及findmax(p),函数的参数为结构体变量的地址及指向结构体变量的指针,程序在执行时如输入:101 Lu 91102 Tan 88103 Liu 98104 Fun 87则程序输出为:The maximum score:No:103 name:Liu score 986.5 结构体的嵌套结构体的成员可以是简单的变量,例如:int、float等,也可以是复合类型。若结构体的成员包括结构体,即结构体中又有结构体,则称结构体的嵌套,或嵌套结构体(nested structure)。在下面的例子中,结构体date内嵌在结构体student中:#include struct dateint year;int month;int day;struct studentchar num10;char name20;char sex;struct date birthday;float score;char addr40;void main()struct student comp_stu =78202,Dennis,M,1986,4,20, 576.00,123 BinHong Road;printf(nTheBirthdayof%sis:%d-%d-%d,comp_,comp_stu.birthday.year,comp_stu.birthday.month,comp_stu.birthday.day);6.6 共用体共用体是另一种构造型数据类型,是多种变量共享的一片内存。直观地讲,共用体可以把所在存储单元中相同的数据部分当作不同的数据类型来处理,或用不同的变量名来引用相同的数据部分。共用体常用于需要频繁进行类型转换的场合,及压缩数据字节或程序移植等方面。共用体类型的定义、变量的说明、成员的引用与结构体类型十分相似。共用体变量和结构体变量的本质差别在于两者的存储方式不同:结构体的成员变量存储时各占不同起始地址的存储单元,在内存中呈连续分配,所占内存为各成员所占内存的总和;而共用体的成员变量存储时共用同一起始地址的存储单元,所占内存为最大内存需求的成员所占内存。如图6.3所示。 ch 高字节低字节 t图6.3 共用体1共用体和共用体变量共用体的定义类似于结构体的定义,一般形式如下:union 共用体类型名 共用体成员表列;共用体变量名表列;其中,共用体类型名或共用体变量名表列之一可省略,但两者必留其一。例如,在共用体中有一整型成员al和字符型成员ch,共用体变量reg,以下三种定义方式都可。(1)定义共用体类型p_type的同时声明共用体变量regunion p_typeint al;char ch;reg;(2)省略共用体类型名而直接声明共用体变量regunionint al;char ch;reg;(3)先定义共用体类型p_type,再声明共用体变量regunion p_typeint al;char ch;union p_type reg;2共用体变量的引用方式在通常使用中,只引用共用体的成员变量,引用方式与结构体变量的引用类似。可通过变量名直接引用,也可通过指向共用体类型的指针变量来间接引用。引用的操作符为.、。例如:union p_type reg,*pu; /* 声明了共用体变量reg和指向共用体的指针变量pu */pu=&cvnt; /* 使共用体指针变量pu指向共用体变量reg */reg.al 和pual /*对成员al用共用体变量直接引用和指针的间接引用 */reg.ch 和puch /*对成员ch用共用体变量直接引用和指针的间接引用*/3共用体变量的存储方式举例例6.9 分析程序的的执行结果union dataint a;char b;x;void main( ) x.a=16384; x.b=a; printf(%dn,x.a); 高位 低位0100000000000000分析:成员a占用2字节,成员b占用1字节。当给x.a赋值后,在内存空间存储情况如下所示。当给x.b赋值时,由于x.b与x.a在低字节共用一个存储单元,赋值后的存储情况如下所示。0100000001100001因而当最后输出x.a时的值为16481。答案:16481。例6.10 数组的第0个元素在低位,以下程序输出的是( )。(A) 39 (B)9 (C)38 (D)0#includevoid main( ) union int i2; long k; char c4; r,*s=&r;s-i0=0x39; s-i1=0x38;printf(%xn,s-c0);分析:存储空间的结构示意图如下: r.c3 r.c2 r.c1 r.c000000000001110000000000000111001 r.i1(0x38) r.i0(0x39)sc0即r.c0,因而其值为16进制的39,答案为A。4共用体与结构的嵌套使用共用体与结构的可以嵌套使用。例6.11 下列程序的输出结果为()。#include void main( ) union EXAMPLE struct int x; int y; in ; int a ; int b ; e;e.a = 1; e.b = 2 ;e.in .x = e.a * e.b ; e.in .y = e.a + e.b ;printf(%d %dn , e.in.x ,e.in.y ) ;分析:如图所示共用体有3个成员in、a、b,以占用最大空间的成员in为准,在Visual C+环境中占用内存空间为8字节,其中e.a、e.b、e.in.x占用同一个内存空间,当执行语句e.a=1;时,e.b、e.in.x的值都为1,当执行语句e.a=2;时,e.b、e.in.x的值都为2,e.a*e.b的值赋给e.in.x,e.in.x的值为4,而此时e.a、e.b的值都为4,所以执行语句e.in .y = e.a + e.b;后,e.in.y的值为8。e.in.xe.ae.be.in.y 低位 高位 图6.4 共用体EXAMPLE的空间占用情况程序输出为:4,8。5程序举例通过一个简单程序,更清楚共用体类型的使用。例6.13 两类实体大致属性相同,个别属性不同。现把两类实体(如学生和教师)放置于一个表格中,表格可通过结构体数组来实现,如表6.1所示。要求输入人员数据,然后再输出(简化考虑,测试数据可采用一类实体一例)。若number含s则第四项为class,即John为comput001班的学生;若number含t则第四项为department,即Dennis为comput系的教师。Class和department两个属性对于任何一个实体而言,只能拥有一个,因此它们可通过共用体共用一段内存单元。number属性的值约束暂时简化为s或t开头,除此之外为非法。表6.1 两类实体numberNamesexClass(班)/Department(系)s02001Johnmcomp001t0007Dennismcomput程序如下:#include#define N 2structchar num8;char name20;char sex;unionchar class18;char department10;dep;membN;int main(void)int n;for(n=0;nN;n+)scanf(%s%s%c,membn.num,,&membn.sex);if(membn.num0=s) scanf(%s,membn.dep.class1);else if(membn.num0=t) scanf(%s,membn.dep.department);else printf(input error!);printf(n);for(n=0;ni=x1 ; 将第一个存储单元链入链表p-next=head ;head=p; head p x1 NULL (d)产生第二个存储单元,读入数据并赋值,p-i=x2 ;将第二个数据连到链表前面,完成语句p-next=head;head=p;读入第三个数据。 p head head p x2 x1 x2 x1 next NULL NULL (a)第二个结点连入前 (b) 第二个结点连入后 图65 单向链表例6.14 下列程序的输出结果是( )#include#include#define NULL 0struct node int i;struct node *next;void main( )struct node *head,*p;int n;head= NULL;for(n=0;ni=n+1;p-next=head;head=p;p=head;while(p!=NULL)printf(%4d,p-i);p=p-next;分析:这是堆栈形式的数据结构,循环中给数据域赋值依次为1、2、3、4、5、6、7、8、9、10,因而输出为10、9、8、7、6、5、4、3、2、1。例6.15 建立堆栈, 堆栈是一种先进后出的数据结构。#include#includestruct node char ch;struct node *next;struct node *createnext( ) /*建立堆栈*/struct node *p,*head;char c;head=NULL;while(c=getchar( )!=#) /*读入字符#时结束*/if(p=(struct node *)malloc(sizeof(struct node)=NULL)printf(堆栈溢出n);break;p-ch=c;p-next=head;head=p;return(head);void outnext(struct node *p) /*遍历链表即链表的输出*/while(p)printf(%3c,p-ch);p=p-next;printf(n);void main( )struct node *head;printf(输入一串字符,输入字符#时结束,建立一个堆栈链表n);head=createnext( );/*建立堆栈*/outnext(head); /*遍历键表*/673 队列的的建立所谓队列是指能存取数据的暂时存储单元,数据从队列中的取出过程与入队过程的次序是相一致的,队列通常称为“先进先出”的存储单元。 队列的建立过程为:在队列的建立过程中,所用到的有头指针head、尾指针rear、当前指针p,尾指针rear始终指向队列中最后的结点。(a)链表未建立时:结点数为0,头指针为空。 n=0,head=NULL; head= NULL; (b)产生第一个存储单元,读入数据;p next (c)将第一个数据读入,并将数据存入第一个存储单元,即p-i=x1 ; 将第一个存储单元链入链表p-next=head ;head=p;rear=p; head rear p x1 NULL 图66链入头结点(d)产生第二个存储单元,读入数据并赋值,p-i=x2 ;将第二个数据连到结点x1后面,所用到语句rear-next=p; 把尾指针后移到当前指针rear=p; rear rear head p head x1 p x2 x1 x2 NULL next NULL (a)第二个结点连入前 (b) 第二个结点连入后 图67 单向链表 (e) 申请空间, 读入第三个数据,然后给结点赋值,重复(d)。注意: 最后尾指针指向空。 在队列建立过程中,头指针位置不变。 当前结点连入队列后,尾指针再指向当前指针。例6.16队列的例子#define NULL 0#include#includestruct node int data; struct node *next;void main( )struct node *head ,*rear,*p;int n;head=NULL;for(n=0;ndata=n+1;if(!head)head=p;else rear-next=p;rear=p;rear-next=NULL; p=head; while(p!=NULL) printf(%4d,p-data); p=p-next; printf(n);例6.17 建立一个队例,用来存储输入的字符,当输入#时
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年5月绍兴银行社会招聘15人模拟试卷及一套完整答案详解
- 2025年3月山东大集物流科技集团有限公司及权属子公司公开招聘考前自测高频考点模拟试题参考答案详解
- 2025广西揭阳普宁市公安局招聘警务辅助人员80人考前自测高频考点模拟试题及答案详解(历年真题)
- 2025年潍坊市技师学院公开招聘控制总量工作人员(39人)模拟试卷及答案详解参考
- 2025广东广州市横沥人力资源管理服务有限公司招聘服务外包人员1人模拟试卷及答案详解(名师系列)
- 2025北京第五实验学校招聘38人模拟试卷附答案详解(考试直接用)
- 2025年春季中国邮政储蓄银行合肥市分行校园招聘考前自测高频考点模拟试题及完整答案详解1套
- 2025昆明市官渡区北京八十学校招聘(18人)考前自测高频考点模拟试题附答案详解(突破训练)
- 2025年甘肃陇南事业单位预计将于5月中旬发布考前自测高频考点模拟试题及答案详解(必刷)
- 2025年宝鸡金台区事业单位招聘高层次人才(29人)模拟试卷及一套答案详解
- 胎儿磁共振技术医学应用
- 医防融合知识讲座
- 培养幼儿的语言能力
- 《认识几种常见的岩石》说课稿、教案和教学设计
- 黑布林英语阅读初一年级16《柳林风声》译文和答案
- 广东省监理从业人员网络继续教育平台题库
- YY/T 1268-2023环氧乙烷灭菌的产品追加和过程等效
- 平地机操作规程
- HY/T 0302-2021沸石离子筛法海水提钾工程设计规范
- GB/T 710-2008优质碳素结构钢热轧薄钢板和钢带
- GB/T 18591-2001焊接预热温度、道间温度及预热维持温度的测量指南
评论
0/150
提交评论