资源预览内容
第1页 / 共36页
第2页 / 共36页
第3页 / 共36页
第4页 / 共36页
第5页 / 共36页
第6页 / 共36页
第7页 / 共36页
第8页 / 共36页
第9页 / 共36页
第10页 / 共36页
亲,该文档总共36页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
9.1结构体结构体9.2结构体数组结构体数组9.3结构体与指针结构体与指针9.4共用体共用体9.5 枚举类型枚举类型9.6用用typedef定义类型定义类型第第9 9章章 结构体、共用体与枚举类型结构体、共用体与枚举类型9.1 9.1 结构体结构体结构体结构体是将是将不同类型不同类型的数据根据需要组合成一个有的数据根据需要组合成一个有机的整体,以便于引用。机的整体,以便于引用。这个整体是一个构造数据类型这个整体是一个构造数据类型结构体类型,其结构体类型,其中的数据是相互联系的。中的数据是相互联系的。如要存储一个学生的有关信息(学号、姓名、性别、如要存储一个学生的有关信息(学号、姓名、性别、年龄、住址)年龄、住址)可采用结构体数据结构描述上述信息。可采用结构体数据结构描述上述信息。structstudentintnum;charname20;charsex;intage;charaddr30;;定义一个结构体类型定义一个结构体类型的一的一般形式为:般形式为:struct结构体名结构体名成员表列成员表列;是类型,不是变量名是类型,不是变量名对各成员都要进行类型说明;对各成员都要进行类型说明;成员名命名规则与变量名成员名命名规则与变量名定义结构体类型变量的方法定义结构体类型变量的方法方法一方法一:先定义:先定义结构体类型结构体类型再定义再定义变量变量structstudentintnum;charname20;charsex;intage;charaddr30;;structstudentstudent1,student2;定义定义studet1和和sudent2为为structstudent类型变量类型变量不能只指定一个变量为不能只指定一个变量为“struct型型”而不指定结构体名而不指定结构体名可用符号常量代表一个结构体类型可用符号常量代表一个结构体类型#defineSTUDENTstructstudentSTUDENTintnum;charname20;charsex;intage;charaddr30;这样,可直接用这样,可直接用STUDENT定义变量,如:定义变量,如:STUDENTstudent1,student2;此时,不必再写关键字此时,不必再写关键字struct方法二方法二:在定义类型的同时定义变量在定义类型的同时定义变量structstudentintnum;charname20;charsex;intage;charaddr30;student1,student2;一般形式是:一般形式是:struct结构体名结构体名成员表列成员表列变量名表列;变量名表列;方法三方法三:直接定义结构类型变量直接定义结构类型变量其一般形式是:其一般形式是:structstruct 成员表列成员表列 变量名表列;变量名表列;此时,不出现结构体名此时,不出现结构体名structintnum;charname20;charsex;intage;charaddr30;student1,student2;几点说明:几点说明:1.1.类型与变量是不同概念,不要混淆;类型与变量是不同概念,不要混淆;2.2.结构体中的成员,可以单独使用,其作用与地位相当于普通变量;结构体中的成员,可以单独使用,其作用与地位相当于普通变量;3.3.成员名可以与程序中的变量名相同,二者不代表同一对象。互不干扰。成员名可以与程序中的变量名相同,二者不代表同一对象。互不干扰。4.4.在结构中,各成员都占有自己的内存空间,它们是同时存在的。在结构中,各成员都占有自己的内存空间,它们是同时存在的。一个结一个结构变量的总长度等于所有成员长度之和构变量的总长度等于所有成员长度之和。SizeofSizeof( )( )为一运算符,其为一运算符,其功能是测试某种类型的变量功能是测试某种类型的变量在内存中所占用的字节数。在内存中所占用的字节数。有:有:structinti;charc;floata;test;sizeof(test)的值是:的值是:7structdateintmonth;intday;intyear;Structstudentintnum;charname20;intage;structdatebirthday;student1,student2;Structstudentintnum;charname20;intage;structintmonth;intday;intyear;birthday;student1,student2;5. 5. 成员也可以是一个结构体变量。例:成员也可以是一个结构体变量。例:结构体类型变量的引用结构体类型变量的引用引用一般形式为:引用一般形式为:结构体变量名结构体变量名.成员名成员名规则:规则:1.不能将一个结构体变量作为一个整体进行赋值和输出;只不能将一个结构体变量作为一个整体进行赋值和输出;只能对其各个成员分别输出。能对其各个成员分别输出。printf(“.”,student1);printf(“%d”,student1.num);输出输出10010错!正确!2 .2 .若成员本身又属一个结构体类型,只能对最低级的成员进若成员本身又属一个结构体类型,只能对最低级的成员进行赋值或存取以及运算。行赋值或存取以及运算。 如:如:student1.birthday.yearstudent1.birthday.year3.3. 对成员变量可以象普通变量一样进行各种运算,如:对成员变量可以象普通变量一样进行各种运算,如: sumagesumage=student1.age+student2.age;=student1.age+student2.age;4.4. 可以引用成员的地址,也可以引用结构体变量的地址可以引用成员的地址,也可以引用结构体变量的地址, ,如:如: scanf(“%dscanf(“%d”,& student1.num);”,& student1.num); printf(“%o”,&student1); printf(“%o”,&student1); scanf(“%d,%s,%c,%d,%s”,&student1); scanf(“%d,%s,%c,%d,%s”,&student1);错!错!输入输入student1.num的值的值输出输出student1的首地址的首地址Structstudentintno;charname20;charsex;structintyear;intmonth;intday;birth;Structstudents;设变量设变量s中的中的“生日生日”是是“1984年年11月月11日日”,下列对,下列对“生日生日”的正确赋值方式是:的正确赋值方式是:A)year=1984;month=11;day=11;B)birth.year=1984;birth.month=11;birth.day=11C)s.year=1984;s.month=11;s.day=11D)s.birth.year=1984;s.birth.month=11;s.birth.day=11;练习:已知学生记录描述为:练习:已知学生记录描述为:结构体变量的初始化结构体变量的初始化在定义结构体类型变量的同时对其每个成员赋初值在定义结构体类型变量的同时对其每个成员赋初值初始化。初始化。structstudentlongintnum;charname20;charsex;charaddr20;a=9801,”Wanghong”,W,”2LinggongRoad”;main()printf(“No.:%ldnname:%snsex:%cnaddress:%sn”,a.num,a.name,a.sex,a.addr);运行结果为:运行结果为:No.:9801name:Wanghongsex:Waddress:2LinggongRoad9.2 9.2 结构体数组结构体数组(每个数组元素都是一个结构体类型的数据每个数组元素都是一个结构体类型的数据)结构体数组的定义结构体数组的定义:structstudentintnum;charname20;charsex;intage;charaddr30;structstudntstu3;也可直接定义:也可直接定义:structstudentintnum;stu3;或或structintnum;stu3;结构体数组的引用结构体数组的引用1 1结构体数组元素中某一成员的引用结构体数组元素中某一成员的引用 stu0.name stu0.name 表示表示stustu的第的第1 1个元素的个元素的namename成员项成员项 stu4.age stu4.age 表示表示stustu的第的第5 5个元素的个元素的ageage成员项成员项2 2结构体数组元素的赋值结构体数组元素的赋值 可将一个结构体数组元素赋给同一结构体数组中的另一个元可将一个结构体数组元素赋给同一结构体数组中的另一个元素,或者赋给同一类型的变量。素,或者赋给同一类型的变量。 stu1 = stu2; stu1 = stu2; Stu4 = stu5; Stu4 = stu5;注意:结构体数组元素的输入和输出只能将单个成员项进行输注意:结构体数组元素的输入和输出只能将单个成员项进行输入和输出,而不能把结构体数组元素作为一个整体直接进行入和输出,而不能把结构体数组元素作为一个整体直接进行输入和输出。输入和输出。结构体数组的初始化结构体数组的初始化structstudentintnum;charname20;charsex;intage;charaddr30;stu3=111,”Li”,M,18,”Dalian”,;也可采用:也可采用:structstudentintnum;structstudentstu=,;结构体数组的初始化的一般形式是在结构体数组的初始化的一般形式是在定义数组后面加上:定义数组后面加上:=初值表列初值表列;structpersoncharname20;intcount;leader3=“Li”,0,”zhang”,0,”Liu”,0;main()inti,j;charleader_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);判断是哪一位候选人判断是哪一位候选人例题例题:设有三个候选人,:设有三个候选人,每次输入一个得票的候选每次输入一个得票的候选人的名字,要求最后输出人的名字,要求最后输出各人得票结果。各人得票结果。计算学生的平均成绩和不及计算学生的平均成绩和不及格的人数。格的人数。structstuintnum;char*name;charsex;floatscore;boy5=101,Liping,M,45,102,Zhangping,M,62.5,103,Hefang,F,92.5,104,Chengling,F,87,105,Wangming,M,58,;main()inti,c=0;floatave,s=0;for(i=0;i5;i+)s+=boyi.score;if(boyi.score成员名成员名指向运算符。其优先级指向运算符。其优先级高于自增、自减运算符高于自增、自减运算符试分析以下运算:试分析以下运算:p-n得到得到p指向的结构体变量中的成员指向的结构体变量中的成员n的值的值p-n+得到得到p指向的结构体变量中的成员指向的结构体变量中的成员n的值,的值,用完后使它加用完后使它加1;+p-n得到得到p指向的结构体变量中的成员指向的结构体变量中的成员n的值的值使其先加使其先加1成员运算符成员运算符指向结构体数组的指针指向结构体数组的指针类似与多维数组中指向一维数组的指针。例:类似与多维数组中指向一维数组的指针。例:#includestring.h#includestdio.hstructstudentintnum;charname20;charsex;intage;structstudentstu3=10101,LiLin,M,18,10102,ZhangFun,M,19,10104,WangMin,F,20;voidmain()structstudent*p;printf(No.NameSexagen);for(p=stu;pnum, p-name, p-sex,p-age);注意:注意:p定义为定义为structstudent类型,它只能指向这种类型的结构类型,它只能指向这种类型的结构体变量,而不能指向该类型的成员(体变量,而不能指向该类型的成员(p=&stu.name是错误的)其是错误的)其它类型的结构体变量。它类型的结构体变量。用结构体变量和指向结构体的指针作为函数参数用结构体变量和指向结构体的指针作为函数参数将一个结构体变量的值传递给另一个函数有将一个结构体变量的值传递给另一个函数有3 3个方法:个方法:1.1.用结构体变量的成员作参数,将实参值传给形参用结构体变量的成员作参数,将实参值传给形参2.2. 用用法法和和用用普普通通变变量量作作实实参参是是一一样样的的,属属于于“值值传传递递”方方式式。应应当当注注意实参和形参的类型保持一致。意实参和形参的类型保持一致。3.3.2.2.用结构体变量作实参用结构体变量作实参4.4. 此此方方法法采采用用的的是是“值值传传递递”的的方方式式,将将结结构构体体变变量量所所占占的的内内存存单单元元的的内内容容全全部部顺顺序序传传递递给给形形参参。形形参参也也必必须须是是同同类类型型的的结结构构体体变变量量。在在函函数数调调用用其其间间形形参参也也要要占占用用内内存存单单元元。这这种种传传递递方方式式在在空空间间和和时时间间上上开开销销较较大大。此此外外,由由于于采采用用值值传传递递方方式式,如如果果在在执执行行被被调调用用函函数数其其间间改改变变了了形形参参(也也是是结结构构体体变变量量)的的值值,该该值值不不能能返返回回主主调调函函数数,这这往往往造成使用上的不便。因此一般较少用这种方法。往造成使用上的不便。因此一般较少用这种方法。5.5.3.3.用用指指向向结结构构体体变变量量(或或数数组组)的的指指针针作作实实参参,将将结结构构体体变变量量(或或数数组)的地址传给形参。组)的地址传给形参。#includestdio.h#defineformat%dn%sn%fn%fn%fnstructstudentintnum;charname20;charsex;floatscore3;voidmain()voidprint();structstudentstu;stu.num=12345;strcpy(stu.name,LiLi);stu.score0=67.5;stu.score1=89;stu.score2=78.6;printf(&stu);voidprint(p)structstudent*p;printf(format,p-num,p-name,p-score0,p-score1,p-score2);printf(n);9.4 9.4 共用体共用体 共共用用体体是是使使用用覆覆盖盖技技术术将将几几个个不不同同类类型型的的变变量量置置于于同同一一段段内存,虽然它们各自占的内存长度不同,但起始地址相同。内存,虽然它们各自占的内存长度不同,但起始地址相同。共用体定义的一般形式:共用体定义的一般形式:unionunion 共用体名共用体名 成员表列成员表列 变量表列;变量表列;结构体和共用体机制上的区别:结构体和共用体机制上的区别: 结结构构体体所所占占内内存存长长度度是是各各成成员员占占的的长长度度之之和和。即即每每个个成成员员分分别别占占有有其其自自己己的的内内存存单单元元。共共用用体体变变量量所所占占内内存存长长度度是是最最长长的成员的长度。的成员的长度。例如:例如:unionainti;charch;floatf;a,b,c;a.ch=Ha.i=23a.f=1234.4567已知:已知:unioninti;charc;floata;test;则:则:sizeof(test)的值是:的值是:4 共用体数据的特点 1)1)同同一一个个内内存存段段可可以以用用来来存存放放几几种种不不同同类类型型的的成成员员变变量量,但但在在每每个个瞬瞬间间只只能能存存放放其其中中一一种种,而而不不是是同同时时存存放放几几种种。起起作作用用的的是是最最后依次存放的成员。如经过以下三次赋值后,只有后依次存放的成员。如经过以下三次赋值后,只有a.f=1.5a.f=1.5有效。有效。 a.i=1; a.i=1; a.cha.ch=a; a.f=1.5;=a; a.f=1.5; 2) 2)共用体变量的地址和它的各成员的地址都是同一个地址共用体变量的地址和它的各成员的地址都是同一个地址 3)3)不不能能对对共共用用体体变变量量名名赋赋值值。也也不不能能企企图图引引用用变变量量名名得得到到成成员员值,不能在定义共用体变量时对它初始化。下面是错误的:值,不能在定义共用体变量时对它初始化。下面是错误的:(1) union (1) union intint i; i; char char chch; ; float f; float f;a=a, a, 1.5;a=a, a, 1.5;(2) a=1;(2) a=1;(3) m=a;(3) m=a; 4)4)在函数间传递共用体时,只能使用指针的方法。在函数间传递共用体时,只能使用指针的方法。 5)5)共共用用体体类类型型可可以以出出现现在在结结构构体体类类型型定定义义中中,也也可可以以定定义义共共用用体体数数组组。反反之之,结结构构体体也也可可以以出出现现在在共共用用体体类类型型定定义义中中,数组也可以作为共用体的成员。数组也可以作为共用体的成员。要要作作如如下下表表格格的的数数据据管管理理,对对教教师师(“T”T”)要要注注明明职职务务( “position”position”) , 对对 学学 生生 ( “S”S”) 要要 注注 明明 班班 级级(“class”class”)。由由于于数数据据的的不不完完全全一一致致,对对班班级级和和职职务务要要用用到共用体。到共用体。namenumsexjobClass PositionLi1011 FS501Wang2085 MTprofstructintnum;charname10;charsex;charjob;unionintclass;charposition10;category;person2;main()intn,i;for(i=0;i2;i+)scanf(%d%s%c%c,&personi.num,personi.name,&personi.sex,&personi.job);if(personi.job=s)scanf(%d,&personi.category.class);elseif(personi.job=t)scanf(%s,personi.category.position);elseprintf(ninputerror!);printf(n);printf(No.namesexjobclass/positionn);for(i=0;i2;i+)if(personi.job=s)printf(%-6d%-10s%-3c%-3c%-6dn,personi.num,personi.name,personi.sex,personi.job,personi.category.class);elseprintf(%-6d%-10s%-3c%-3c%-6sn,personi.num,personi.name,personi.sex,personi.job,personi.category.position);9.5 9.5 枚举类型枚举类型如如果果变变量量只只有有几几种种可可能能的的值值,可可以以定定义义为为枚枚举举类类型型。它它是是把把变变量量的值一一列举出来。变量只能取列举出的值。的值一一列举出来。变量只能取列举出的值。枚举类型定义一般方法:枚举类型定义一般方法:enumweekdaysun,mon,tue,wed,thu,fri,sat;变量声明方法:变量声明方法:enumweekdayworkday,week_end;workday和和week_end被被定定义义为为枚枚举举变变量量,它它们们只只能能取取值值于于sun到到sat之一。如:之一。如:workday=mon;week_end=sum;是正确的。是正确的。1 1在在C C编译中,对枚举按常量处理,故称枚举常量。不能对它们赋值。例如:编译中,对枚举按常量处理,故称枚举常量。不能对它们赋值。例如: Mon = 1; Sun = 7; Mon = 1; Sun = 7; 是错误的。是错误的。2 2枚枚举举元元素素作作为为常常量量,它它们们是是有有值值的的,如如果果没没有有进进行行初初始始化化,第第一一个个枚枚举举元元素素的的值值是是0 0,第第二二个个枚枚举举元元素素的的值值为为1 1,依依此此类类推推。例例如如,对对上上述述枚枚举举变变量量wordkaywordkay来来说说,如下语句:如下语句: workday = workday = Fri;printf(Fri;printf(“%d%d”,workday,workday); ); 输出结果是输出结果是4 4。也可以改变枚举元素的值,在定义时由程序指定,例如:也可以改变枚举元素的值,在定义时由程序指定,例如: enumenum weekday Mon = 1,Tue,Wed,Thu,Fri,Sat,Sun workday; weekday Mon = 1,Tue,Wed,Thu,Fri,Sat,Sun workday;定义定义MonMon为为1 1,以后顺序加,以后顺序加1 1,SunSun为为7 7。3 3枚枚举举类类型型变变量量只只能能取取枚枚举举元元素素表表中中的的某某个个元元素素,而而不不能能是是其其它它值值。不不能能把把整整数数直直接接赋赋给给枚枚举举变变梁梁。例例如如:workday workday = = 2 2 ; ;是是错错误误的的。它它们们属属于于不不同同的的类类型型。应应先先进进行行强强制制类类型型转转换换才才能能赋赋值值。例例如如:workday workday = = ( (enumenum weekday) weekday) 2;2;甚甚至至可可以以是是表表达式。例如:达式。例如:workday = (workday = (enumenum weekday) (5-3); weekday) (5-3);4 4枚举值可以用来作判断比较。例如:枚举值可以用来作判断比较。例如:if (workday = Mon) if (workday = Mon) 枚枚举举值值的的比比较较规规则则是是:按按其其在在定定义义时时的的顺顺序序号号比比较较。顺顺序序号号大大,枚枚举举值值也也大大。如如果果workday = Friworkday = Fri,那么,那么workdayworkday就大于就大于TueTue。 枚举类型的变量在使用时要注意以下几点:枚举类型的变量在使用时要注意以下几点: 例:已知今天是星期日,编写一个程序,求若干天后是星期几。#includevoidmain()intn;enumsun,mon,tue,wed,thu,fri,satday;charweekday77=星星期期日日,星星期期一一,星星期期二二,星星期期三三,星星期期四四,星期五星期五,星期六星期六;printf(输入间隔天数输入间隔天数:);scanf(%d,&n);day=sun;printf(今今天天是是%s,%d天天后后是是%s.n,weekdayday,n,weekday(day+n)%7); 9.6 9.6 用用typedeftypedef定义类型定义类型 C C语语言言允允许许用用typedeftypedef说说明明一一种种新新的的类类型型名名,新新的的类类型型名名即即可可当当做做原原类类型标识符来使用,用它来定义变量,其型标识符来使用,用它来定义变量,其一般形式一般形式为:为: typedeftypedef 其其中中,typedeftypedef是是类类型型定定义义关关键键字字;原原类类型型标标识识符符指指的的是是已已有有的的类类型型标标识识符符,如如intint、floatfloat、已已定定义义过过的的结结构构体体、共共用用体体、枚枚举举等等;新新类类型型标标识识符符是用户自行定义的标识符,用来代替原类型标识符。是用户自行定义的标识符,用来代替原类型标识符。例如:例如:typedeftypedef intint INTEGER; INTEGER; typedeftypedef flaotflaot REAL; REAL;可可以以用用新新定定义义的的类类型型标标识识符符去去说说明明变变量量、数数组组、结结构构体体、共共用用体体、枚枚举举等等。例如:例如:INTEGER INTEGER i,ji,j; ; 它们等价于:它们等价于:intint i,ji,j; ;REAL REAL a,ba,b; ; float float a,ba,b; ; 9.6 9.6 用用typedeftypedef定义类型定义类型1.1.数组数组typedeftypedef char STRING80; char STRING80;STRING s1,s2;STRING s1,s2;等价于:等价于:char s180,s280char s180,s2802.2.指针指针typedeftypedef intint *PINT; *PINT;PINT p1,p2;PINT p1,p2;等价于:等价于:intint *p1,*p2; *p1,*p2;用用typedeftypedef除了可以定义基本类型外,还可以定义其它各种已经定义过的类型:除了可以定义基本类型外,还可以定义其它各种已经定义过的类型:3.3.函数函数typedeftypedef char FCH(); char FCH();FCH FCH afaf; ;等价于:等价于:char char afaf();();4.4.结构体结构体typedeftypedef structstruct date date intint year; year;intint month; month;intint day; day; DATE; DATE;DATE DATE dtdt; ;等价于:等价于:structstruct date date dtdt; ;1)1)用用typedeftypedef可可以以把把已已有有的的各各种种类类型型名名定定义义成成新新的的类类型型名名,但但不不能能直直接接定定义义变变量。量。2)typedef2)typedef只只是是对对已已有有的的数数据据类类型型名名增增加加一一个个新新的的替替换换名名,并并不不能能创创造造新新的的数数据类型,也不取代现有的数据类型名。现有的数据类型名可以继续使用。据类型,也不取代现有的数据类型名。现有的数据类型名可以继续使用。3)3)用用typedeftypedef定定义义了了一一个个新新类类型型后后,可可以以再再用用typedeftypedef将将新新类类型型名名定定义义成成另另一一个新的类型名,即嵌套定义。个新的类型名,即嵌套定义。4 4)typedeftypedef与与#define#define有相似之处,例如:有相似之处,例如: typedeftypedef intint INTEGER;INTEGER;与与#define #define INTEGER INTEGER intint都都是是用用INTEGERINTEGER代代表表intint,但但#define#define是是在在预预编编译译时时处处理理的的,它它只只能能做做简简单单的的字字符符串串替替换换,而而typedeftypedef是在编译时处理的,并不是做简单的字符替换。是在编译时处理的,并不是做简单的字符替换。例如,前面介绍的定义数组:例如,前面介绍的定义数组:typedeftypedef char STRING80; char STRING80;STRING s;STRING s;并不是将并不是将STRING80STRING80替换成替换成charchar,而是相当于定义:,而是相当于定义:char s80char s80;使用使用typedeftypedef时,要注意以下几点时,要注意以下几点
收藏 下载该资源
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号