第章结构体与共用体_第1页
第章结构体与共用体_第2页
第章结构体与共用体_第3页
第章结构体与共用体_第4页
第章结构体与共用体_第5页
已阅读5页,还剩62页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第第1111章章 结构体与共用体结构体与共用体11.1 结构体类型的定义与变量说明结构体类型的定义与变量说明 为将不同数据类型、但相互关联的一组数据,为将不同数据类型、但相互关联的一组数据,组合成一个有机整体使用,组合成一个有机整体使用,C语言提供一种称为语言提供一种称为“结构结构”的数据结构。的数据结构。例:定义结构体类型例:定义结构体类型student二、二、 定义结构体类型变量的方法定义结构体类型变量的方法1、先定义结构体类型再定义变量名、先定义结构体类型再定义变量名形式:形式: struct 结构体名结构体名 结构体变量名表结构体变量名表 例:在前面已定义结构体类型例:在前面已定义结构

2、体类型struct student 则可定义则可定义:struct student stu1,stu2; stu1,stu2即为即为struct student类型的变量类型的变量2、在定义类型的同时、在定义类型的同时 定义变量定义变量一般形式为一般形式为:struct 结构体名结构体名 成员表列成员表列 变量名表列变量名表列;struct student int num; char name20; char sex; int age; float score; char addr30; student1,student2;3、直接定义结构类型、直接定义结构类型 的变量的变量一般形式为:一般形

3、式为:struct 成员表列成员表列 变量名表列变量名表列; * 不出现结构体名不出现结构体名structint num; char name20; char sex; int age; float score; char addr30; student1,student2;三、结构体类型的嵌套三、结构体类型的嵌套定义:结构体成员又是一个结构体变量定义:结构体成员又是一个结构体变量例例: struct date int month; int day; int year; struct student char name20; char sex; int age; struct date bir

4、thday; stu1,stu2; 嵌套结构体变量的引用:点标记法,但只能对嵌套结构体变量的引用:点标记法,但只能对最低成员最低成员进行赋值或存取、运算。进行赋值或存取、运算。 例:例:stu1.age=20; stu1.birthday.month=7; stu1.birthday.day=31;l 思考以下的引用思考以下的引用 printf(“%d%d%d”,stu1.birthday);( ) stu1.birthday=12, 31, 1988 ; ( )11.2 11.2 结构体类型变量引用与初始化结构体类型变量引用与初始化一、一、 引用引用 不能不能将一个结构体变量作为将一个结构体

5、变量作为一个整体一个整体进行输入进行输入和输出,只能对和输出,只能对各个成员分别输入输出各个成员分别输入输出例如:例如:printf(”%d,%s,%c,%d,%f,%sn”,student1);( )引用:引用: student1.num=102;( )成员的引用方式为:结构体变量名成员的引用方式为:结构体变量名. 成员名成员名 注意:注意:成员运算符成员运算符. 在所有运算符中优先级在所有运算符中优先级最高最高结构体变量引用方法:结构体变量引用方法:struct clock int hour, minute, second;struct date int year, month, day;

6、 struct clock time; today,nextday ;1. 单独引用结构体变量的成员单独引用结构体变量的成员 today.year=2004; today.time.second=15; 2. 结构体变量作为一个整体引用结构体变量作为一个整体引用 nextday=today;二、结构体类型变量的初始化二、结构体类型变量的初始化定义时初始化:将各元素初值放在定义时初始化:将各元素初值放在“ ”里赋里赋值给变量。值给变量。例:例: struct student char name20; char sex; int age; float score; stu1, stu2=“Wang

7、wu”,m,20,88.5;11.3 结构体数组结构体数组一、结构体数组变量的定义一、结构体数组变量的定义与与结构体变量定义类似,只是结构体变量名结构体变量定义类似,只是结构体变量名现为结构体数组变量名现为结构体数组变量名如:如:struct student int num; char name20; char sex; int age; float score; stu30;数组各元素在内存中数组各元素在内存中连续存放,如右图所连续存放,如右图所示。示。101“WGJ”M2888.5“CS”102“DYH”F2688.0“CS”103“DYC”M2478.5“CS”二、结构体数组变量的初始化

