1、共 40 页 第 1 1 页共 40 页 第 2 2 页 掌握结构类型数据的定义和引用;掌握结构类型数据的定义和引用; 了解共用体类型数据的定义和引用。了解共用体类型数据的定义和引用。共 40 页 第 3 3 页 如果将这些属性分别定义为互相独立的简单变量,则难以如果将这些属性分别定义为互相独立的简单变量,则难以反映相互间的反映相互间的内在联系内在联系( (同一个学生的属性同一个学生的属性) ) 可采用可采用结构体数据结构结构体数据结构描述上述信息描述上述信息, ,将不同类型的数据将不同类型的数据组合成一个有机的整体,这些数据是相互联系的。组合成一个有机的整体,这些数据是相互联系的。问题:问题
2、:l结构是逻辑上相互联系的一组分量的集合。结构是逻辑上相互联系的一组分量的集合。l结构中的分量可以是不同类型的数据,结构中的分结构中的分量可以是不同类型的数据,结构中的分量称为结构的成员量称为结构的成员一个学生有学号一个学生有学号/姓名姓名/性别性别/年龄年龄/地址等属性地址等属性在使用结构之前,首先要对结构的组成进行描述,称为在使用结构之前,首先要对结构的组成进行描述,称为结构结构的定义的定义。结构定义说明了该结构的组成成员,以及每个成员。结构定义说明了该结构的组成成员,以及每个成员的类型。的类型。n u mn am esexageaddr1 0 0 1 0L i m inM1 8D ali
3、an共 40 页 第 4 4 页例例: :structstruct student student int int num; num; char name20; char name20; char sex; char sex; int int age; age; char addr30; char addr30; ; 定义一个结构体类型定义一个结构体类型的一般形式为:的一般形式为:struct 结构体结构体类型名类型名 成员表列成员表列 ;对各成员都要进行类型说明;对各成员都要进行类型说明;成员名定名规则与变量名同。成员名定名规则与变量名同。共 40 页 第 5 5 页方法一:方法一:先定义结
4、构体类型再定义变量名先定义结构体类型再定义变量名structstruct student studentintint num; num; char name20; char name20; char sex; char sex; int int age; age; char addr30; char addr30; ;structstruct student student1, student2; student student1, student2;定义定义studet1和和sudent2为为struct student类型变量类型变量不能只指定一个变不能只指定一个变量为量为“struct型
5、型”而不而不指定结构体名指定结构体名共 40 页 第 6 6 页可用符号常量代表一个结构体类型,如:可用符号常量代表一个结构体类型,如:#define #define STUDENTSTUDENT struct struct student studentSTUDENTSTUDENTintint num; num; char name20; char name20; char sex; char sex; int int age; age; char addr30; char addr30;这样,可直接用这样,可直接用STUDENT定义变量,如:定义变量,如:STUDENT student1,
6、 student2;此时,不必再写关键字此时,不必再写关键字struct共 40 页 第 7 7 页方法二:方法二:在定义类型的同时定义变量,在定义类型的同时定义变量,如:如:structstruct student studentintint num; num; char name20; char name20; char sex; char sex; int int age; age; char addr30; char addr30;student1, student2;student1, student2;一般形式:一般形式:struct 结构体名结构体名 成员表列成员表列 变量名表列
7、;变量名表列;共 40 页 第 8 8 页方法三:方法三:直接定义结构类型变量。直接定义结构类型变量。其一般形式是:其一般形式是:structstruct 成员表列成员表列 变量名表列;变量名表列;此时,不出现结构体名此时,不出现结构体名共 40 页 第 9 9 页几点说明:几点说明:1. 1. 类型与变量是不同概念,不要混淆;类型与变量是不同概念,不要混淆;2. 2. 结构体中的成员,可以单独使用,其作用与结构体中的成员,可以单独使用,其作用与地位相当于普通变量;地位相当于普通变量;3. 3. 成员也可以是一个结构体变量;例如:成员也可以是一个结构体变量;例如:struct date int
8、 month; int day; int year; ;Struct studentint num;char name20;int age;struct date birthday;student1,student2;4. 成员名可以与程序中的变量名相同,二者不成员名可以与程序中的变量名相同,二者不代表同一对象。代表同一对象。共 40 页 第 1010 页10.1.3 10.1.3 结构体变量的引用结构体变量的引用规则:规则:1.1. 不能将一个结构体变量作为一个整体进行赋值和不能将一个结构体变量作为一个整体进行赋值和输出;只能对其各个成员分别输出输出;只能对其各个成员分别输出 引用形式为:引
9、用形式为:结构体变量名结构体变量名. .成员名成员名printfprintf(“(“.”,student1);.”,student1);printfprintf(“ %d”, student1.num); (“ %d”, student1.num); 输出输出 1001010010错!正确!2 . 若成员本身又属一个结构体类型,只能对最低若成员本身又属一个结构体类型,只能对最低级的成员进行赋值或存取以及运算。级的成员进行赋值或存取以及运算。 如:如:student1.birthday.year=2010共 40 页 第 1111 页3.3. 对成员变量可以象普通变量一样进行各种运算,对成员变量
10、可以象普通变量一样进行各种运算,如:如: sumagesumage=student1.age+student2.age;=student1.age+student2.age;4.4. 可以引用成员的地址,也可以引用结构体变量的可以引用成员的地址,也可以引用结构体变量的地址地址, ,如如 scanf(“%d”,&student1.num);scanf(“%d”,&student1.num); printf(“%o”,&student1); printf(“%o”,&student1); scanf(“%d,%s,%c,%d,%s”,&student1); scanf(“%d,%s,%c,%d,%
11、s”,&student1);错!错!输入输入student1.num的值的值输出输出student1的首地址的首地址共 40 页 第 1212 页 10.1.4 10.1.4 结构体变量的初始化结构体变量的初始化main( )main( ) struct struct student student long int long int num; num; char name20; char name20; char sex; char sex; char addr20; char addr20; a=9801,”Wang hong”,W,”2 Linggong a=9801,”Wang hon
12、g”,W,”2 Linggong Road”;Road”;printf(“No.:%ldnname:%snsex:%cnaddress:%sprintf(“No.:%ldnname:%snsex:%cnaddress:%sn”,a.num,a.name,a.sex,a.addrn”,a.num,a.name,a.sex,a.addr);); 运行结果为:No.:9801name:Wang hongsex:Waddress:2 Linggong Road共 40 页 第 1313 页l 在结构体在结构体中中使用使用数组数组类型类型作为作为结构的一个结构的一个成员成员;l 用结构体用结构体类型类型
13、作为作为数组元素的数组元素的基类型构成数组基类型构成数组。结构与数组的关系结构与数组的关系例:例:structstruct student student int xh int xh; ; char xm14; char xm14; char xb char xb; ; float sx float sx; ; xscj96; xscj96;96个元素都具有结构数据类型共 40 页 第 1414 页 结构体数组是一个数组,数组中的每一个元素结构体数组是一个数组,数组中的每一个元素都是结构类型。都是结构类型。 说明结构数组的方法:先定义一个结构,再用说明结构数组的方法:先定义一个结构,再用结构类
14、型说明一个数组变量。结构类型说明一个数组变量。例例:为记录为记录100个人的基本情况,说明一个有个人的基本情况,说明一个有100个元个元素的数组。数组的素的数组。数组的基类型为结构基类型为结构 structstruct person person char name 30; char sex; struct date birthday manman100100 ;(;(数组名与结构体名可以不同数组名与结构体名可以不同) )man就是有就是有100个元素的结构数组,数组的每个个元素的结构数组,数组的每个元素为元素为 person 型。型。10.2.110.2.1结构体数组的定义结构体数组的定义共
15、 40 页 第 1515 页例如:structstruct student studentintint num; num; char name20; char name20; char sex; char sex; int int age; age; char addr30; char addr30; struct struct student stu3; student stu3;struct student int num; stu3;或或struct int num; stu3;一般形式:structstruct 结构体类型名结构体类型名 元素元素 ;structstruct 结构体类型
16、名结构体类型名 结构体数组名结构体数组名; ;共 40 页 第 1616 页strcpy ( man3.name, Fangjinstrcpy ( man3.name, Fangjin” );” );man3.sex = M;man3.sex = M;man3.birthday.year = 1963;man3.birthday.year = 1963;man3.birthday.month = 9;man3.birthday.month = 9;man3.birthday.day = 13;man3.birthday.day = 13;例如:例如:要将数组要将数组manman中的中的3 3号
17、元素赋值为:号元素赋值为:FangjinFangjin, M, 1963, 9, 13, M, 1963, 9, 13,使用下列语句:使用下列语句:为数组中一个元素的每个成员赋值为数组中一个元素的每个成员赋值共 40 页 第 1717 页结构数组存放在连续的内存区域中,所占结构数组存放在连续的内存区域中,所占内内存大小存大小为为结构类型的大小结构类型的大小乘以数组元素的乘以数组元素的数数量量。structstruct person man100: 37 person man100: 37* *100 = 100 = 37003700字节字节301 222301 222301 222.ns ym
18、dns ymdns ymdman0man1man99 将将“FangjFangji in n”改为改为“FangjFangju un n”: manman3 3.name.name5 5 = = u u;/ /* *为数组中元素的数组成员中的一个字符赋值为数组中元素的数组成员中的一个字符赋值* */ /共 40 页 第 1818 页10.2.3 10.2.3 结构体数组的初始化结构体数组的初始化structstruct student studentintint num; num; char name20; char name20; char sex; int char sex; int ag
19、e; age; char addr30; char addr30; stu3=111,”Li”,M,18,”Dalian”, stu3=111,”Li”,M,18,”Dalian”,;也可采用:也可采用:structstruct student student int int num; num; ; ; struct student stu struct student stu=,;结构体数组的初始化的一般形式是在结构体数组的初始化的一般形式是在定义数组后面加上:定义数组后面加上:=初值表列初值表列;共 40 页 第 1919 页例:设有三个候选人,每次输入一个得票的候选人的名字,要例:设有三
20、个候选人,每次输入一个得票的候选人的名字,要求最后输出各人得票结果。求最后输出各人得票结果。#include “string.h#include “string.h”structstruct person person char name20; char name20; int int count; count; leader3=“Li”,0,”zhang”,0,”Liu”,0; leader3=“Li”,0,”zhang”,0,”Liu”,0;main( )main( ) int int i, j; i, j; char leader_name20; char leader_name20;
21、for( i= for( i=1 1;i=10;i+);i=10;i+) scanf(“%s”,leader_name scanf(“%s”,leader_name);); for(j=0;j3;j+) for(j=0;j3;j+) if(strcmp(leader_name,leaderj.name if(strcmp(leader_name,leaderj.name)=0) )=0) leaderj.count leaderj.count+;+; for(i for(i=0;i3;i+)=0;i3;i+) printf(“%5s:%dn”,leaderi.name,leaderi.coun
22、t); printf(“%5s:%dn”,leaderi.name,leaderi.count); 共 40 页 第 2020 页/例例: : 编写一个编写一个3030名学生信息状况的示意性检索程序,名学生信息状况的示意性检索程序,每名学生的信息包括:每名学生的信息包括:xhxh( (学号学号) )、xbxb(性别)、(性别)、cjcj(成绩)、(成绩)、xmxm( (姓名姓名) )。要求:要求:(1 1)输入)输入3030名学生信息;名学生信息;(2 2)输出男同学中成绩大于)输出男同学中成绩大于9090的学生的的学生的xmxm、xbxb、cjcj。 共 40 页 第 2121 页struc
23、tstruct student student int xh int xh; ; char xb char xb; ; int cj int cj; ; char xm20; char xm20; main()main() struct struct student stu30; student stu30; int int i; i; for(i for(i=0;i30;i+)=0;i30;i+) scanf(%d%c%d,&stui.xh,&stui.xb,&stui.cj); scanf(%d%c%d,&stui.xh,&stui.xb,&stui.cj); gets(stui.xmge
24、ts(stui.xm);); for(i for(i=0;i30;i+)=0;i=90) if(stui.xb=m&stui.cj=90) printf(%s,%c,%dn,stui.xm,stui.xb,stui.cjprintf(%s,%c,%dn,stui.xm,stui.xb,stui.cj);); 共 40 页 第 2222 页 结构与指针的关系结构与指针的关系: :l将指针作为结构中的一个成员将指针作为结构中的一个成员; ;l指向结构的指针指向结构的指针( (称为结构体变量的指针称为结构体变量的指针).). 结构体变量的指针:结构体变量的指针: 是该是该结构体结构体变量所占居的内存
25、段的起始地址。变量所占居的内存段的起始地址。 结构体变量指针说明的一般形式结构体变量指针说明的一般形式: : structstruct 结构类型名结构类型名 * *结构指针变量名结构指针变量名; ; 例如例如:struct date :struct date * *pdate,todaypdate,today; ; pdate pdate=&today;=&today;yearmonthdaytoday (struc date)pdate共 40 页 第 2323 页通过指针访问结构中的成员通过指针访问结构中的成员: : 采用运算符采用运算符“-”-”进行操作。进行操作。结构指针结构指针-成员
26、名成员名“-”-”运算符优先级最高运算符优先级最高(15(15级级) ),从左至右结合,从左至右结合。注:注:C C语言中优先级为语言中优先级为1515的运算符有的运算符有4 4种:种:( ) . -( ) . - 例例: p-: p-成员名成员名 或或 ( (* *p).p).成员名成员名 分析以下运算:分析以下运算:p-np-n 得到得到p p指向的结构体变量中的成员指向的结构体变量中的成员n n的值的值p-n+ p-n+ 得到得到p p指向的结构体变量中的成员指向的结构体变量中的成员n n的值的值用完后使它加用完后使它加1 1; 相当于:相当于:( (p-n)+p-n)+ +p-n +p
27、-n 得到得到p p指向的结构体变量中的成员指向的结构体变量中的成员n n的值的值 使其先加使其先加1 1;相当于:;相当于:+(p-n)(p-n) 共 40 页 第 2424 页例如:例如:main( )main( )structstruct student studentlong intlong int num; num; char name20; char name20; char sex; char sex;structstruct student stu_1; student stu_1;structstruct student student * *p;p;p=&stu_1p=&s
28、tu_1;stu_1.num=9901;strcpy(stu_1.name,”Li Min”);stu_1.sex=W;printf(“No.:%ldnname%snsex:%cn”,stu_1.num,stu_1.name,stu_1.sex);printf(“nNo.:%ldnname%snsex:%cn”,(*p).num,(*p).name,p-sex);共 40 页 第 2525 页例例:找到年龄最大的人,并输出。请找出程序中:找到年龄最大的人,并输出。请找出程序中是否有是否有问题。问题。#define N 4#define N 4#include “stdio.h”#include
29、 “stdio.h”struct manstruct man char name20; char name20; int age; int age;personN=“li”,18,“wang”,19,“zhang”,20,“sun”personN=“li”,18,“wang”,19,“zhang”,20,“sun”,22;,22;main()main()struct man struct man * *q,q,* *p;p; int i,m=0; int i,m=0; p=person; p=person; for (i=0;iN;i+) for (i=0;iN;i+) if(m if(mag
30、e)age) q=p+;q=p+; m=q-age;m=q-age; printf(%s,%d,q printf(%s,%d,q- - name,qname,q-age);-age); 共 40 页 第 2626 页 main() main()structstruct student student int int num; num; int int age; age; ; ; struct struct student stu3=1000,20,1001,19,1003,23; student stu3=1000,20,1001,19,1003,23; struct struct stude
31、nt student * *p;p; p=stu p=stu; ; printf(“%dn printf(“%dn”,(”,(* *p+).num);p+).num); 输出结果:输出结果:1000改成:改成:(*+p).num结果为:结果为:1001共 40 页 第 2727 页#include “stdio.h#include “stdio.h”structstruct student student int int num; num; char name20; char name20; float score3; float score3;stustu=20701,”lili”,67.5
32、,88,79.6;=20701,”lili”,67.5,88,79.6;void print(structvoid print(struct student student * *p)p) printf(“%d %s %5.1f %5.1f %5.1fn”,p-num,p- printf(“%d %s %5.1f %5.1f %5.1fn”,p-num,p-name,pname,p-score0,p-score1,p-score2);-score0,p-score1,p-score2); main()main()print(&stuprint(&stu);); 共 40 页 第 2828 页1
33、0.4.1 10.4.1 共用体的概念共用体的概念共用体:共用体:使几个不同的变量共占同一段内存的结构,使几个不同的变量共占同一段内存的结构,称为称为“共用体共用体”类型的结构。类型的结构。“共用体共用体”类型变量的定义形式为:类型变量的定义形式为:union union 共用体名共用体名 成员表列成员表列 变量表列;变量表列;例如:例如:union dataunion dataintint i; i; char ch char ch; ; float f;a,b,c; float f;a,b,c;或或union dataint i;char ch;float f;union data a,b
34、,c;或或union int i;char ch;float f; a,b,c;直接直接定义定义先定义先定义类型类型共 40 页 第 2929 页 结构体类型变量所占内存长度是各成员占结构体类型变量所占内存长度是各成员占的内存的内存长度之和长度之和。 共用体类型变量所占内存长度等于共用体类型变量所占内存长度等于最长的最长的成员的长度成员的长度。 成员成员分量分量之间是之间是相互联系相互联系的,所进行的操的,所进行的操作相互依赖。作相互依赖。共 40 页 第 3030 页 #include stdio.h #include union pp union pp int int i; i; char
35、 ch2; char ch2; a; a; main() main() a.ch0=1; a.ch0=1; a.ch1=3; a.ch1=3; printf(“%dn”,a.i printf(“%dn”,a.i);); a的内存存储情况如下:的内存存储情况如下:a.ia.ch1a.ch00 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1输出结果:输出结果:769低低字字段段高高字字段段(1401)8共 40 页 第 3131 页注意:注意:只能引用共用体变量中的成员,不能引用只能引用共用体变量中的成员,不能引用共用体变量本身。如:共用体变量本身。如:可以引用可以引用 a .i(a
36、.i(引用共用体变量中的整型变量引用共用体变量中的整型变量i)i) a .ch a .ch( (引用共用体变量中的字符变量引用共用体变量中的字符变量chch) ) a .f( a .f(引用共用体变量中的实型变量引用共用体变量中的实型变量f)f)不能只引用共用体变量,如:不能只引用共用体变量,如: printf(“%d”,aprintf(“%d”,a););错啦!错啦!共 40 页 第 3232 页1.1.每一瞬时只有一个成员起作用每一瞬时只有一个成员起作用 ;2.2.共用体变量中起作用的成员是最后一次存放的成员;共用体变量中起作用的成员是最后一次存放的成员;3.3.共用体变量的地址和它的各成
37、员的地址都是同一地址;共用体变量的地址和它的各成员的地址都是同一地址;4.4.不能对共用体变量名赋值,也不能不能对共用体变量名赋值,也不能通过通过引用变量名来得到引用变量名来得到成员的值,不能在定义共用体变量时对它初始化。成员的值,不能在定义共用体变量时对它初始化。5.5.不能把共用体变量作为函数参数,也不能使函数带回共用不能把共用体变量作为函数参数,也不能使函数带回共用体变量,但可使用指向共用体变量的指针;体变量,但可使用指向共用体变量的指针;6.6.共用体类型可以出现在结构体类型定义中,也可以定义共共用体类型可以出现在结构体类型定义中,也可以定义共用体数组。而结构体也可以出现在共用体类型定
38、义中,数用体数组。而结构体也可以出现在共用体类型定义中,数组也可以作为共用体的成员。组也可以作为共用体的成员。共 40 页 第 3333 页 若一个变量只有几种可能的值,可以定义为若一个变量只有几种可能的值,可以定义为枚举类型枚举类型。所谓所谓“枚举枚举”是指将变量的值一一列举出来,变量的值是指将变量的值一一列举出来,变量的值只限于列举出来的值的范围内。只限于列举出来的值的范围内。 定义方法:定义方法:先定义枚举类型先定义枚举类型 enum weekday sun, mon, tue, wed, thu, frienum weekday sun, mon, tue, wed, thu, fri
39、, , sat;sat;再用此类型定义变量,如:再用此类型定义变量,如:enumenum weekday workday, week_end; weekday workday, week_end;或或直接定义枚举变量。如:直接定义枚举变量。如:enum weekday sun, mon, tue, wed, thu, frienum weekday sun, mon, tue, wed, thu, fri, sat , sat workday,week_end;workday,week_end;共 40 页 第 3434 页 枚举元素为常量,不是变量,故不能对它们赋值枚举元素为常量,不是变量,
40、故不能对它们赋值 枚举常量有值。如上面定义中,枚举常量有值。如上面定义中,sun sun 、 mon mon 、 tuetue sat sat的值依次为的值依次为0 0、1 1、2 27 7 也可改变枚举元素的值,在定义时指出,如:也可改变枚举元素的值,在定义时指出,如: enumenum weekdaysun=7,mon=1,tue,wed,thu,fri,sat; weekdaysun=7,mon=1,tue,wed,thu,fri,sat; 枚举值可用来作判断比较,如:枚举值可用来作判断比较,如: if(workday=monif(workday=mon) if(workdaysun)
41、if(workdaysun) 一个整数不能直接赋值给一个枚举变量,应先进行强制类一个整数不能直接赋值给一个枚举变量,应先进行强制类型转换才能赋值,如:型转换才能赋值,如: workday=(enumworkday=(enum weekday)2; ( weekday)2; (相当于将序号为相当于将序号为2 2的枚举的枚举元素值赋给元素值赋给workday , workday , 即:即:workday=tueworkday=tue; ;共 40 页 第 3535 页l 标准类型(如标准类型(如intint、charchar、longlong、doubledouble等)系等)系统已经定义好的类
42、型,用户可以直接使用,无须再统已经定义好的类型,用户可以直接使用,无须再进行定义。进行定义。l 用户自定义类型:用户根据自己的实际要求,将已用户自定义类型:用户根据自己的实际要求,将已有的类型重新命名为一个新的简单类型。有的类型重新命名为一个新的简单类型。除除结构结构和和联合联合等类型之外,还可以用类型说明等类型之外,还可以用类型说明语句语句typedeftypedef定义新的类型来代替已有的类型。定义新的类型来代替已有的类型。共 40 页 第 3636 页l例例 typedeftypedef intint INTEGER;INTEGER; typedeftypedef floatfloat
43、REAL;REAL;在具有上述在具有上述typedeftypedef语句的程序中,下列语句是语句的程序中,下列语句是等价的:等价的: int i,j; float paiint i,j; float pai; 等价于等价于 INTEGER i, j; REAL paiINTEGER i, j; REAL pai; ; 10.6.2 typedef 10.6.2 typedef语句的一般形式语句的一般形式typedeftypedef 已定义的类型已定义的类型 新的类型新的类型共 40 页 第 3737 页l例例 typedeftypedef structstruct node node int int data; data; struct struct * *link;link; JD JD定义了一个新的结构体类型定义了一个新的结构体类型JDJD, ,它代表结构体它代表结构体structstruct node . node .以后可以使用以后可以使用JDJD来定义变量来定义变量: : JD JD * *s; s; 定义指向结点类型的指针定义指向结点类型的指针s s