资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,结构体与共用体,结构体概述,结构体变量,结构体数组,共用体,枚举类型,用,typedef,定义类型,1,结构体概述,结构体的引入,和一个学生有关的数据:,姓名、性别、学号、年龄、,家庭住址、学习成绩,这些数据项之间,关系密切但数据类型不尽,相同,,若分别定义多个变量,就会割裂这些数据,项之间的内在联系。,数组?,2,为了方便处理,多个数据项,的数据,常把这些,关系密切但类型不同,的数据项组织在一起,,即,“封装”,起来,并为其取一个名字,在,C,语言中,,就称其为,结构体,。,结构体通常是由不同数据类型的数据项组成,一般也称是由不同成员组成,因此可以说:,一个结构体可包含若干成员,每一个成员可具有不同的名字及数据类型。,结构体的引入为,处理复杂的数据结构,提供,了有力的手段,也,为函数间传递一组不同数据,类型的数据,提供了方便,特别是对于数据结构,较为复杂的大型程序提供了方便。,3,结构体类型的定义,结构体类型,和简单类型不同,,简单类型,是由系统预定义的,如,int、float、char,,直接可以使用,。而,结构体类型,是根据需要,由程序员自行定义,,因此在使用之前,必须先定义结构体类型,。,结构体类型定义:,struct,结构体名,类型标识符 成员名;,类型标识符 成员名;,.,;,合法标识符,可省;,无名结构体,成员类型可以是,基本型或构造型,struct,是,关键字,不能省略,注意:这里说的是定义结构体类型而不是变量。,4,例,struct student,int num;,char name20;,char sex;,int age;,float score;,char addr30;,;,结构体类型定义描述结构,的组织形式,,不分配内存,5,说明:,(1)定义一个,结构体类型,只是描述了此结构体的组织形,式,在编译时,并不为其分配,存储空间,即仅描述此,数据结构的形态或者说模型,故不能对定义的一个,结构体类型进行赋值、存取或运算。,结构体的成员可以是简单变量、数组、指针、结构体或,共用体等。,(3)结构体类型定义可以,放在函数内部,,也可以放在,函数外,部,。若放在内部,则只在函数内有效;若放在外部,,则从定义点到源文件尾之间的所有函数都有效。,(4)结构体成员的,名字,可以同程序中的其它变量,同名,,二者,不会相混,系统会自动识别它。,例如:刚才定义的结构体中,,年龄改用生日来描述。,定义结构体:,struct date_type,int year;,int month;,int day;,;,这样,关于学生信息的结构体,可定义为:,struct stud_type,struct date_type birthday;,;,注意:结构体,date_type,一定要定义在结构体,stud_type,之前。,6,结构体与共用体,结构体概述,结构体变量,结构体数组,共用体,枚举类型,用,typedef,定义类型,7,结构体变量,结构体变量的定义与初始化,1,.,结构体变量的定义,先定义,再引用。,一个结构体变量的定义可以有,三种方式,。,8,struct stud_type,char name10;,long num;,char sex;,int age;,float score;,char address10;,;,struct stud_type,student1,student2,;,(1)先,定义类型,再,定义变量,直观,灵活!,9,(2)在定义类型的,同时,定义变量,struct stud_type,student1,student2,;,(3),直接,定义结构体变量,struct,student1,student2,;,第一种的简略形式。,用于结构体类型仅做一次性使用的场合。,10,说明:,(1)在定义,结构体类型,时,系统,并不分配内存,空间,,仅当,定义结构体变量时,,系统才为,被定义的每一变量,分配相应的存储单元,。,如上面定义的结构体变量,student1、,student2,在内存中各占3,3,个字节,(10+4+1+,4+4+10=33,);,(2),结构体变量的定义一定要在结构体类型定义,之后,或,同时,进行。,(2),结构体变量,的定义一定要在结构体类型,定义,之后,或,同时,进行,对尚未定义的,结构体类型,不能用它来定义结构体变量。,例,struct student,int num;,char name20;,char sex;,int age;,float score;,char addr30;,;,name,num,sex,age,score,addr,4,字节,4,字节,20,字节,1,字节,4,字节,30,字节,.,例如:,对一个教师,teacher,的结构体类型未作定义,,则下面的变量定义,struct teacher,teah1,是错误的;,11,2,.,结构体变量的初始化,所谓,结构体变量初始化,,就是在定义结构体变量的同时,对其成员变量,赋初值,。,在赋值时应注意,按顺序及类型,依次为每个结构体成员指定初始值。,结构体初始化的一般,格式,为,:,struct,结构体类型名 结构体变量=初始化值;,例,struct student,char name20;,int num;,char sex;,int age;,float score;,char addr30;,;,struct stud_type student1=,“wang”,196103,m,20,98,”xian”;,12,说明:,(1)初始化数据之间用,逗号,分隔。,(2)初始化数据的个数一般与成员的,个数相同,,,若,小于,成员数,则剩余的成员将被自动,初始,化为0,(若成员是指针,则初始化为,NULL)。,(3),初始化数据的,类型,要与相应成员变量的类型,一致。,不一致将强制类型转换,。,(4),初始化时只能对,整个结构体变量,进行,,不能,对结构体类型中的,某个成员,进行初始化赋值。,13,struct date_type,int year;,int mouth;,int day;,;,void main(),struct stud_type,student1=,wang,196103,m,1978,10,12,98,Xian;,struct stud_type,student,2,=,liu,196105,m,1980,9,22,88,Benjing;,printf(%d,student1.birthday.day);,struct stud_type,char name10;,long num;,char sex;,struct date_type birthday;,float score;,char address10;,;,14,结构体变量的引用,1.对结构体变量成员的引用,在,C,语言程序中,不准许对结构变量整体进行各种运算、赋值或输入输出操作,而,只能对其成员,进行此类操作。,引用结构体变量成员的一般形式:,结构体变量名,.,成员名,其中“.”是结构体成员运算符,其,优先级别最高,,结合性是,自左至右,。由此对结构体成员就完全可以像操作简单变量一样操作它。,15,如:对上例定义的结构体变量,student1,或,student2,,可作如下的赋值操作:,student1.name10=wang;,strcpy(student1.name,”wang”),student1.num=196103;,student1.sex=m;,student1.birthday.year=1978;,student1.birthday.mouth=10;,student1.birthday.day=12;,student1.score=98;,还可以如下操作:,sum=student1.score+student2.score;,scanf(“%s%d”,student1.name,&,student1.num);,printf(“%s%d”,student1.name,student1.num);,错误,正确,16,2.对结构体变量整体的引用,结构体变量和简单变量相比,除了上面所述,在参加各种运算、赋值或输入输出方式上有所不同外即是由结构体变量成员完成,其它,同简单变量一样,,如:,(1),可以相互赋值,,但注意相互赋值的两个结构体,变量必须是同一个结构体类型;,如:,student1=student2;,(2),可作为函数的形参、实参或函数返回值。,17,结构体变量作为函数参数,结构体变量,成员,作函数参数,结构体变量中的所有成员都可作为函数参数。,struct stud_type,char name10;,long num;,char sex;,student1;,将结构体变量,student1,的三个成员分别传递给函数,func1(),func2(),func3():,func1(student1.name);,func2(student1.num);,func3(student1.sex);,18,若需要将成员地址传递给函数,则只,需在其前加取地址符“,&,”。,如,:,func1(student1.name);,func2(,&,student1.num);,func3(,&,student1.sex);,其中字符数组名,name,代表其成员地址,故不需要写“,&,”。,19,2.结构体变量,整体,作函数参数,老板本的,C,系统不允许用结构体变量作函数,参数,只允许用指向结构体变量的指针作函数参数,,传递的是结构体变量的首地址。,而,ANSI C,取消了这一限制,,规定按值传递方式,。,在函数调用时,,系统为形参结构体变量分配存储空间,,,并从相应的实参结构体变量中取得各成员的值,若,对,形参中结构体变量各成员值进行修改,并不能修改实,参结构体变量各成员的值,。,注意,实参和形参结构体变量,类型,应当完全一致。,P125,例,6.2,20,结构体与共用体,结构体概述,结构体变量,结构体数组,共用体,枚举类型,用,typedef,定义类型,21,结构体数组,结构体数组的定义与初始化,1.结构体数组的定义,结构体数组:数组的成员是结构体类型数据元素。,在定义结构体数组时,其定义方法与定义,结构体变量方法类似,也有,三种形式,。,第一种定义方式:,22,struct date_type,int year;,int mouth;,int day;,;,struct stud_type,char name10;,long num;,char sex;,struct date_type birthday;,float score;,char address10;,;,struct stud_type student3;,由此就定义了一个结构体数组,数组名是,student1,,它有3个元素,每个元素都是,struct stud_type,类型,每个数组元素各占,41,个字节,(10+4+1+(,4+4+4)+4+10=41,)共占,41*3,个字节。,23,2.结构体数组的初始化,结构体数组在定义的同时可以初始化,。,其,一般格式,是在定义之后紧跟一个用花括号括起来的一组初始数据,为了增强可读性,,最好使每一个数组元素的初始数据也用花括弧括起来,,以此来区分各个数组元素。,对刚定义的结构体数组,student,初始化如下:,struct stud_type student3=,wang,196103,m,1978,10,12,98,xian,“zhang”,196102,f,1977,1,10,87,“Beijing”,“li”,196204,m,1977,9,21,82,”xian”,;,24,结构体数组元素的引用,和简单变量数组元素的引用一样:,数组名,元素下标,结构体数组元素的成员引用:,数组名,元素下标,.,成员名,说明:,(1)可以将一个结构体数组元素赋值给同一结构体类型数,组中另一个元素,或赋给同一类型的变量。,定义:,struct stud_type student3,student1,;,赋值:,student1,student0,;,student0=student1;,studnet1=student1;,25,(2),不能,把结构体数组元素作为一个,整体,直接进行,输入或输出,。,如,printf(“%d”,student0),;,或,scanf(%d,&student0),;,只能,以,单个成员,为对象进行,输入输出,,,如:,scanf(%s,student0.name),;,scanf(%d,student0.num),;,printf(%s,student0.name);,26,例 统计候选人选票,struct person,char name20;,int count;,leader3=“Li”,0,“Zhang”,0,“Wang”,0;,void main(),int i,j;char leader_name20;,for(i=1;i=10;i+),scanf(%s,leader_name);,for(j=0;j3;j+),if(,strcmp,(leader_name,leaderj.name)=0),leaderj.count+;,for(i=0;i3;i+),printf(%5s:%dn,leaderi.name,leaderi.count);,name,count,Li,Zhang,Wang,0,0,0,27,结构体与共用体,结构体概述,结构体变量,结构体数组,共用体,枚举类型,用,typedef,定义类型,28,共用体,共用体是一种,同一存储区域由不同,类型变量共享,的数据类型。,它提供一种方法能,在同一存储区中操作,不同类型的数据,,也就是说,共,用体采用的是,覆盖存储技术,,准许不同类型数据互相覆盖。,29,共用体类型定义,共,用体类型的定义与结构体类似,。,一般定义格式如下:,union,共,用体名,共,用体成员表;,;,其中,union,是关键字,称为,共,用体定义标识符,,共,用体名同样由程序员来命名。大括号中的,共,用体成员表包含若干成员,每一个成员都具有如下的形式:,数据类型标识符 成员名;,例如:,union data,int i;,char ch;,float f;,;,30,共用体变量定义与引用,1.共用体变量的定义,共用体变量的定义和结构体变量定义一样有,三种形式,。,union,共,用体名,共,用体成员表;,变量列表,;,如:,union data,int i;,char ch;,float f;,a,b,c;,31,共用体和结构体有着本质的,区别,:,共用体,是几个不同的变量,共占同一段内存,,,且都是从同一地址开始存储,,任意时刻只存储,一种数据,。分配空间的大小为需要存储的数据,中占用字节数最多的那个数据类型的大小。,结构体,是不同成员使用,不同的存储空间,,占用,的空间大小为各个成员需要占用的字节数的和。,32,例:,struct,data,union,data,short int i;short int i;,char ch;char ch;,x;x;,2000,2002,2003,x.i,x.ch,x.f,x.ch,x.i,x.f,2000,33,2.共用体变量的引用,共用体变量名.成员名;,如上例所示:,x.i;x.ch;x.f,说明:,(1)共用体变量不能同时存放多个成员的值,而只能存,放其中一个值,即只能存放当前(最新)的一个成,员的值;,(2)就共用体变量整体而言,和结构体变量一样是,不能,进行整体的输入、输出,,但可以在两个同一类型的,共用体变量之间赋值;,34,例 共用体变量的引用,void main(),union int_char,short i;char ch2;x;,x.i=24897;,printf(“i=%dn i=%o n”,x.i,x.i);,printf(“ch0=%o,ch1=%o n,ch0=%c,ch1=%c n”,x.ch0,x.ch1,x.ch0,x.ch1);,35,结构体与共用体,结构体概述,结构体变量,结构体数组,共用体,枚举类型,用,typedef,定义类型,36,枚举类型,在实际应用中,有些变量的取值范围是有限,的,仅可能只有几个值,如一个星期7天,一年,12个月,一副扑克有4种花色,每一花色有13张牌等。,整型数来表示:,直观性差,!,如在程序中使用1,对于非编程者来说,它是代表星期一呢?还是一月份?很难区分。,若在程序中使用“,Mon”,,则不会有人认为是代表一月份。由此看出,,为提高程序的可读性,,引入,非数值量,,即一些有意义的符号是非常必要的。,对于这种应用,,C,语言引入,枚举类型,,所谓“枚举”,就是,将变量可取的值一一列举出来,。,37,枚举类型也要,先定义其类型,,,再定义其变量,。,枚举类型定义的一般形式是:,enum,枚举名,枚举值列表;,;,其中,enum,是关键字,称为枚举类型定义标识符,枚举名由程序员命名。,枚举值列表形式如下:,标示符,1,标示符,2,标示符,n,这里的标识符也是由程序员自定义,都是一些描述性标识符,,要求不能重名,,这些标识符分别代表不同枚举元素,通常称为,枚举常量,。,38,例如,:,enum weekday,sun,mon,tue,wed,thu,fri,sat,;,由此定义了一个枚举类型,enum weekday,,,它有7个枚举元素(常量)。,在定义了类型之后,就可以用该类型来,定义变量,:,enum weekday workday;,变量的定义也可以有,三种形式,。,39,说明:,(1)在,C,语言中,每一个枚举常量的值取决于在,说明时排列的先后次序,,第一个枚举常量的,序号为0,(规定序号从0编起),因此,此枚举常,量值为0,,以后顺序加1,,故,不允许对枚举常量进,行赋值操作,。,若想改变枚举常量的值,在枚举变量定义时可由,程序员指定,:,如:,enum fruit,apple=7,pear,orange=3,lemon,peach,t;,此时,apple,的值为7,,pear,的值为8,,orange,的值为3,,lemon,peach,的值分别为4,5。,40,(2)一个枚举变量的值只能是这几个枚举常量,之一,可以将枚举常量赋给一个枚举变量,,但不能将一个整数赋给它。如:,workday=sun;,正确,workday=7;,错误,41,enum weekday,0 1 2 3 4 5 6,sun,mon,tue,wed,thu,fri,sat,;,enum weekday,sun=7,mon,tue,wed,thu,fri,sat,;,enum weekday,sun=7,mon=1,tue,wed,thu,fri,sat,;,7 8 9 10 11 12 13,7 1 2 3 4 5 6,42,结构体与共用体,结构体概述,结构体变量,结构体数组,共用体,枚举类型,用,typedef,定义类型,43,用,typedef,定义类型,功能,:用自定义名字为,已有,数据类型命名,类型定义,简单形式:,typedef,type,name,;,例,typedef int INTEGER;,类型定义语句关键字,已有数据类型名,用户定义的类型名,例,typedef float REAL;,类型定义后,与已有类型一样使用,例,INTEGER a,b,c;,REAL f1,f2;,int a,b,c;,float f1,f2;,说明:,1.,typedef,没有创造,新数据类型,2.,typedef,是定义类型,不能定义变量,3.,typedef,与,define,不同,define,typedef,预编译时处理,编译时处理,简单字符置换,为已有类型命名,优点:,1,)可缩写长的类型名;,2,)可将程序参数化,便于移植。,44,例 定义结构体类型,struct date,int month;,int day;,int year;,d,;,例 定义结构体类型,struct date,int month;,int day;,int year;,DATE,;,例 定义结构体类型,typedef,struct date,int month;,int day;,int year;,DATE,;,typedef,定义类型步骤:,按定义变量方法先写出定义体 如,int i;,将变量名换成新类型名 如,int,INTEGER,;,最前面加,typedef,如,typedef,int,INTEGER,;,用新类型名定义变量 如,INTEGER,i,j;,DATE d1;,45,说明:,(1)定义的新类型名,一般使用大写字母,,以便与系统,的标准类型标识符相区别。,(2)仅,给已有的类型名重新命名,,,并不产生新的数据类型,,,原有的数据类型也没有被取代,,即只是此类型的一个,“,别名,”。,如,typedef int INTEGER;,只是给,int,起了一个新的名字而已,,int,仍可用。,(3)定义一个新的数据类型名,并没有定义变量,因而,谈,不上分配存储单元,。,(4),typedef,与#,define,有相似之处,:,如,typedef int INTEGER;,#defint INTEGER int;,作用都是用,INTEGER,代替,int,,,但二者,有本质的区别,,,前者是为,int,定义了一个别名,而后者是宏代换。,46,P141 6.10,union grade,int gi;,char gc;,;,struct info,int num;,char name20;,int age;,union grade score;,personN;,struct info,int num;,char name20;,int age;,union grade,int gi;,int gc;,score;,personN;,47,
展开阅读全文