8、与引用二、结构体数组变量的初始化与引用初始化:数组初始化:数组=初值表列初值表列;引用:引用: 结构体数组分量结构体数组分量 . 结构体成员结构体成员三、结构体数组程序举例三、结构体数组程序举例例例11-1 计算一个班学生的三门课程的平计算一个班学生的三门课程的平均成绩,并输出该班学生姓名及平均成绩。均成绩,并输出该班学生姓名及平均成绩。程序如下程序如下#include #define MAXSIZE 100struct student char name16;/*学生姓名学生姓名*/ int grade3,average;/*三门成绩,平均分三门成绩,平均分*/ ;void main() i

9、nt i,j,num,s; struct student stuMAXSIZE; printf(Enter number of students:); scanf(%d,&num); for(i=0;inum;i+) printf(Enter name:); scanf(%s,); printf(Enter the grades(3):); for (j=0,s=0;j3;j+) scanf(%d,&stui.gradej); s=s+stui.gradej; stui.average=s/3; for(i=0;i-成员名成员名: : pstpst-num=1

10、001;-num=1001;l注意注意:pstpst不能指向成员:不能指向成员:pstpst=&stu1.num=&stu1.num非法非法; ; 但是但是: : int int * *q; q=&stu1.numq; q=&stu1.num合法合法例例1111- -2 2 用指向结构体变量的指针来访问用指向结构体变量的指针来访问学生的各项数据。学生的各项数据。#include string.hstruct stuint num; char *name; char sex; float score; boy=102,Zhang ping,M,78.5,*p; v

11、oid main()p=&boy; printf(Number=%dnName=%sn,boy.num,); printf(Sex=%cnScore=%4.1fnn,boy.sex,boy.score); printf(Number=%dnName=%sn,(*p).num,(*p).name); printf(Sex=%cnScore=%4.1fnn,(*p).sex,(*p).score); printf(Number=%dnName=%sn,p-num,p-name); printf(Sex=%cnScore=%4.1fnn,p-sex,p-score); 二、指

12、向结构体数组的指针二、指向结构体数组的指针例例11-3 输出数组中各元素中各成员的值。输出数组中各元素中各成员的值。struct student int num; char name20; char sex; int age; ; struct student stu3 =10101,Zhang,M,18, 10102,Li,M,19, 10103,Wang,F,20;/续10101“Zhang”M1810102“Li”M1910103“Wang”F20main() /*续上页*/ struct student *p; printf(No. Name Sex Agen); for (p=stu

13、; pnum, p-name, p-sex, p-age); 10101“Zhang”M1810102“Li”M1910103“Wang”F20注意事项注意事项: :如果如果p的初值为的初值为stu,即指向结构体数组的第,即指向结构体数组的第1个元素个元素stu0,则,则p+1指向下指向下1个元素的起始地个元素的起始地址址stu1。区别:区别:(+p)- -num 和和 (p+)- -nump已定义为指向已定义为指向struct student类型的指针变类型的指针变量,则量,则p只能指向只能指向1个结构体类型数据,而不能个结构体类型数据,而不能指向结构体类型的某一成员(即指向结构体类型的某一

14、成员(即p的地址不是的地址不是成员的地址)。成员的地址)。如:如:p=&;( 错误错误)三、用结构体变量和指向结构体的指针作函数参数三、用结构体变量和指向结构体的指针作函数参数将一个结构体变量的值传递给另一个函数,有将一个结构体变量的值传递给另一个函数,有3种方法:种方法:(1)用结构体变量的成员作参数。用结构体变量的成员作参数。 例如,用例如,用stu1num或或stu2name作函数实作函数实参,将实参值传给形参。参,将实参值传给形参。 “值传递值传递”方式。方式。(2) 用结构体变量作实参。用结构体变量作实参。 “值传递值传递”的方的方式式,改变,改变的形参值不能

15、返回主调函数,因此一般较少用这种方法。的形参值不能返回主调函数,因此一般较少用这种方法。(3) 用指向结构体变量用指向结构体变量(或数组或数组)的指针作实参,将结的指针作实参,将结构体变量构体变量(或数组或数组)的地址传给形参。的地址传给形参。例例11-4 有一个结构体变量有一个结构体变量stu,内含学生学号、姓名和,内含学生学号、姓名和3门课的成绩。要求在门课的成绩。要求在main函数中赋以值,在另一函数函数中赋以值,在另一函数print中将它们打印输出。今用结构体变量作函数参数。中将它们打印输出。今用结构体变量作函数参数。#include #define FORMAT %dn%sn%fn%

16、fn%fn struct student int num; char name20; float score3; ;main() void print(struct student); struct student stu; stunum=12345; strcpy(stuname,Li Li); stuscore0=675; stuscore1=89; stuscore2=786; print(stu); void print(struct student stu)printf(FORMAT,stu.num,, stu.score0, stu.score1,stu.score

17、2); printf(n);例例11.5 将上题改用指向结构体变量的指针作实参将上题改用指向结构体变量的指针作实参#include #define FORMAT %dn%sn%fn%fn%fn struct student int num; char name20; float score3; ;main() void print(struct student *); struct student stu; stunum=12345; strcpy(stuname,Li Li); stuscore0=675; stuscore1=89; stuscore2=786; print(&st

18、u); void print(struct student *stu)printf(FORMAT,(*stu).num, (*stu).name, (*stu).score0, (*stu).score1, (*stu).score2); printf(n);11.5 11.5 链表链表 一、概述一、概述 链表存储结构是一种动态数据结构,其特链表存储结构是一种动态数据结构,其特点是它包含的数据对象的个数及其相互关系可以点是它包含的数据对象的个数及其相互关系可以按需要改变,存储空间是程序根据需要在程序运按需要改变,存储空间是程序根据需要在程序运行过程中向系统申请获得,链表也不要求逻辑上行过程中向

