• 1. 第9章 结构体等构造数据类型
  • 2. 9.1 结构体构造数据类型就是由基本数据类型按照一定的规则组合在一起而构成的数据类型。包括数组、结构体、联合体和枚举。 结构体的概念 是C语言中的构造类型,是由不同数据类型的数据组成的集合体。 为处理复杂的数据结构提供了手段。 为函数间传递不同类型的参数提供了便利。
  • 3. 9.1.1 问题的提出与程序示例 P238表9-1 P239例9.1
  • 4. 定义结构体类型 struct 结构体名 { 数据类型 成员名 1; 数据类型 成员名 2;  : 数据类型 成员名 n; }; 变量说明形式 struct 结构体名 结构体变量名;注意: 结构变量的存储类型概念、它的寿命、可见性及使用范围与普通变量、数组等完全一致。 结构变量说明必须在结构类型定义之后,二者也可同时进行。 结构变量占内存大小可用 sizeof 运算求出: sizeof(变量)9.1.2 结构体的说明和结构体变量的定义
  • 5. 结构体变量有三种定义方法 (1)先定义结构体类型,再定义变量名(格式见上页) 如: struct student { int num; char name [50]; int age; …… }; struct student student1, student2; 即student1和student2具有struct student的结构
  • 6. (2)在定义结构类型的同时定义变量 struct student { int num; char name [50]; int age; …… }student1,student2;
  • 7. (3)不定义结构类型名,直接定义结构类型变量 struct /*此处没有结构体名*/ { int num; char name[50]; int age; …… } student1,student2;
  • 8. 在应用过程中,也可以把一个结构体的成员作为另一个结构体的变量(即一个结构体的成员的类型是另一个结构体),如结构体student : struct date { int month; int day; int year; };struct student { int num; …… struct date brithday; }student1,student2;
  • 9. 不能将一个结构体变量作为一个整体加以引用,而只能对结构体变量中各个成员进行引用。 如:printf(“ …”,student1);(错误) 结构体成员的引用格式:结构体变量名.成员 如果成员本身又属于另一个结构体类型,如前面讲到的student,则应做如下引用: student1.birthday.month student2.birthday.year (要逐级找到最低一级的成员)9.1.3 结构体成员的引用
  • 10. 对成员变量可以象普通变量一样进行各种运算, 成员地址与结构体地址都可以引用, 如: scanf(“ %d”,&student1.num); 它是成员地址 printf(“ %d”,&student1); 它是结构体地址 "."运算优先于"*"运算: *student1.name 等同于 *(student1.name)
  • 11. 结构体变量的初始化与对数组的初始化相似,在定义时初始化。 如果初始化数值的个数小于结构体成员的个数,系统自动将其他成员初始化为0。9.1.4 结构体的初始化
  • 12. /********例:结构体的初始化的引用 *****************/ main() { struct regist1 { char *name; char sex; int old; char *addr; }wang,li; wang.name=”Wang zhonghua"; wang.sex='m'; wang.old=20; wang.addr=”Room230,Building 1st,Ts_Univ."; li.name="Li aihua"; li.sex='f'; li.old=21; li.addr=”Room906,Xinzai"; 若结构体变量定义在main函数外,则struct结构体变量变成全局变量,即外部变量,则可以 wang= {”wang zhonghua", ’m’, 25, ”Room230,Building 1st, Ts_Univ."}
  • 13. printf(" name sex old address\n"); printf("-----------------------------------------\n"); printf("%-14s%-4c%-4d%-25s\n", wang.name,wang.sex,wang.old,wang.addr); printf("%-14s%-4c%-4d%-25s\n", li.name,li.sex,li.old,li.addr); }
  • 14. 9.2 结构体数组结构数组的说明格式 struct 结构体名 数组名[长度]; 结构体数组的引用 数组名[下标]. 成员名; 结构体数组的初始化 struct 结构体名 数组名[ ]={初始数据};
  • 15. /******例:使用结构体数组处理通讯录数据 ********/ #include“stdio.h” #include“stdlib.h” #define MAX 3 struct regist { char name[20]; char sex; int old; char addr[100]; }; main() { struct regist man[MAX]; char s[10]; int i;
  • 16. for(i=0;i
  • 17. 9.3 结构体与指针格式: struct 结构体名 *结构体指针变量名; 用结构体指针访问结构成员 (*结构体指针变量名).成员名 或 结构体指针变量名->成员名 运算次序 ++pman->name 等同于 ++(pman->name) *pman->name 等同于 *(pman->name)9.3.1 指向结构体的指针
  • 18. 注意:结构体指针指向的是整个结构体变量,不具体指向结构体的某个成员。但可以通过指向结构体的指针存取结构体的成员。
  • 19. 当结构体中的成员包含指针时,若结构体变量的值是初始的,则不需要动态分配存储空间,若结构体变量的值是用输入语句输入的,则要动态分配存储空间。 如:P247—249例9.6、9.79.3.2 结构体中的成员包含指针 9.3.3 用结构体类型指针建立链表(略)
  • 20. 9.4 结构体与函数(1)用结构体变量的成员作参数。 (2)用指向结构体变量(或数组)的指针做实参,将结构体变量(或数组)的地址传给形参。 (3)整个结构体变量作为函数的实际参数(但有些编译系统不允许)。9.4.1 结构体数据作为函数的参数 struct 结构体名 * 函数名(参数表) 9.4.2 返回指向结构体指针的函数9.4.3 用函数实现动态链表的插入和删除(略)
  • 21. 9.5 联合体 有时需要把几种不同类型的变量(如整型、字符型、实型)放在同一个地址开始的内存单元(即同一段内存单元)中,即几个不同的变量共占一段内存的结构,这种结构称为联合体,又称共用体。 P262-263例 在一个时间点上,一个联合体变量只能存放其中的一种数,用新的数据覆盖老的数据,新的数据的类型决定变量的类型。9.5.1 问题的提出与程序示例
  • 22. 联合体的定义格式: union 联合体名 { 数据类型 成员名 1; 数据类型 成员名 2;  : 数据类型 成员名 n; };例:union uarea { char c; short s; long l; };9.5.2 联合体的说明和联合体变量的定义
  • 23. 联合体变量的定义格式: (1) 先定义联合体,再先定义联合体变量。 union 联合体名 { 数据类型 成员名 1; 数据类型 成员名 2;  : 数据类型 成员名 n; }; union 联合体名 联合体变量名; 例:union uarea { char c; short s; long l; }; union uarea x;
  • 24. (2) 定义联合体的同时定义联合体变量。 union 联合体名 { 数据类型 成员名 1; 数据类型 成员名 2;  : 数据类型 成员名 n; }联合体变量名; 例:union uarea { char c; short s; long l; } x;
  • 25. (3) 不定义联合体类型名,直接定义联合体类型变量。 union { 数据类型 成员名 1; 数据类型 成员名 2;  : 数据类型 成员名 n; } 联合体变量名; 例:union { char c; short s; long l; } x;
  • 26. 使用联合体变量应注意的问题: 1. 同一内存段可用来存放几种不同类型的成员,但每一瞬间 只有一个成员起作用。 2. 如有赋值: a.i=1; a.c=’a’ a.f=1.5; 3. 不能对联合体变量表列赋值,这一点与结构体不一样。 如:union { int i; char ch; float b; }a={a,’a’,1.5}; 这是不对的 4. 不能把联合体变量作为函数参数,也不能用函数带回联合体变量。
  • 27. 联合体变量成员的引用格式: 联合体变量名.成员名9.5.3 联合体变量成员的引用 使用指向联合体变量的指针存取联合体变量成员的语法格式: (*指向联合体变量的指针).成员名 指向联合体变量的指针->成员名9.5.4 指向联合体变量的指针
  • 28. 联合体变量的成员值可作为函数的参数,指向联合体变量的指针也可作为函数的参数,返回值也可以是指向联合体变量的指针;但是,联合体变量不能作为函数的参数,并且函数的返回类型也不是联合体;9.5.5 联合体变量与函数
  • 29. 9.6 枚举如果某些变量只有几种可能,如: 星期一、星期二、… … 星期日 性别及特定范围的概念 可以通过枚举法将变量一一列出,在这种情况下可以使用枚举类型变量
  • 30. 9.6.1 枚举的说明和枚举变量的定义 枚举类型的定义格式: enum 枚举类型名 { 枚举元素表 } ; 如: enum weekday {sun,mon,tue,wed,thu,fri,sat};
  • 31. 枚举变量的定义格式: (1) 先定义枚举类型,再定义枚举类型变量。 enum 枚举类型名 { 枚举元素表 } ; enum 枚举类型名 枚举类型变量名 ; 如:enum color { red,green,blue,yellow,white }; enum color select,change;
  • 32. (2) 在定义枚举类型的同时定义枚举类型变量。 enum 枚举类型名 { 枚举元素表 } 枚举类型变量名;如:enum color { red,green,blue,yellow,white }select,change;
  • 33. (3) 不定义枚举类型名,直接定义枚举类型变量。 enum { 枚举元素表 }枚举类型变量名;如:enum { red,green,blue,yellow,white } select,change;
  • 34. 9.6.2 枚举变量的使用 如果一个变量被定义为一个枚举变量,则它的取值只能取对应的枚举元素,而不能取其它任何值。
  • 35. 应用枚举应注意以下问题: 1. 枚举元素是常量,不是变量,不能对它赋值,如: sun=0; mon=1; 2. 枚举元素作为常量是有值的,而且按顺序0,1,2,… 赋值,如 enum{sun,mon,tue,wed,thu,fri,sat}workday,week_end; 那么, workday和week_end为所列七个元素值之一 若有workday=mon, 则 workday=1 它也可以在元素内强行赋值,如: enum weekday{sun=7, mon=1, tue… … } workday 则tue以后的数自动以1为增量递增 3. 枚举值可以用来作比较,如: if(workday==mon) … … 4. 整数不能直接赋给一个枚举变量,如: workday=2 (不正确,类型不一致) (enum) (int) workday=(enum weekday)2; 把序号2的枚举元素赋给 workday,即tue
  • 36. /***例 分别输入一周中的每天工作时间,并输出总的工资**/ /* 星期天的工资为120RMB/h,星期六为100RMB/h,其他时间80RMB/h */ # include “stdio.h” void main() { enum week{SUN,MON,TUE,WED,THR,FRI,SAT}; enum week day; int total,pay,hour; total=0; printf("Please enter your working hours from SUN to SAT\n");
  • 37. for(day=SUN;day<=SAT;day++) { scanf("%d",&hour); switch(day) { case SUN : pay=hour*120; break; case SAT : pay=hour*100; break; default : pay=hour*80; break; /* from MON to FRI */ } total+=pay; } printf("Your total pay is: %d",total); }
  • 38. 前面我们已经讲过,C的标准类型有: int、char、float、double、long 以及结构体(struct)、共用体(union)、枚举类型(enum)等, 此外还可以定义新的类型来代替已有的类型名,9.7 类型定义
  • 39. 类型定义格式: typedef 原类型名 新类型名;如用typedef定义结构体struct:typedef struct { int month; int day; int year; }DATE;DATE birthday 则birthday具有: month、day、year三个成员DATE成为 结构体类型 以后可用 DATE定义 别的变量名如: typedef int INTEGER; 指定INTEGER为int类型 typedef float REAL; 指定REAL为float类型