1 / 48

计算机程序设计

计算机程序设计. ch 10 结 构 体. 1 结构体 (Structure) 定义与引用. 结构体概述 结构体类型的声明 结构体变量的定义 结构体变量的初始化 结构体变量的引用. 结构体概述. 结构体 将不同类型的数据组合成一个整体 用来表示简单类型无法描述的复杂对象 可以用结构体来定义用户自己的数据结构 举例 描述学生信息. 结构体类型的声明. 一般形式 struct [ 结构体名 ] { 成员表列 }; “ 成员表列 ” 形式 类型 成员名 ; 类型 成员名 ; . 结构体类型声明的说明 (1).

lorant
Download Presentation

计算机程序设计

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 计算机程序设计 ch 10 结 构 体

  2. 1 结构体 (Structure)定义与引用 • 结构体概述 • 结构体类型的声明 • 结构体变量的定义 • 结构体变量的初始化 • 结构体变量的引用

  3. 结构体概述 • 结构体 • 将不同类型的数据组合成一个整体 • 用来表示简单类型无法描述的复杂对象 • 可以用结构体来定义用户自己的数据结构 • 举例 • 描述学生信息

  4. 结构体类型的声明 • 一般形式 • struct [结构体名] { 成员表列 }; • “成员表列”形式 类型 成员名; 类型 成员名; ... ...

  5. 结构体类型声明的说明 (1) • 声明了一种类型,而不是定义变量 • 结构体名可以没有,但是这样就无法再次使用该结构体类型了 • 成员表列中是成员(Member)的定义 • 成员的定义形式与变量定义相同 • 成员类型可以是另一结构体类型,但不可直接或间接递归嵌套(自身); • 成员表列不可为空,至少要有一个成员

  6. 结构体类型声明的说明 (2) • 注意{}后有分号 • 同一结构体的成员不能重名 • 不同结构体的成员可以重名; • 结构体成员和其他变量可以重名; • 结构体类型与其成员或其他变量可重名 • 结构体类型名称是 struct 结构体名, 注意struct关键字不能省略

  7. 结构体类型声明的说明 (3) • 即使两个结构体声明中的成员类型、名称、顺序都完全一致,它们也是不同的类型 • 结构体类型也要“先声明,后使用” • 如果结构体类型声明在函数内部,则该函数之外无法引用此结构体类型 • 一般把结构体类型声明放到文件最前面 • 也可以把结构体类型声明放在头文件里

  8. 结构体类型的声明举例 struct student { unsigned num; /* 学号 */ char name[20]; /* 姓名 */ char sex; /* 性别 */ unsigned age; /* 年龄 */ float score; /* 分数 */ char addr[50]; /* 地址 */ };

  9. 结构体变量的定义 (1) • 先声明结构体类型再定义变量 struct student { unsigned num; char name[20]; char sex; unsigned age; float score; char addr[50]; }; //定义类型 struct student stu1, stu2; //定义变量

  10. 结构体变量的定义 (2) • 在声明结构体类型的同时定义变量a struct student { unsigned num; char name[20]; char sex; unsigned age; float score; char addr[50]; } stu1, stu2;

  11. 结构体变量的定义 (3) • 直接定义无名结构类型变量 struct { unsigned num; char name[20]; char sex; unsigned age; float score; char addr[50]; } stu1, stu2;

  12. 结构体声明和变量定义举例 struct date { int year, month, day; }; struct student{ unsigned num; char name[20]; char sex; struct date birthday; float score; } stu1, stu2;

  13. 结构体变量的初始化 • 按照成员的顺序和类型对成员初始化 struct date date1 = {1990, 10, 20}; struct student stu = { 1001, /*unsigned num*/ "Tom", /*char name[20]*/ 'M', /*char sex*/ {1983, 9, 20},/*struct date birthday*/ 93.5 /*float score*/ };

  14. 结构体变量中成员的引用 • 一般形式 • 结构体变量名.成员名 • 成员运算符 . • 具有最高的优先级,自左向右结合 • 说明 • 结构体成员和同类型的变量用法相同 • 若成员类型又是一个结构体,则可以使用若干个成员运算符,访问最低一级的成员

  15. 结构体变量中成员的引用举例 struct student stu; ... ... scanf("%f", &stu.score); stu.num = 12345; stu.birthday.month = 11; stu.score = sqrt(stu.score) * 10; strcpy(stu.name, "Mike"); printf("No.%d:", stu.num);

  16. 结构体变量整体引用 • 结构体类型变量之间可以直接相互赋值 • 实质上是两个结构体变量相应的存储空间中的所有数据直接拷贝 • 包括复杂类型在内的所有结构体成员都被直接赋值,如字符串、结构体类型等 • 函数的实参和形参可以是结构体类型,并且遵循实参到形参的单向值传递规则 • 为了提高程序的效率,函数的参数多使用结构体类型指针

  17. 结构体变量整体引用举例 struct student stu1, stu2={1002, "Kate", 'F', {1981, 11, 4}, 89.0}; void print(struct student s) { printf("%d,%4s,%c,%d.%02d.%02d,%4.1f\n", s.num, s.name, s.sex, s.birthday.year, s.birthday.month, s.birthday.day, s.score); } void main () { stu1 = stu2; /* 直接赋值 */ print(stu1); /* 1002,Kate,F,1981.11.04,89.0 */ }

  18. 结构体变量整体引用举例 struct Person { char name[20]; int age; //... }; void main() { struct Person John; struct Person clone; strcpy(John.name,”John”); John.age=20; clone = John; //两个结构体变量具有了相同数据 }

  19. 2. 结构体数组 • 结构体数组的用法与基本类型数组类似 • 定义、初始化、引用 • 结构体数组可用于表示二维表格 • 举例 struct student s[10]; for (i=0; i<10; i++) scanf("%d,%s,%c,%d,%f", &s[i].num, s[i].name, &s[i].sex, &s[i].age, &s[i].score);

  20. 结构体数组初始化及应用举例 struct student stu[] = { {1001,"Tom",'M',{1980,1,2},85.5}, {1002,"Kate",'F',{1981,11,4},89.0}, {1003,"Mike",'M',{1980,3,5},95.5}}; for (i=0; i<3; i++) printf("%d,%4s,%c,%d.%02d.%02d,%4.1f\n", stu[i].num, stu[i].name, stu[i].sex, stu[i].birthday.year, stu[i].birthday.month, stu[i].birthday.day, stu[i].score);

  21. 结构体数组与二维表 struct student s[5]; 结构体元素 数组

  22. 3 指向结构体的指针 • 指向结构体的指针 • 定义、使用与其他基本类型指针类似 • 可以使用指向运算符(->)引用指针所指向的结构体的成员 • 指向运算符 -> • 结构体指针->成员名 • 具有最高的优先级,自左向右结合 • 若struct student stu, *p=&stu; 则stu.num、 (*p).num、 p->num等效

  23. 指向结构体数组的指针 • 指向结构体数组的指针 • 与指向其他基本类型数组的指针用法类似 • 注意相关运算符的结合方向和优先级 • 举例 struct student stu[10], *p=stu; ++p->num; /* 同++(p->num);*/ p++->num; /* 同(p++)->num;*/ (++p)->num; (p++)->num;

  24. 结构体指针作函数参数举例 void input(struct student *p) { scanf("%d %s %c %d.%d.%d %f", &p->num, p->name, &p->sex, &p->birthday.year, &p->birthday.month, &p->birthday.day, &p->score); } void main () { struct student stu[20]; int i; for (i=0; i<20; i++) input(stu+i); }

  25. 【例】分配一块存储区域,输入一个学生数据。【例】分配一块存储区域,输入一个学生数据。 ps=(struct stu*)malloc(sizeof(struct stu)); ps->num=102; ps->name="Zhang ping"; ps->sex='M'; ps->score=62.5; printf("Number=%d\nName=%s\n", ps->num,ps->name); printf("Sex=%c\nScore=%f\n", ps->sex,ps->score); free(ps); } main() { struct stu { int num; char *name; char sex; float score; } *ps;

  26. 4 结构体的应用—链表 node struct node { int data; struct node *next; }; struct node *head; ai next data

  27. 链表的操作 • 链表的建立 • 从链尾到链头:新结点插入到链头 • 从链头到链尾:新结点插入到链尾 • 链表的遍历 • 删除结点 • 根据一定的条件,删除一个或多个结点 • 插入结点 • 根据一定的条件,把新结点插入到指定位置

  28. ai-1 ai p 建立链表 (从链尾到链头) ① for(i=0; i<n; i++) ... head ④ head = p; ③ p->next = head; ② p = malloc(sizeof (struct node)); p->data = a[i];

  29. p ai ^ ai-1 ^ q 建立链表 (从链头到链尾) ① for(i=0; i<n; i++) ⑤ p = q; ... ③ q->next = NULL; ④ p->next = q; ② q = malloc(sizeof (struct node)); q->data = a[i];

  30. ai-1 ai ai+1 p 遍历链表 ① while(p) ③ p = p->next; ... ... ② printf("%d", p->data);

  31. ai-1 ai ai+1 p q 删除结点 ① if(p->next满足删除条件) ② q = p->next; ④ free(q); ... ... ③ p->next = q->next;

  32. ai ai+1 x p q 插入结点 ① if(p满足插入条件) ... ... ④ p->next = q; ③ q->next = p->next; ② q = malloc(sizeof (struct node)); q->data = x;

  33. 链表操作中需要注意的几个问题 • 注意考虑几个特殊情况下的操作: • 链表为空表 (head==NULL) • 链表只有一个结点 • 对链表的第一个结点进行操作 • 对链表的最后一个结点进行操作 • 最后一个结点的next指针应为NULL

  34. 例 用指针变量输出结构数组 struct stu { int num; char *name; char sex; float score; }boy[5]={ {101,"Zhou ping",'M',45}, {102,"Zhang ping",'M',62.5}, {103,"Liou fang",'F',92.5}, {104,"Cheng ling",'F',87}, {105,"Wang ming",'M',58}, }; main() { struct stu *ps; printf("No\tName\t\t\tSex\tScore\t\n"); for(ps=boy;ps<boy+5;ps++) printf("%d\t%s\t\t%c\t%f\t\n", ps->num, ps->name, ps->sex, ps->score); }

  35. 例题

  36. 计算一组学生的平均成绩和不及格人数。用结构指针变量作函数参数编程。 struct stu { int num; char *name; char sex; float score;}boy[5]={ {101,"Li ping",'M',45}, {102,"Zhang ping",'M',62.5}, {103,"He fang",'F',92.5}, {104,"Cheng ling",'F',87}, {105,"Wang ming",'M',58}, };

  37. main() { struct stu *ps; void ave(struct stu *ps); ps=boy; ave(ps); } void ave(struct stu *ps) { int c=0,i; float ave,s=0; for(i=0;i<5;i++,ps++) { s+=ps->score; if(ps->score<60) c+=1; } printf("s=%f\n",s); ave=s/5; printf("average=%f\ncount=%d\n",ave,c); }

  38. 建立一个三个结点的链表,存放学生数据。为简单起见, 我们假定学生数据结构中只有学号和年龄两项。可编写一个建立链表的函数create。 #define NULL 0 #define TYPE struct stu #define LEN sizeof (struct stu) struct stu { int num; int age; struct stu *next; }; TYPE *creat(int n) { struct stu *head,*pf,*pb; int i; for(i=0;i<n;i++) { pb=(TYPE*) malloc(LEN); printf("input Number and Age\n"); scanf("%d%d",&pb->num,&pb->age); if(i==0) pf=head=pb; else pf->next=pb; pb->next=NULL; pf=pb; } return(head); }

  39. 共用体 • 概念:各成员共享同一段内存 —共用体 • 定义: union Data //定义类型 { int i; char ch; float f; } a ; //定义变量 union Data b, c; //定义变量

  40. 共用体 • 引用:只能引用共用体变量中的成员,而共用体变量不能整体引用。 union Data a,b; a.i=2; b.i=a.i; printf(“%d”, a); 错误。不能引用a。

  41. 共用体 • 特点: • 成员共享内存:只能放一个成员的值 • 共用体变量初始化只能对一个成员进行(初值表只有一个常量) • 最后一次赋值的成员有效(覆盖了以前所有成员的值) • 共用体变量的地址及其各成员地址都是同一地址 • 同类型共用体变量之间可互相赋值 • 共用体变量可作函数参数 • 可用作结构体成员;共用体成员也可以是数组或结构体。

  42. 共用体的应用 • 用于安排共享一段内存的数据 • 275页 例9.8 struct person{ int num; char name[10]; char sex; char birthday[12]; char addr[16]; union { char single[7]; char nmtel[20]; }mate; }ps[3];

  43. 枚举类型 • 概念: 当变量的值仅限于有限的可列举的范围时,使用枚举类型,可增强程序可读性,并减少变量取值误差。 • 定义形式: enum [枚举名] {枚举元素列表};//枚举元素由程序设计者自定义,但取值自动为0,1,2 … 例 enum Weekday {sun,mon,tue,wed,thu,fri,sat}; enum Weekday workday,weekend;

  44. 枚举类型 • 可自行指定枚举元素常量的值,例如 enum Weekday { sun=7,mon=1,tue,wed,thu,fri,sat,today }; // got 7 1 2 3 4 5 6 7 page277 例 9.9 9.10

  45. 用typedef定义类型别名 • 一般形式 • typedef <变量定义形式中变量名换成类型名> • 举例 • typedef float REAL; • typedef struct { int month; int day; int year; } DATE;

  46. 例 统计候选人选票 struct person { char name[20]; int count; }leader[3]={"Li",0,"Zhang",0, "Wang",0}; int main( ) { int i,j ; char leader_name[20]; for(i=1;i<=10;i++) { scanf("%s",leader_name); for(j=0;j<3;j++) if(strcmp(leader_name,leader[j].name)==0) leader[j].count++; } for(i=0;i<3;i++) printf("%5s:%d\n",leader[i].name,leader[i].count); }

  47. 实验作业 (指针) 257页:16, 17 (结构体)279页:1 2 3 The End 实验 化院12月3日(少年班12月5日) (结构体)279页:4, 5 6

  48. http://www.c-faq.com/struct/align.html • --sizeof结构体 不等于 各成员字节数之和

More Related