19、系统申请获得,链表也不要求逻辑上相邻的元素在物理位置上也相邻,它没有顺序存相邻的元素在物理位置上也相邻,它没有顺序存储结构所具有的弱点。储结构所具有的弱点。 1 1链表结构链表结构(1)头指针变量)头指针变量head指向链表的首结点。指向链表的首结点。(2)每个结点由)每个结点由2个域组成:个域组成:1)数据域)数据域存储结点本身的信息。存储结点本身的信息。2)指针域)指针域指向后继结点的指针。指向后继结点的指针。(3)尾结点的指针域置为)尾结点的指针域置为“NULL(空)(空)”,作,作为链表结束的标志为链表结束的标志2 2、链表结构的定义、链表结构的定义struct studentchar

20、 name10; struct student *next; ; next为为student类型指针变量,指向下一个结类型指针变量,指向下一个结点的指针域。点的指针域。结点的变量或指针变量的定义:结点的变量或指针变量的定义:struct student node,*head;lnode可以存放一个学生结点可以存放一个学生结点l指针指针head可以存放学生结点的地址。可以存放学生结点的地址。 二、动态分配存储空间库函数二、动态分配存储空间库函数1malloc函数函数其函数原型为其函数原型为 void *malloc(unsigned int size); malloc在内存的动态存储区中分配一个

