1、Rose第五章 复杂构造数据类型济南大学Rose 1 概述在解决实际问题时,有时需要将多个不同的数据类型组合在一起表达一个整体的信息。例如:描述一个学生的完整信息时,有学号、姓名、年龄、成绩、家庭地址等项。这些项目之间是彼此联系的,应组织定义成一个组合项,统一表示和使用,见下例:济南大学Rose结构体类型举例学号学号姓名姓名性别性别年龄年龄成绩成绩家庭地址家庭地址intnumcharname8charsexintagefloatscorecharaddr209001 李华李华女女2086济南济南某一个学生的具体信息表示:某一个学生的具体信息表示:济南大学Rose结构体类型定义 这种由若干个不同
2、类型的数据项组成的这种由若干个不同类型的数据项组成的组合类型,在组合类型,在C C语言中叫做结构体类型,相当语言中叫做结构体类型,相当于其它语言中描述的于其它语言中描述的“记录记录”。结构体类型在使用之前应先定义其类型结构体类型在使用之前应先定义其类型结构,然后再定义该类型变量,才能使用。结构,然后再定义该类型变量,才能使用。如上实例:如上实例:济南大学Rose结构体类型定义结构体类型定义 struct student int num;char name8;char sex;int age;float score;char addr20;结构体描述:结构体描述:学号学号姓名姓名性别性别年龄年龄
3、成绩成绩家庭地家庭地址址intnumcharname8charsexintagefloatscorecharaddr20济南大学Rose定义有定义有n n个成员的结构体类型的一般形式:个成员的结构体类型的一般形式:struct结构体类型名结构体类型名类型标识符类型标识符1成员名成员名1;类型标识符类型标识符2 成员名成员名2;.类型标识符类型标识符n 成员名成员名n;说明:说明:1、用、用 将成员扩起来。将成员扩起来。2、成员的类型可以是任意类型,称、成员的类型可以是任意类型,称为一个域或一个数据项。为一个域或一个数据项。3、注意最后的分号不能忽略。、注意最后的分号不能忽略。济南大学Rose2
4、定义结构体变量注意前面定义的注意前面定义的student同同int、char等一样只是类等一样只是类型的名字,不是结构体变量,不能直接使用,需由此型的名字,不是结构体变量,不能直接使用,需由此类型继续定义结构体变量才能使用,类型继续定义结构体变量才能使用,步骤步骤:先定义一个结构体类型,再定义变量。先定义一个结构体类型,再定义变量。struct 结构体类型名结构体类型名 变量名列表;变量名列表;注:关键字注:关键字struct 与结构体类型标识符一起使用。与结构体类型标识符一起使用。例:例:struct student stu1,stu2,stu50;已定义的已定义的类型名类型名济南大学Ros
5、e定义了结构体变量后,系统为之分配内存定义了结构体变量后,系统为之分配内存单元,结构体的各成员在内存中是单元,结构体的各成员在内存中是按顺序按顺序连续连续存放的,所以结构体变量在内存中占据的字节存放的,所以结构体变量在内存中占据的字节数是各个成员的长度和,如数是各个成员的长度和,如stu1stu1变量占据内存变量占据内存字节数为字节数为2+8+1+2+4+20=372+8+1+2+4+20=37。学号学号姓名姓名性别性别年龄年龄成绩成绩家庭地家庭地址址intnumcharname8charsexintagefloatscorecharaddr20济南大学Rose2 2、定义类型的同时定义结构体
6、变量、定义类型的同时定义结构体变量:例例 如如:struct 结构体类型名结构体类型名 类型标识符类型标识符1 成员名成员名1;类型标识符类型标识符2 成员名成员名2;类型标识符类型标识符n 成员名成员名n;变量名表变量名表;例例:structstruct note note char name20;char name20;char sex;char sex;char addr20;char addr20;char tel8;char tel8;济南大学Rose3 3、直接定义结构体类型变量、直接定义结构体类型变量:例例 如如:struct 类型标识符类型标识符1 成员名成员名1;类型标识符类
7、型标识符2 成员名成员名2;类型标识符类型标识符n 成员名成员名n;变量名表变量名表;例例:structstruct char name20;char name20;char sex;char sex;char addr20;char addr20;char tel8;char tel8;注意:不出注意:不出现类型名现类型名济南大学Rosestruct date int month;int day;int year;struct student int num;char name8;char sex;int age;struct date birthday;stu1,stu2;济南大学Rose
8、3 结构体变量的引用结构体变量的引用 一般来说,在程序设计中不直接引用结构体变量,而是引用 结构体变量的某个成员变量1 1、成员的引用形式为、成员的引用形式为:成员成员运算符运算符优先级优先级最高。最高。济南大学Rose例例:struct student stu1;引用成员引用成员 stu1.num=9002;gets(stu1.name);stu1.sex=m;printf(“%d,%d”,stu1.num,stu1.name);济南大学Rose2 2、结构体变量使用说明、结构体变量使用说明1.结构体变量通常不能整体使用,不能整体输入、输出,只能对单个成员分别引用。但当结构体变量作为函数参数
9、或赋初值时,可以整体输入;或者两个相同类型的结构体变量,如果一个已经赋值,可以对另外一个整体赋值。济南大学Rose2、结构体变量使用说明2.如果成员本身又属于一个结构体类型,则这个成员也不能整体赋值,要用若干各成员运算符引用,如前面的birthday成员本身又是date类型的变量,则需 stu1.birthday.month=4;stu1.birthday.day=5;stu1.birthday.year=1998;济南大学Rose举例:举例:编程输入一个班级的编程输入一个班级的3030名同学信息,名同学信息,统计来自山东的学生人数。学生信息统计来自山东的学生人数。学生信息由以下几项组成:由以
10、下几项组成:学号,姓名,性别,籍贯学号,姓名,性别,籍贯济南大学Rose程序主要步骤:程序主要步骤:1 1、定义数据类型,结构体类型、定义数据类型,结构体类型studentstudent。2 2、定义该类型的数组、定义该类型的数组cai0801cai0801,长度,长度3030。3 3、循环程序,输入、循环程序,输入3030名同学信息。名同学信息。循环次数:循环次数:3030次,固定次数的循环。次,固定次数的循环。循环体内容:循环体内容:依次为每个元素的各个成员依次为每个元素的各个成员 输入数据。输入数据。比较籍贯成员项的数据是否为比较籍贯成员项的数据是否为 “山东山东”,如果是,则计数器加,
11、如果是,则计数器加1.1.4 4、输出统计后的、输出统计后的countcount值。值。济南大学Rosestruct student char num11;char name8;char sex;char addr20;;main()struct student cai080110;int i,count=0;printf(“input 30 students information:n”);for(i=0;i.num=89101;strcpy(p-.name,Li Lin);/*观察观察name的赋值方式的赋值方式*/p-.sex=M;p-.score=89;济南大学Rose7 7、结构体数
12、组应用举例、结构体数组应用举例 例例11.2 对候选人得票的统计程序。设有对候选人得票的统计程序。设有3个候选人,个候选人,每次输入一个得票的候选人的名字,要求最后输出每次输入一个得票的候选人的名字,要求最后输出各人的得票结果。各人的得票结果。程序定义一个全局结构体数组程序定义一个全局结构体数组leader,并初始化。,并初始化。struct person char name20;int count;leader3=li,0,zhang,0,fu,0;循环循环10次,每次输入一个选举者输入的候选人名次,每次输入一个选举者输入的候选人名字,然后再依次与字,然后再依次与3个候选人比较,是谁的名字就
13、让个候选人比较,是谁的名字就让其得票数加其得票数加1,最后输出统计结果。,最后输出统计结果。济南大学Rose补充:结构体指针对结构体数组的访问补充:结构体指针对结构体数组的访问 struct student int num;char name20;char sex;float score;main()struct student stu3=10101,Li Lin,M,87.5,10102,Zu Feng,F,98,10103,Wang Mi,M,78;struct student*p;for(p=stu;pnum,p-name,p-sex,p-score);济南大学Rose补充:结构体做为函
14、数的参数补充:结构体做为函数的参数 struct student int num;char name20;float score3;void print(struct student stu)printf(%dn%sn%fn%fn%fn,stu.num,stu.name,stu.score0,stu.score1,stu.score2);main()struct student stu;stu.num=12345;strcpy(stu.name,Li Li);stu.score0=67.5;stu.score1=89;stu.score2=78;print(stu);济南大学Rose本小节内容
15、回顾本小节内容回顾 结构体使用的步骤:先定义类型,再定义变量或数组(带上struct关键字)使用;使用时通常要分成员引用操作。成员引用运算符。structstruct note note char name20;char name20;char sex;char sex;char addr20;char addr20;char tel8;char tel8;;structstruct note note 济南大学Rose 注意:结构体成员如果是字符串数据,如:char name10;则该成员赋值时比较特殊,不能整体赋值,应使用strcpy()函数。name“张灵”;strcpy(name,“张
16、灵”)济南大学Rose 结构体的各成员在内存中是按顺序连续结构体的各成员在内存中是按顺序连续存放的,所以结构体变量在内存中占据存放的,所以结构体变量在内存中占据的字节数是各个成员的长度和。的字节数是各个成员的长度和。structstruct note note char name20;char name20;char sex;char sex;char addr20;char addr20;char tel8;char tel8;tt tt;则变量则变量tttt占据的内占据的内存空间长度为存空间长度为4949济南大学Rose8 共用体共用体1.共用体的概念所谓所谓“共用体共用体”类型类型,是指
17、使几个不同类型的是指使几个不同类型的成员共同占用同一段内存单元。成员共同占用同一段内存单元。济南大学Rose2.共用体的定义例例1:union data int i;char ch;float f;aa,bb,cc;union共用体类型名共用体类型名类型标识符类型标识符1 成员名成员名1;类型标识符类型标识符2 成员名成员名2;.类型标识符类型标识符n 成员名成员名n;济南大学Rose例例2:union data int i;char ch;float f;;union data aa,bb;例例3:union int i;char ch;float f;aa,bb,cc;共用体类型的变量声明
18、形式也有共用体类型的变量声明形式也有3种,同结构体类型。种,同结构体类型。济南大学Rose实 型整 型union data int i;char ch;float f;aa;共用体变量所占内存的共用体变量所占内存的长度等于最长的成员的长度等于最长的成员的长度。而不是各成员的长度。而不是各成员的长度之和,这一点不同长度之和,这一点不同于结构体。于结构体。每一瞬时只能存放其每一瞬时只能存放其中的一个成员,而不是中的一个成员,而不是同时存放几种,即其它同时存放几种,即其它成员不起作用。成员不起作用。字符 型济南大学Rose3.共用体变量的引用 共用体变量只能引用它的成员,不能引用共用共用体变量只能引
19、用它的成员,不能引用共用体变量本身。体变量本身。例如前例中的变量例如前例中的变量aa,可以引用它的成员,可以引用它的成员 aa.i=56;aa.f=123.6432;aa.ch=A;如下使用是错误的:如下使用是错误的:printf(“%d”,aa);济南大学Rose4.共用体类型数据的特点(1)每一瞬时只能存放其中的一个成员,而不是同时存放)每一瞬时只能存放其中的一个成员,而不是同时存放几种,即其它成员不起作用。几种,即其它成员不起作用。(2 2)只有最后一个存放的成员的值有效,其他成员将失去)只有最后一个存放的成员的值有效,其他成员将失去原值。原值。如上例中的变量如上例中的变量aa 只有最后
20、一个成员值只有最后一个成员值aa.ch=A是有效的。是有效的。(3 3)共用体变量的地址和它的成员地址都是同一地址。)共用体变量的地址和它的成员地址都是同一地址。即即&aa和和&aa.i、&aa.ch、&aa.f的起始地址都是一样的。的起始地址都是一样的。(4 4)共用体变量不能初始化,也不能对变量名整体赋值,)共用体变量不能初始化,也不能对变量名整体赋值,不能引用变量名来输出一个值,只能引用它的某个成员。不能引用变量名来输出一个值,只能引用它的某个成员。济南大学Rose(5)共用体变量不能作为函数的参数,也不能作为函数返)共用体变量不能作为函数的参数,也不能作为函数返回值。但可以使用指向共用
21、体变量的指针。回值。但可以使用指向共用体变量的指针。(6 6)可以定义共用体数组。)可以定义共用体数组。(7 7)共用体类型可以出现在结构体中,共用体成员也可以)共用体类型可以出现在结构体中,共用体成员也可以是结构体类型。是结构体类型。Rose共用体与结构体混合使用共用体与结构体混合使用济南大学Rose例例11.12 设有若干个人员的数据,其中有学生和教师。设有若干个人员的数据,其中有学生和教师。学生的数据包括:学生的数据包括:姓名、号码、性别、职业、班级。姓名、号码、性别、职业、班级。教师的数据包括:教师的数据包括:姓名、号码、姓别、职业、职务。姓名、号码、姓别、职业、职务。现要求把他们放在
22、同一表格中,要求输入人员的数据,现要求把他们放在同一表格中,要求输入人员的数据,然后再输出。见图。然后再输出。见图。numnamesexjobclass position101Lifs501102Fengmtprof如果如果job项为项为s,则第,则第5项为项为class,如果,如果job项为项为t,则第,则第5项为项为position。济南大学Rose数据类型定义:数据类型定义:整体是一个结整体是一个结构体类型;其中第构体类型;其中第5 5项可以用共用体项可以用共用体来处理。来处理。struct member int num;char name20;char sex;char job;uni
23、on int class;char position10;catagory;mem20;济南大学Rose9 枚举类型枚举类型 所谓所谓“枚举枚举”,是指将变量的所有取值一,是指将变量的所有取值一一列举出来,变量的取值只限于列举出来的值一列举出来,变量的取值只限于列举出来的值的范围。该变量称之为枚举型变量。的范围。该变量称之为枚举型变量。所列举的值叫做所列举的值叫做枚举元素枚举元素(枚举常量)。(枚举常量)。关键关键字字类型名和枚举元素类型名和枚举元素名由用户自己命名名由用户自己命名类型名和枚举元素类型名和枚举元素名由用户自己命名名由用户自己命名例例1:enum weekdaysun,mon,t
24、ue,wd,thu,fri,dat;enum weekday day;济南大学Rose例例2:enum weekday sun,mon,tue,wd,thu,fri,dat day;例例3:enum sun,mon,tue,wd,thu,fri,dat day;定义一个枚举类型名,再用它定义变量。定义一个枚举类型名,再用它定义变量。enum 枚举类型名枚举类型名枚举元素,枚举元素,枚举元素枚举元素,枚举元素,枚举元素n;enum 枚举类型名变量列表;枚举类型名变量列表;济南大学Rose说明:说明:1、C语言中枚举元素按语言中枚举元素按常量常量处理,它们是有值的。它处理,它们是有值的。它们的值是
25、系统按其定义顺序自动赋予的们的值是系统按其定义顺序自动赋予的 0、1、2、3、4、。因此上例中的枚举元素因此上例中的枚举元素sun的值为的值为0,mon的值为的值为1,依次类推。枚举变量的值即是它所取的枚举元素的值,依次类推。枚举变量的值即是它所取的枚举元素的值,此值可输出查看,如此值可输出查看,如dayfri;则;则day的值为的值为5,可以,可以输出输出printf(“%d”,day);输出结果为输出结果为5。济南大学Rose2、枚举元素是常量,但不是字符串。、枚举元素是常量,但不是字符串。如元素如元素sun是常量值为是常量值为7,但不是字符串,但不是字符串“sun”不要希望不要希望wee
26、k1=sun;printf(“%s”,week1);就能;就能打印出打印出“sun,.”,可以用下面语句检查输出:可以用下面语句检查输出:if(week1=sun)printf(“sun”);。济南大学Rose4、枚举变量取值只能是所列举的枚举元素,不能直、枚举变量取值只能是所列举的枚举元素,不能直接赋予一个整数值,如:接赋予一个整数值,如:day2;3、枚举元素的值也可以改变,但必须在定义时指定。、枚举元素的值也可以改变,但必须在定义时指定。如:如:enum weekday sun=7,mon=1,tue,wd,thu,fri,dat;如果定义时未指定值,则按顺序取默认值。如果定义时未指定值,则按顺序取默认值。济南大学Rose例题:例题:键盘输入键盘输入-的任意整数,表示星期日,的任意整数,表示星期日,到分别表示星期一到星期六。要求写出程序输到分别表示星期一到星期六。要求写出程序输出对应的英文名称。出对应的英文名称。Ex11_buchong.cEx11_buchong.c济南大学Rose本章总结本章总结 结构体、共用体、枚举类型的定义 先定义类型,再定义变量。成员引用 结构体变量空间的计算、共用体变量空间的计算。结构体指针及指向运算符。枚举类型元素值的计算。