第08章:结构体、共用体与枚举类型,C语言程序设计课件,与中南大学出版社教材相配套.ppt_第1页
第08章:结构体、共用体与枚举类型,C语言程序设计课件,与中南大学出版社教材相配套.ppt_第2页
第08章:结构体、共用体与枚举类型,C语言程序设计课件,与中南大学出版社教材相配套.ppt_第3页
第08章:结构体、共用体与枚举类型,C语言程序设计课件,与中南大学出版社教材相配套.ppt_第4页
第08章:结构体、共用体与枚举类型,C语言程序设计课件,与中南大学出版社教材相配套.ppt_第5页
已阅读5页,还剩74页未读 继续免费阅读

下载本文档

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

文档简介

C语言程序设计,第8章结构体、共用体与枚举类型,8.1概述8.2结构体定义8.3结构体变量的使用8.4结构体数组8.5结构体与指针*8.6结构体与函数*8.7共用体*8.8枚举类型8.9用户定义类型本章小结,8.1概述,在学习本章之前,我们已经讨论过的数据类型有简单类型(整型、实型、字符型)、数组类型和指针类型。简单变量是一个单个的变量,变量与变量之间无固定内在的联系,分别表示独立的数据,无从属关系。数组则表示是同一类型数据的集合,并用下标把数组的各个元素有序地联系起来。指针类型主要是用于动态存储分配,它们适合于各自不同的用途。但这些数据类型有时还难以处理一些较为复杂的数据结构,例如:在数据处理领域中,常常要求把一些不同类型的数据作为一个整体来处理。上面提到的在中国计算机软件专业技术资格和水平考试中,用来描述每一个考生的信息,由准考证号(长整型)、姓名(字符型数组)、性别(字符型)、年龄(整型)、报考级别(,字符数组)和成绩(实型)组成。它们的处理对象均为参加软考的应试人员,但又都分别属于不同的类型。这时如果使用简单的变量来表述,则难以反映出它们之间的内在联系,用数组则无法容纳不同类型的元素。因此,如同其它高级语言(如PASCAL,COBOL等)一样,C语言提供了一种称之为结构体的类型(Structure),来描述这种由不同类型数据组成的“复杂类型”。如图8-l所示。,上图表示的结构体,可用下列程序语句来描述,稍后我们会进行详细的解释。structexamineeslongnum;charname20;charsex;intage;chargrade2;floatscore;,8.2结构体定义,上面我们用C语言定义了一个如图8-1所示的由不同类型的数据项所组成的复合类型,这种类型就称之为结构体类型。组成结构体的每个数据称为该结构体的成员项,有时又称为结构体分量。在程序中若要使用结构体时,就必须首先对结构体的组成进行描述,这称为结构体的定义。结构体的定义应说明该结构体是由哪几个成员项组成的,以及每个成员项具有的数据类型。,8.2.1结构体类型的定义,定义一个结构体类型的一般形式为:struct结构体类型名数据类型成员名1;数据类型成员名2;数据类型成员n;,结构体类型和基本数据类型的主要区别如下:(1)结构体类型定义中的每一个成员项,表示该结构体的分量或称“域”,它们并不是变量。例如,上面定义的num,name,sex,age等均为结构体类型structexaminees的成员,而不能称为变量名。因此,在一个函数中,允许另外定义与结构体类型成员相同名的变量,它们各自代表不同的对象。例如:structexamineesintage;chargrade2;floatscore;/*定义age、grade、score为结构体类型成员*/intage;chargrade2;floatscore;/*定义age、grade、score为变量*/,(2)基本数据类型(如int,char,float等)是一个具体的数据类型,一旦定义后其说明的变量就分配了固定字节的内存空间,按指定的形式存放。例如,一个整型变量占2个字节并按定点形式存放。而“结构体类型”只是一个抽象的数据类型,它只表示了“由若干不同类型数据项组成的复合类型”,它由哪些成员项组成,占多少字节等信息。(3)与基本数据类型不同,系统没有预先定义结构体类型,凡需使用结构体类型数据的,都必须在程序中先行加以定义。定义了一个结构体类型后,系统并没有为所定义的各成员项分配相应的存储空间,这是因为定义类型而不是定义变量。定义一个类型只是说明该类型的结构,即告诉系统它由哪些类型的成员构成,各占多少字节、按什么形式存储,并把它们当成一个整体来处理。应当明确,只有在定义了变量以后,系统才为所定义的变量分配相应的存储空间。,8.2.2结构体变量定义,结构体作为一种数据构造类型在C语言程序中必须经过“定义初始化引用”的过程。下面我们分别来进行讨论。我们首先来讨论结构体类型变量的定义。定义一个结构体变量,可以采用以下三种不同的方法:1.先进行结构体类型的定义,然后再进行结构体变量的定义例如,上面已定义了一个结构体类型structexaminees后,现在就可以用它来定义相应类型的变量了。例如:structexamineesstud1,stud2;,其中structexaminees称为结构体类型名,stud1,stud2称为结构体变量名。也称变量stud1,stud2具有structexaminees类型的结构。如图8-2所示:应当说明:(1)一旦进行了上述结构体变量的定义后,变量stud1和stud2就与C语言中的其它变量一样,系统将根据组成该变量各成员的不同类型,分配相应的存储空间。(2)结构体变量名末尾必须带有一个分号,用以表示变量表结束。,(3)定义一个结构体类型变量与定义一个标准类型变量不同。例如,在定义一个整型变量时,只需指出int变量名即可。但在定义结构体类型变量时不仅要求指定变量为结构体类型,而且要求指定为某一特定的结构体类型。因此将上述考生结构体类型变量定义成:examineesstud1,stud2或者:structstud1,stud2;都将是错误的。(4)定义了一个结构体类型后,就可以多次用来定义各种具体的结构体类型变量。(5)为了使用方便,通常在程序开头,定义一个符号常量来代表一个结构体类型:#defineSTUDstructexaminees这样在程序中,STUD就与structexaminees完全等效。,STUDlongnum;charname20;intage;chargrade2;floatscore;这样定义类型后,就可以直接用STUD来定义变量了;STUDstud1,stud2;于是用该方法定义结构体变量就和用int,char,float定义基本变量的形式一样,不必再写struct关键字。,2.在定义结构体类型的同时定义结构体变量用该方式定义的一般形式是:struct结构体类型名数据类型成员名1;数据类型成员名2;数据类型成员名n;结构体变量名表;例如:上述软件考试的考生结构体类型变量又可以用该方法定义如下:,structexamineeslongnum;charname20;charsex;intage;chargrade2;floatscore;stud1,stud2;这种定义方式较为紧凑,既定义了类型,又定义了变量。如果还需定义其它同类型的结构体变量,还可用:structexamineesstud3,stud4;这样表示又定义了两个和变量stud1,stud2同类型的结构体变量stud3,stud4。,3.直接定义结构体类型变量其一般形式为:struct数据类型成员名1;数据类型成员名2;数据类型成员名n;结构体变量名表;,例如上述定义又可写成:structlongnum;charname20;charsex;intage;chargrade2;floatscore;stud1,stud2;这种定义方法与上面第二个定义方法相比较,只是省略了结构体类型名examinees。因此就不能再用它来定义其它变量。下面的定义则为非法的:structstud3,stud4;,上述三种结构体变量的定义方法,可根据实际处理情况选择使用。但应当注意以下几点:(1)类型和变量是不同的概念,不能混同。在定义一个结构体变量时,应先定义其类型,然后再定义变量为该类型。只有经过变量定义后,才能对变量进行赋值、存取或运算操作处理;而不能对一个类型进行相应的操作运算,并且系统只能为变量分配存储空间。(2)对结构体类型中的成员项(或称“域”,“结构分量”)可以单独引用,其作用相当于基本变量。有关引用方法将在后面讨论。(3)允许结构体类型中的成员项是结构体变量,例如上述考生结构体类型变量中,当我们将年龄项改为出生日期时,其结构形式如图8-3所示:,这样,我们就需先定义一个structdate类型,它表示出生日期,应包括三个成员项month(月)、day(日)、year(年)。然后在structexaminees结构体中,将成员项birthday定义成:structdate结构体类型。例如:,structdateintmonth;intday;intyear;structexamineeslongnum;charname20;structdatebirthday;chargrade2;floatscore;stud1,stud2;,8.3结构体变量的使用,在结构体类型变量说明的同时,可以给它的每个成员项赋初值,这称之为结构体类型变量的初始化。对结构体变量的初始化规则与数组相同,即只有当结构体变量为全局变量或为静态变量时,才能进行初始化。,8.3.1结构体变量初始化,1.对外部存储类型的结构体变量进行初始化例如:structexamineesstructexamineesstud1=20101,“LiPing”,“M”,18,“2C”,86.5;main()上面结构体变量studl为外部全局变量,在初始化时,按照所定义的结构体类型的数据结构,依次写出各初始值,在编译时,就将它们赋给变量中各成员。,2.对静态存储类型的结构体变量进行初始化例如:main()staticstructexamineeslongnum;charname20;charsex;intage;chargrade2;floatscore;stud1=20101,“LiPing”,M,18,“2C”,86.5,应当指出对结构体变量进行初始化时要注意以下两点:(1)初始化是指对结构体变量斌与初值,而不是对结构体类型中的各成员项赋值,因此,下述初始化形式是错误的:staticstructexamineeslongnum=20101;charname20=“LiPing”;charsex=Mintage=18;chargrade2=“2C”;floatscore=86.5;stud1;,(2)如果一个结构体类型内又嵌套另一个结构体类型(如图8-3所示的形式),则对该结构体变量初始化时,仍按顺序写出各个初始值:staticstructexamineesstud1=20101,”LiPing”,M,10,12,1978,”2C”,86.5其中10,12,1978为birthday的初值。,8.3.2结构体变量引用,结构体是由不同数据类型的若干数据集合而成。在程序中使用结构体时,一般不允许把结构体作为一个整体参加操作处理,而应通过对结构体的各个成员项的引用来实现各种运算和操作。1.引用结构体变量中的一个成员由于结构体变量是一个整体,要访问其中一个成员,必须先找到这个结构体变量,然后再从中找出其中的一个成员。引用的一般形式:结构体变量名.成员名其中圆点符号称为成员运算符。例如上面定义的结构中要想访问stud1项,应写成:stud1.age。,访问stud1.age的步骤如图8-4所示:即第一步先访问结构体变量stud1,找到该变量的起始地址后,第二步从stud1所分配的内存区间中找到age成员项对应的数据。说明:(1)如果在同一函数中又另外定义了一个age简单变量,它将由系统另外分配存储空间,与stud1.age分属不同的变量。stud1.age表示结构体变量中的age成员项,而age表示简单变量age。,(2)若定义stud1,stud2均为同一结构体类型structexaminees的两个变量,则当引用两个变量中的age成员项时,应分别用stud1.age和stud2.age,它们表示内存中不同的存储单元并且各自有不同的值。(3)如果一个结构体中又嵌套一个结构体,则要访问一个成员时,应采取逐级访问的方法。例如:图8-3中所示的嵌套结构体变量,若要访问考生l的出生年份时,则用:stud1.birthday.year。而不能写成:year或birthday.year或stud1.year。(4)允许对结构体变量的成员进行各种相应的运算,但运算的规则应遵循定义结构体时各成员项类型的规则。例如:stud1.num的类型是长整型,因此,它适合于长整型简单变量所允许的所有运算。如算术运算、关系运算、逻辑运算和赋值运算等。,例如:stud1.num=20101(赋值运算)stud2.num=stud1.num+1(算术运算)stud1.age+(自加运算)stud2.score=60.0(关系运算)addr=执行stud2=stud1这个赋值语句时,完成将stud1变量中各成员项逐个依次赋给stud2中相应的各成员。当然要求stud1和stud2必须具有完全相同的数据类型。但必须注意,不允许将一组常量直接赋给一个结构体变量。如下面赋值语句是非法的:stud2=20102,“LiuHao”,F,20,2P,90,3.结构体变量的输入和输出结构体变量的输入输出,同样要求必须指明结构体变量所对应的各成员项。例如:scanf(%ld,%s,%c,%d,,8.4结构体数组,根据C语言规定,凡具有相同数据类型的数据均可以组成数组。例如前面讨论过的整型数组、实型数组、字符型数组以及布尔型数组等。根据同样的原则,具有相同结构类型的结构体也可以组成数组,称之为结构体数组,即结构体数组中的每一个元素都是结构体变量。,8.4.1结构体数组定义与初始化,1.结构体数组的定义定义结构体数组的方法和定义结构体变量的方法相类似,只是需进行数组定义说明。定义方法可以采用以下三种方法:(1)先进行结构体类型的定义,然后再定义结构体数组例如:structexamineeslongnum;charname20;charsex;intage;chargrade2;floatscore;structexamineesstud30;,上面定义了一个结构体数组stud,它由30个元素组成,每个元素都是structexaminees类型。该数组在内存中占有一段连续的存储空间,相当于定义了一张软件考试的考生信息表。如图8-5所示:(2)同时进行结构体类型和结构体数组的定义例如:structexamineeslongnum;floatscore;stud30;,(3)直接定义结构体数组而不需定义结构体类型名例如:structlongnum;floatscore;stud30;以上三种定义方法的效果均相同,定义后该数组的每个元素占33个字节,30个元素共占990个字节空间。它们在内存中的存储示意图如图8-6所示:,2.结构体数组的初始化结构体数组在引用前可以进行初始化,即对结构体变量中的各个元素赋初始值。但C语言规定只能对全局的或静态存储类型的结构体数组初始化。例如:structexamineeslongnum;charname20;charsex;intage;chargrade2;floatscore;stud3=20101,“LiPing”,M,18,“2C”,86.5,20102,“LiHao”,F,20,“2P”,90,20103,“ChenJun”,F,18,“2C”,92.5;,这样,程序在编译时,就完成将每个内层大括号中的数据,依次赋给所定义数组的每一个元素。另外,由于在编译时,系统会根据给出初值的结构体常量的个数自动确定数组元素的个数,因此定义数组时,允许元素个数可以不指定,即可以写成以下形式:stud=,;也可以先定义结构体类型,然后定义数组为该结构体类型,并在定义数组时进行初始化。因此,又可以写成以下形式:structexamineeslongnum;floatscore;structexamineesstud(),;,8.4.2结构体数组引用,对于结构体数组的引用就是指对结构体数组元素的引用。由于结构体数组元素就相当于结构体变量,因此前面讨论的关于引用结构体变量的方法也同样适用于结构体数组元素。1.结构体数组元素中某一成员的引用例如:引用stud()数组中第2个元素的num成员项时则写成:stud(2).num,显然其值为20103,引用该数组第0个元素的name成员项时则写成:stud(0).name,显然其值为“LiPing”。2.结构体数组元素的赋值可以将一个结构体数组元素赋值给同一结构体类型的数组中另一个元素,或者赋给同一类型的变量。,例如:下面定义了一个同类型的结构体变量和数组:structexamineesstudl,stud30;则下面的赋值语句是合法的:studl=stud(2);stud(1)=stud(0);stud(29)=studl;3.结构体数组元素的输入输出结构体数组元素的输入输出只能将单个成员项进行输入输出,而不能把结构体数组元素作为一个整体直接进行输入输出。例如:scanf(“%ld”,stud0.num);scanf(“%s”,);printf(“%ld,%s,%c,%d,%s,%fn”,stud(0).num,,stud0.sex,stud0.age,stud0.grade,stud0.score);以上均为合法的输入输出语句。,而:scanf(“%ld”,stud(0);printf(“%ld”,stud(0);均为非法的输入输出语句。特别要建议的是,不要用一个scanf函数输入不同类型的数据。如用下列输入语句:scanf(%ld,%s,%c,%d,%s,%f,stud0.num,,stud0.sex,stud0.age,stud0.grade,stud0.score);如果从键盘输入:20101,LiPing,M,18,2C,86.5将会出现错误。这是因为在输入字符串数据时,遇到空格符就表示字符串输入结束,因此上述输入中,只将“Li”输入给了stud(0).name,而将“Ping”作为下一个数据输入给了stud0.sex,当然也就出错了。因此,通常对于结构体数组元素的输入操作都采用,gets字符串输入函数。gets函数专用于接收从键盘输入的字符串,当输入“回车”键时,就把回车以前的字符送到字符数组中,然后使用C语言标准函数库提供的下述转换函数将字符串转换成相应类型的数据:(1)将字符串转换成整数的函数:atoi()(2)将字符串转换成实数的函数:atof()(3)将字符串转换成长整数的函数:atol()当然在引用上述转换幽数时,必须在#include命令中包含“stdlib.h”文件。,8.4.3结构体数组使用实例,下面我们通过一个例子来说明结构体数组的定义和引用。【例8-1】某单位有30人参加2005年全国计算机软件专业技术资格和水平考试,现需要将每一名考生的准考证号、姓名、性别、年龄、报考等级和考试成绩录入计算机,并统计出平均分和及格率。程序如L8-1.c,8.5结构体与指针,1结构体变量指针结构体指针是一个指针变量,用以指向一个结构体变量,即为指向该变量所分配的存储区域的首地址。例如:我们在前面定义过一个结构体类型structexaminees,现在可以用下面形式定义一个指向该类型数据的指针变量:structexaminees*p;则表示指针变量p可以用来指向任何一个属于structexaminees类型的结构体变量。,8.5.1指向结构体的指针,结构体指针在程序中定义的一般形式如下:struct结构名*结构指针变量名;其中结构体类型名必须是已经定义过的结构。结构体指针的定义规定了它的数据特性,并为结构体指针本身分配了一定的存储空向、但此时指针的内容还没有确定,即它的具体指向是不定的。因此,我们在使用指针之前,必须通过初始化给具体结构体的存储地址值进行赋值。当然要求结构体指针和结构体必须具有相同的结构类型。指针变量还可以用来指向结构体数组中的元素。2.结构体变量指针的应用下面我们通过例子来说明指向结构体变量指针的应用。【例8-2】结构体变量指针的应用。程序如L8-2.c,在定义了一个指针变量p以后,必须使它指向一个具体的变量,赋值语句“p=floatb;charc;unioninfox;表示已定义了一个共用体类型unioninfo,同时定义了一个共用体变量x,系统将分配给变量x中各个成员项共同占用同一个存储空间。我们用图8-12来表示:上图表示共用体变量x的各成员项a、b、c均从同一个地址开始存放,其中整型量a占2个字节,实型量b占4个字节,字符量c占1个字节。但该共用体,变量所占内在单元一共是4个字节。可见共用体和结构体定义形式相似,但含义不同:共用体变量所占内存单元数为其成员中占用最长的单元的长度,各成员项共同使用一个存储空间;而结构体变量所占内存单元数以其各成员所占单元的总和为长度,每个成员项分别占有自己的存储空间。共用体变量的定义也可采用下面两种形式:(1)将共用体类型定义和变量定义合在一起。例如:unioninfointa;floatb;charc;x;,(2)缺省共用体类型名,直接定义共用体变量。unioninta;floatb;charc;x;,8.7.2共用体的引用,共用体类型变量一经定义后,就可以在程序中加以引用。1.用成员运算符引用共用体变量中的一个成员项如同引用结构体变量中的成员项一样,可以用成员运算符“.”来引用指定共用体变量的成员项。引用的一般形式为:共用体变量名.成员项例如上面共用体变量定义后,可执行下面赋值语句:x.a=5;/*引用共用体变量x的成员项a*/x.b=3.14;/*引用共用体变量x的成员项b*/x.c=$;/*引用共用体变量x的成员项c*/,值得注意的是,一个共用体变量不能同时存放多个成员的值,而只能存放最后一条赋值语句所赋的值。上述三条赋值语句顺序执行后,共用体变量x的值只能是成员项x.c的值,即$的ASCII码36。2.通过指针变量引用共用体变量中的成员项。引用的一般形式为:指针变量-成员项;例如:unioninfo*p,x;p=/*引用共用体变量x的成员项c*/其中定义p为指向unioninfo共用体类型的指针变量,先使p指向共用体变量x,其它三条赋值语句执行的结果如同上面用圆点成员运算符进行赋值一样。,3.两个同类型共用体变量的赋值ANSIC新标准允许两个相同类型的共用体变量之间进行赋值。如果已有定义:unioninfox,y;则表示x,y同类型,假定x.c=$,则执行y=x,赋值语句后,表示共用体变量y的值也为$。4.共用体变量的输入输出可以用成员运算符或指针运算符对共用体变量的成员项进行输入输出,但不允许直接用共用体变量名进行输入输出。例如:对于:printf(“%c”,x.c);/*将输出字符$*/p-a=5;printf(“dt”,p-a);/*输出5*/p-c=$;printf(“%cn”,p-c);/*输出$*/是正确的;,而:scanf(“%d,%f,%c,printf(“%d,%f,%c”,x)错误的。在使用共用体类型变量时,我们还应注意以下几点:(1)共用体变量中各成员项共用同一内存空间,因此,共用体变量的地址和每一个成员项的地址是同一地址。(2)C语言规定不能对共用体变量名赋值,也不能通过直接引用变量名来得到成员项的值;也不允许在定义共用体变量时对其进行初始化。(3)在结构体类型中可定义共用体类型,也可以定义共用体数组。同样,在共用体类型中可定义结构体类型,也可以定义结构体数组。(4)不允许将共用体变量作为函数参数,也不允许用共用体变量作为函数的返回参数,但可以通过使用指向共用体变量的指针来解决。,8.7.2共用体的使用实例,【例8-7】某单位有N名职工参加计算机办公应用职业技能考评。设每个人的数据包括准考证号、姓名、年龄和成绩。单位规定参加考评的年龄为25岁以下的职工应进行笔试,笔试成绩为百分制,60分以上为及格、而25岁以上的职工应进行操作考核,考核成绩为A、B、C、D四个等级,C级以上为及格。请编程统计考评及格的人数,并输出每位考生考试的成绩。分析:可利用在结构体类型中定义共用体类型的数据定义方法来进行考生的数据处理。首先定义一个结构体数组PersonN,它包括的成员项有准考证号num,姓名name,年龄age和成绩score,而应将成绩成员项score定义为共用体类型,当年龄小于25岁的考生,其考试成绩为实型成员项exam,当为25岁以上的考生,其考核成绩为字符型成员项grade。所编程序如下L8-7.c,*8.8枚举类型,1.枚举类型为了更为清晰地描述各种数据结构,ANSIC新标准增加了一种用户定义型数据类型枚举类型。所谓“枚举“类型是指该类型变量的值只能是指定的若干个值之一。采用枚举类型数据可以从以下两个方面加强所编程序的功能:第一:可以更清楚更正确地表述问题,从而更容易阅读和书写程序。第二:通过枚举类型的说明能把有关问题的更多信息交给编译程序,从而可利用这些信息进行更广泛的错误检查,并产生效率更高的程序。,8.8.1枚举类型的概念、定义及其功能,2.枚举类型变量的定义由于当前计算机大量应用的问题还是数据信息的处理。在程序中常常以一些数值来代替处理那些非数值信息例如用数字0,1,2,3,6来分别代表星期日,星期一,星期六。用0,1,2,3,4分别代表红、黄、兰、白、黑五种颜色,因而C语言提供了一种新的数据类型,它允许程序员直接用符号名来依次列举它的每一个可能的值。枚举类型变量定义的一般形式:enum枚举类型名枚举常量表;enum枚举类型名枚举变量名;例如,定义星期的枚举类型:enumweekdaysun,mon,tue,wed,thu,fri,sat;enumweekdaydate;,3.枚举类型变量的功能前者定义了一种由“一星期中的七天”为成份的新的数据类型、并将该类型取名为weekday,后者定义了一个属于enumweekda

温馨提示

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

评论

0/150

提交评论