21、在内存的动态存储区中分配一个size长度的连续存储空间。长度的连续存储空间。例如:例如:int *p;p=(int *)malloc(8); lp指示系统分配的指示系统分配的4个整型存储单元的起始地址个整型存储单元的起始地址l也可看成包含也可看成包含4个数组元素的个数组元素的p数组:数组:p0,p1,p2,p32 calloc函数函数其函数原型为其函数原型为 void *calloc(unsigned n,unsigned sie);其作用是在内存的动态区存储中分配其作用是在内存的动态区存储中分配n个长度为个长度为sie的连续空间。函数返回一个指向分配域起始地的连续空间。函数返回一个指向分配域

22、起始地址的指针;如果分配不成功,返回址的指针;如果分配不成功,返回NULL。用用calloc函数可以为一维数组开辟动态存储空间,函数可以为一维数组开辟动态存储空间,n为数组元素个数,每个元素长度为为数组元素个数,每个元素长度为size。3 free函数函数其函数原型为其函数原型为void free(void void free(void * *ptrptr); ); 函数函数free释放由指针变量释放由指针变量ptr所指示的内存区域。所指示的内存区域。 例如:例如:free(p); 通过函数通过函数free将已分配的内存区域交还系将已分配的内存区域交还系统,使系统可以重新对其进行分配。统,使系

23、统可以重新对其进行分配。例例11-5 11-5 动态定义数组。动态定义数组。#include void main()int n,i,*p; printf(n=); scanf(%d,&n); p=(int *)malloc(n*sizeof(int); for(i=0;in;i+) pi=i*i; for(i=0;inext=NULL;(3)如果)如果head为为NULL,则,则 head=p; 否则否则 last-next=p;(4)last=p; (5)重复()重复(2)(4),继续建立新结点。),继续建立新结点。例例11.6 写一函数建立一个有写一函数建立一个有3名学生数据的单向

24、动名学生数据的单向动态链表。态链表。建立链表的函数可以如下:建立链表的函数可以如下:#define NULL 0#define LEN sizeof(struct student)struct studentlong num; float score; struct student*next; ; int n; /*n为全局变量,本模块中各函数均为全局变量,本模块中各函数均可使用它可使用它*/struct student *creat(void)/*定义函数。此函数带回一定义函数。此函数带回一个指向链表头的指针个指向链表头的指针*/struct student*head; struct stu

25、dent*p,* last ; n=0;p= last =( struct student*) malloc(LEN);/*开辟一个开辟一个新单元新单元*/ scanf(%ld,%f,&p-num,&p-score); head=NULL; while(p-num!=0)n=n+1; if(n=1)head=p; else last -next=p; last =p; p=(struct student *)malloc(LEN); scanf(%ld,%f,&p-num,&p-score); last-next=NULL; return(head); main

26、() creat(); /*调用调用creat函数后建立了一个单函数后建立了一个单向动态链表向动态链表*/ 2 . 2 . 头插法建立单链表头插法建立单链表特点特点:新产生的结点作为新的链表头插入链表。新产生的结点作为新的链表头插入链表。操作步骤:操作步骤:(1)head=NULL;(2)生成新结点,指针变量)生成新结点,指针变量p指向该结点;指向该结点;(3)p-next=head; head=p; (4)重复()重复(2)(3),继续生成下一个链表),继续生成下一个链表结点。结点。 ( (二二) )、链表的访问、链表的访问1. 输出链表结点输出链表结点操作步骤:操作步骤:(1)得到链表头结

27、点的地址)得到链表头结点的地址 head;(2)指针变量)指针变量p=head;(3)输出)输出p所指结点的成员值所指结点的成员值;(4)p后移一个结点,后移一个结点,p=p-next;(5)重复()重复(3)(4),直到链表为空。),直到链表为空。 例例11.7 编写一个输出链表的函数编写一个输出链表的函数print。 void print(struct student *head)struct student *p; printf(nNow,These %d records are:n,n); p=head; if(head!=NULL) do printf(%ld %5.1fn,p-nu

28、m,p-score); p=p-next; while(p!=NULL); 2. 2. 统计链表结点的个数统计链表结点的个数一般情况下,各个单链表中结点个数是随机一般情况下,各个单链表中结点个数是随机的,要想知道表中结点数目,必须从表头开的,要想知道表中结点数目,必须从表头开始访问到表尾,逐个统计出结点数目。始访问到表尾,逐个统计出结点数目。 3. 查找链表的某个结点查找链表的某个结点在链表上查找符合某个条件的结点,也必须在链表上查找符合某个条件的结点,也必须从链表头开始访问链表。从链表头开始访问链表。( (三三) )、链表的插入操作、链表的插入操作在第在第n个结点之后插入个结点之后插入1个新

29、结点个新结点 ,插入操作步骤:插入操作步骤:(1)q指针指向新结点,指针指向新结点,i为已访问过的结点数;为已访问过的结点数;(2)p=head,r指向指向p结点的前一个结点;结点的前一个结点;(3)i+,r=p,p=p-next,p结点往前移动一个结点;结点往前移动一个结点;(4)若)若inext=head,head=q;(6)若)若inext=q,q-next=NULL;(7)否则,将)否则,将q结点插入到第结点插入到第n个结点之后,即插入到个结点之后,即插入到r结点与结点与p结点之间:结点之间:r-next=q,q-next=p;(8)返回链表头)返回链表头head。( (四四) )、链

30、表的删除操作、链表的删除操作删除第删除第n个结点个结点 (1)p=head,q指针指向指针指向p所指结点的前所指结点的前1个结点;个结点;(2)i为访问过的结点数目;为访问过的结点数目;(3)i+,q=p,p=p-next,p、q移动移动1个结点;个结点;(4)若)若p!=NULL且且inext;(6)若)若head=NULL,链表为空,不能删除;,链表为空,不能删除;(7)若)若p=NULL,第,第n个结点不存在,不能删除;个结点不存在,不能删除;(8)找到第)找到第n个结点,删除个结点,删除p结点:结点: q-next=p-next; p的前的前1个结点的个结点的next值赋值为值赋值为p

31、的的next域;域;(9)返回)返回head。 11.611.6共用体共用体一、共用体的概念一、共用体的概念 使几个不同的变量共占同一段内存的结构,使几个不同的变量共占同一段内存的结构,称为称为“共用体共用体”类型的结构。类型的结构。定义共用体类型变量的方法:定义共用体类型变量的方法:(1)union共用体名共用体名 成员表列成员表列 变量表列;变量表列;例如:例如:union data int i; char ch; float f; a,b,c;(2)将类型声明与变量将类型声明与变量定义分开:定义分开:union dataint i; char ch; float f; ;union da

32、taa,b,c;(3)直接定义共用体变量直接定义共用体变量 unionint i; char ch; float f; a,b,c; 结构体变量所占内存长度是各成员占的内存长结构体变量所占内存长度是各成员占的内存长度之和。每个成员分别占有其自己的内存单元。度之和。每个成员分别占有其自己的内存单元。 可以看到,可以看到,“共用体共用体”与与“结构体结构体”的的定义形式相似。但它们的含义是不同的。定义形式相似。但它们的含义是不同的。 共用体变量所占的内存长度等于最长的成员共用体变量所占的内存长度等于最长的成员的长度。的长度。二、共用体变量中成员的引用方式二、共用体变量中成员的引用方式 只有先定义了

33、共用体变量才能引用它。而且不能引只有先定义了共用体变量才能引用它。而且不能引用共用体变量,而只能引用共用体变量中的成员。用共用体变量,而只能引用共用体变量中的成员。例如,前面定义了例如,前面定义了a、b、c为共用体变量,下面的引用为共用体变量,下面的引用方式是正确的:方式是正确的: a.i (引用共用体变量中的类型变量引用共用体变量中的类型变量i) a.ch (引用共用体变量中的字符变量引用共用体变量中的字符变量ch) a.f (引用共用体变量中的实型变量引用共用体变量中的实型变量f)不能只引用共用体变量,例如:不能只引用共用体变量,例如: printf(“%d”,a)是错误的是错误的。三、共

34、用体类型数据的特点三、共用体类型数据的特点(1) 同一个内存段可以用来存放几种不同类型的成同一个内存段可以用来存放几种不同类型的成员,但在每一瞬时只能存放其中一种,而不是同时员,但在每一瞬时只能存放其中一种,而不是同时存放几种。存放几种。(2) 共用体变量中起作用的成员是最后一次存放的成共用体变量中起作用的成员是最后一次存放的成员,在存入一个新的成员后原有的成员就失去作用。员,在存入一个新的成员后原有的成员就失去作用。(3) 共用体变量的地址和它的各成员的地址都是同共用体变量的地址和它的各成员的地址都是同一地址。一地址。例如:例如:&a、&a.i、&a.c、&a

35、.f 都是同一地址值。都是同一地址值。(4) 不能对共用体变量名赋值,也不能企图引用变不能对共用体变量名赋值,也不能企图引用变量名来得到一个值,又不能在定义共用体变量时对量名来得到一个值,又不能在定义共用体变量时对它初始化。它初始化。例如,下面这些都是例如,下面这些都是不对不对的:的: union int i; char ch; float f; a=1,a,1.5;(不能初始化不能初始化) a=1; (不能对共用体变量赋值不能对共用体变量赋值) m=a; (不能引用共用体变量名以得到一个值不能引用共用体变量名以得到一个值)(5) 不能把共用体变量作为函数参数,也不能使不能把共用体变量作为函数

36、参数,也不能使函数带回共用体变量,但可以使用指向共用体变函数带回共用体变量,但可以使用指向共用体变量的指针量的指针(与结构体变量这种用法相仿与结构体变量这种用法相仿)。(6) 共用体类型可以出现在结构体类型定义中,共用体类型可以出现在结构体类型定义中,也可以定义共用体数组。反之,结构体也可以出也可以定义共用体数组。反之,结构体也可以出现在共用体类型定义中,数组也可以作为共用体现在共用体类型定义中,数组也可以作为共用体的成员。的成员。11.7枚举类型枚举类型1枚举类型的定义枚举类型的定义 enum 枚举类型名枚举类型名 取值表取值表;例如,例如,enum weekdays Sun,Mon,Tue

37、,Wed,Thu,Fri,Sat; 如果一个变量只有几种可能的值,可以定义为如果一个变量只有几种可能的值,可以定义为枚举类型。所谓枚举类型。所谓“枚举枚举”是指将变量的值一一列举是指将变量的值一一列举出来,变量的值只限于列举出来的值的范围内。出来,变量的值只限于列举出来的值的范围内。枚举变量的定义枚举变量的定义与结构变量类似与结构变量类似(1)间接定义)间接定义例如,例如,enum weekdays workday;(2)直接定义)直接定义例如,例如,enum weekdays Sun,Mon,Tue,Wed,Thu,Fri,Sat workday;说明说明(1)枚举型仅适应于取值有限的数据。)枚举型仅适应于取值有限的数据。例如,根据现行的历法规定,周天,年例如,根据现行的历法规定,周天,年个月。个月。(2)取值表中的值称为枚举元素,其含义由程序)取值表中的值称为枚举元素,其含义由程序解释。解释。例如,不是因为写成例如,不是因为写成“Sun”就自动代表就自动代表“星期星期天天”。事实上,。事实上, 枚举元素用什么表示都可以。枚举元素用什么表示都可以。(3)枚举元素作为常量是有值的)枚举元素作为常量是有值的定义时定义时的顺序号(从开始),所以枚举元素可以进行的顺序号(从开始),所以枚举元素可以进行比较,比较规则是:序号大者为大!比较,比较规则是:序号大者为大!例如

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论