Presentation is loading. Please wait.

Presentation is loading. Please wait.

第9章 用户自己建立数据类型 9.1 定义和使用结构体变量 9.2 使用结构体数组 9.3 结构体指针 9.4 用指针处理链表

Similar presentations


Presentation on theme: "第9章 用户自己建立数据类型 9.1 定义和使用结构体变量 9.2 使用结构体数组 9.3 结构体指针 9.4 用指针处理链表"— Presentation transcript:

1 第9章 用户自己建立数据类型 9.1 定义和使用结构体变量 9.2 使用结构体数组 9.3 结构体指针 9.4 用指针处理链表
9.5 共用体类型 9.6 使用枚举类型 9.7 用typedef声明新类型名

2 9.1 定义和使用结构体变量 9.1.1 自己建立结构体类型 9.1.2 定义结构体类型变量 结构体变量的初始化和引用

3 9.1.1 自己建立结构体类型 用户自己建立由不同类型数据组成的组合型的数据结构,它称为结构体
例如,一个学生的学号、姓名、性别、年龄、成绩、家庭地址等项,是属于同一个学生的,因此组成一个组合数据,如student_1的变量,反映它们之间的内在联系

4 9.1.1 自己建立结构体类型 struct Student { int num; char name[20]; char sex;
int age; float score; char addr[30]; }; 由程序设计者指定了一个结构体类型struct Student 它包括num,name,sex,age,score,addr等不同类型的成员

5 9.1.1 自己建立结构体类型 声明一个结构体类型的一般形式为: struct 结构体名 { 成员表列 }; 类型名 成员名;

6 9.1.1 自己建立结构体类型 说明: (1)结构体类型并非只有一种,而是可以设计出许多种结构体类型,例如 struct Teacher
struct Worker struct Date等结构体类型 各自包含不同的成员

7 9.1.1 自己建立结构体类型 说明: (2) 成员可以属于另一个结构体类型。 struct Date
{ int month; int day; int year; };   struct Stu   { int num;char name[20]; char sex;int age; struct Date birthday; char addr[30];   };

8 9.1.1 自己建立结构体类型 说明: (2) 成员可以属于另一个结构体类型。 num name sex age birthday addr
month day year

9 9.1.2 定义结构体类型变量 前面只是建立了一个结构体类型,它相当于一个模型,并没有定义变量,其中并无具体数据,系统对之也不分配存储单元。
相当于设计好了图纸,但并未建成具体的房屋。为了能在程序中使用结构体类型的数据,应当定义结构体类型的变量,并在其中存放具体的数据。

10 9.1.2 定义结构体类型变量 1. 先声明结构体类型,再定义该类型变量 声明结构体类型struct Student,可以用它来定义变量
struct Student student1,student2; 结构体类型名 结构体变量名

11 9.1.2 定义结构体类型变量 1. 先声明结构体类型,再定义该类型变量 声明结构体类型struct Student,可以用它来定义变量
struct Student student1,student2; student1 10001 Zhang Xin M 19 90.5 Shanghai student2 10002 Wang Li F 20 98 Beijing

12 9.1.2 定义结构体类型变量 2.在声明类型的同时定义变量 struct Student { int num;
char name[20]; char sex; int age; float score; char addr[30]; } student1,student2;

13 9.1.2 定义结构体类型变量 3. 不指定类型名而直接定义结构体类型变量 其一般形式为: struct { 成员表列 }变量名表列;
指定了一个无名的结构体类型 。

14 9.1.2 定义结构体类型变量 (1) 结构体类型与结构体变量是不同的概念,不要混同。只能对变量赋值、存取或运算,而不能对一个类型赋值、存取或运算。在编译时,对类型是不分配空间的,只对变量分配空间。

15 9.1.2 定义结构体类型变量 (2) 结构体类型中的成员名可以与程序中的变量名相同,但二者不代表同一对象。
(3) 对结构体变量中的成员(即“域”),可以单独使用,它的作用与地位相当于普通变量。

16 9.1.3 结构体变量的初始化和引用 例9.1 把一个学生的信息(包括学号、姓名、性别、住址)放在一个结构体变量中,然后输出这个学生的信息。
结构体变量的初始化和引用 例9.1 把一个学生的信息(包括学号、姓名、性别、住址)放在一个结构体变量中,然后输出这个学生的信息。 解题思路: 自己建立一个结构体类型,包括有关学生信息的各成员 用它定义结构体变量,同时赋以初值 输出该结构体变量的各成员

17 #include <stdio.h> int main() {struct Student { long int num; char name[20]; char sex; char addr[20]; }a={10101,“Li Lin”,‘M’, “123 Beijing Road”}; printf("NO.:%ld\nname:%s\n sex:%c\naddress:%s\n", a.num,a.name,a.sex,a.addr); return 0; }

18 #include <stdio.h> int main() {struct Student { long int num; char name[20]; char sex; char addr[20]; }a={10101,“Li Lin”,‘M’, “123 Beijing Road”}; printf("NO.:%ld\nname:%s\n sex:%c\naddress:%s\n", a.num,a.name,a.sex,a.addr); return 0; } { }

19 #include <stdio.h> int main() {struct Student { long int num; char name[20]; char sex; char addr[20]; }a={10101,“Li Lin”,‘M’, “123 Beijing Road”}; …… } a.num=10010; 对 printf(“%s\n”,a); 不对

20 #include <stdio.h> int main() {struct Student { long int num; char name[20]; char sex; char addr[20]; }a={10101,“Li Lin”,‘M’, “123 Beijing Road”}; …… } struct Student b; b=a; 对 b.num++; 对

21 #include <stdio.h> int main() {struct Student { long int num; char name[20]; char sex; char addr[20]; }a={10101,“Li Lin”,‘M’, “123 Beijing Road”}; …… } scanf(″%ld″,&a.num); 对 printf(″%o″,&a); 对 scanf(“%ld,%s,%c,%s\n”,&a); 错

22 #include <stdio.h> int main() { struct Date { int month; int day; int year; }; struct Stu { int num;char name[20]; char sex;int age; struct Date birthday; char addr[30]; }a,b; a.birthday.month=12; 对 a.age=10; b.age=9; 对 sum=a.age+b.age; 对

23 例9.2 输入两个学生的学号、姓名和成绩,输出成绩较高学生的学号、姓名和成绩 解题思路:
(1)定义两个结构相同的结构体变量student1和student2; (2)分别输入两个学生的学号、姓名和成绩; (3)比较两个学生的成绩,如果学生1的成绩高于学生2,就输出学生1的全部信息,如果学生2的成绩高于学生1,就输出学生2的全部信息。如果二者相等,输出2个学生的全部信息

24 #include <stdio.h> int main() { struct Student { int num; char name[20]; float score; }student1,student2; scanf("%d%s%f",&student1.num, student1.name, &student1.score); scanf(“%d%s%f”,&student2.num, student2.name, &student2.score); 不能加&

25 printf("The higher score is:\n"); if (student1. score>student2
printf("The higher score is:\n"); if (student1.score>student2.score) printf("%d %s %6.2f\n",student1.num, student1.name, student1.score); else if (student1.score<student2.score) printf("%d %s %6.2f\n",student2.num, student2.name, student2.score); else {printf("%d %s %6.2f\n",student1.num, } return 0;

26 9.2 使用结构体数组 9.2.1定义结构体数组 9.2.2 结构体数组的应用举例

27 9.2.1定义结构体数组 例9.3 有3个候选人,每个选民只能投票选一人,要求编一个统计选票的程序,先后输入被选人的名字,最后输出各人得票结果。

28 9.2.1定义结构体数组 解题思路: 设一个结构体数组,数组中包含3个元素 每个元素中的信息应包括候选人的姓名(字符型)和得票数(整型)
输入被选人的姓名,然后与数组元素中的“姓名”成员比较,如果相同,就给这个元素中的“得票数”成员的值加1 输出所有元素的信息

29 #include <string. h> #include <stdio
#include <string.h> #include <stdio.h> struct Person { char name[20]; int count; }leader[3]={“Li”,0,“Zhang”,0,“Sun”,0}; 全局的结构体数组 name count leader[0] Li Zhang Sun

30 leader[j].count=leader[j].count+1;
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); return 0; leader[j].count=leader[j].count+1;

31 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); return 0;

32 说明: (1)定义结构体数组一般形式是 ① struct 结构体名 {成员表列} 数组名[数组长度];
② 先声明一个结构体类型,然后再用此类型定义结构体数组: 结构体类型 数组名[数组长度]; 如: struct Person leader[3];

33 (2)对结构体数组初始化的形式是在定义数组的后面加上:
说明: (2)对结构体数组初始化的形式是在定义数组的后面加上: ={初值表列}; 如: struct Person leader[3]= {"Li",0,"Zhang",0,"Fun",0};

34 9.2.2 结构体数组的应用举例 例9.4 有n个学生的信息(包括学号、姓名、成绩),要求按照成绩的高低顺序输出各学生的信息。

35 #include <stdio.h> struct Student { int num; char name[20]; float score; }; int main() { struct Student stu[5]={{10101,"Zhang",78 }, {10103,"Wang",98.5}, {10106,"Li", 86 }, {10108,“Ling”, 73.5}, {10110,“Fun”, 100 } }; struct Student temp; const int n = 5 ; int i,j,k; 常变量 若人数变为30 30

36 #include <stdio.h> struct Student { int num; char name[20]; float score; }; int main() { struct Student stu[5]={{10101,"Zhang",78 }, {10103,"Wang",98.5}, {10106,"Li", 86 }, {10108,“Ling”, 73.5}, {10110,“Fun”, 100 } }; struct Student temp; const int n = 5 ; int i,j,k; #define N 5 注意temp的类型

37 printf("The order is:\n"); for(i=0;i<n-1;i++) { k=i; for(j=i+1;j<n;j++) if(stu[j].score>stu[k].score) k=j; temp=stu[k]; stu[k]=stu[i]; stu[i]=temp; } for(i=0;i<n;i++) printf("%6d %8s %6.2f\n", stu[i].num,stu[i].name,stu[i].score); printf("\n"); return 0; 写法上与普通变量一致

38 9.3 结构体指针 9.3.1 指向结构体变量的指针 9.3.2 指向结构体数组的指针 9.3.3 用结构体变量和结构体变量的指针作函数参数

39 9.3.1 指向结构体变量的指针 指向结构体对象的指针变量既可以指向结构体变量,也可以用来指向结构体数组中的元素。
指针变量的基类型必须与结构体变量的类型相同。例如: struct Student *pt;

40 9.3.1 指向结构体变量的指针 例9.5 通过指向结构体变量的指针变量输出结构体变量中成员的信息。
例9.5 通过指向结构体变量的指针变量输出结构体变量中成员的信息。 解题思路:在已有的基础上,本题要解决两个问题: 怎样对结构体变量成员赋值; 怎样通过指向结构体变量的指针访问结构体变量中成员。

41 #include <stdio. h> #include <string
#include <stdio.h> #include <string.h> int main() { struct Student { long num; char name[20]; char sex; float score; }; ……

42 stu_1 struct Student stu_1; struct Student * p; p=&stu_1; stu_1.num=10101; strcpy(stu_1.name,“Li Lin”); stu_1.sex='M‘; stu_1.score=89.5; printf("No.:%ld\n”,stu_1.num); printf("name:%s\n",stu_1.name); printf("sex:%c\n”,stu_1.sex); printf(”score:%5.1f\n”,stu_1.score); return 0; } p 10101 Li Lin M 89.5

43 stu_1 struct Student stu_1; struct Student * p; p=&stu_1; stu_1.num=10101; strcpy(stu_1.name,“Li Lin”); stu_1.sex='M‘; stu_1.score=89.5; printf("No.:%ld\n”,stu_1.num); printf("name:%s\n",stu_1.name); printf("sex:%c\n”,stu_1.sex); printf(”score:%5.1f\n”,stu_1.score); return 0; } p 10101 Li Lin M 89.5 (*p).num (*p).name (*p).sex (*p).score

44 说明: 为了使用方便和直观,C语言允许把(*p).num用p->num来代替 (*p).name等价于p->name
如果p指向一个结构体变量stu,以下等价: ① stu.成员名(如stu.num) ② (*p).成员名(如(*p).num) p->成员名(如p->num)

45 9.3.2 指向结构体数组的指针 例9.6 有3个学生的信息,放在结构体数组中,要求输出全部学生的信息。

46 解题思路:用指向结构体变量的指针处理 (1)声明struct Student,并定义结构体数组、初始化
(2)定义指向struct Student类型指针p (3)使p指向数组首元素,输出元素中各信息 (4)使p指向下一个元素,输出元素中各信息 (5)再使p指向结构体数组的下一个元素,输出它指向的元素中的有关信息

47 #include <stdio.h> struct Student { int num; char name[20]; char sex; int age; }; struct Student stu[3]={ {10101,"Li Lin",'M',18}, {10102,"Zhang Fun",'M',19}, {10104,"Wang Min",'F',20} };

48 int main() { struct Student. p; printf(" No
int main() { struct Student *p; printf(" No. Name sex age\n"); for(p=stu;p<stu+3;p++) printf(“%5d %-20s %2c %4d\n”, p->num, p->name, p->sex, p->age); return 0; } stu[0] 10101 Li Lin M 18 10102 Zhang Fang 19 10104 Wang Min F 20 stu[1] stu[2]

49 int main() { struct Student. p; printf(" No
int main() { struct Student *p; printf(" No. Name sex age\n"); for(p=stu;p<stu+3;p++) printf(“%5d %-20s %2c %4d\n”, p->num, p->name, p->sex, p->age); return 0; } p stu[0] 10101 Li Lin M 18 10102 Zhang Fang 19 10104 Wang Min F 20 stu[1] stu[2]

50 int main() { struct Student. p; printf(" No
int main() { struct Student *p; printf(" No. Name sex age\n"); for(p=stu;p<stu+3;p++) printf(“%5d %-20s %2c %4d\n”, p->num, p->name, p->sex, p->age); return 0; } stu[0] p 10101 Li Lin M 18 10102 Zhang Fang 19 10104 Wang Min F 20 stu[1] stu[2]

51 int main() { struct Student. p; printf(" No
int main() { struct Student *p; printf(" No. Name sex age\n"); for(p=stu;p<stu+3;p++) printf(“%5d %-20s %2c %4d\n”, p->num, p->name, p->sex, p->age); return 0; } stu[0] 10101 Li Lin M 18 10102 Zhang Fang 19 10104 Wang Min F 20 stu[1] p stu[2]

52 9.3.3 用结构体变量和结构体变量的指针作函数参数
用结构体变量和结构体变量的指针作函数参数 将一个结构体变量的值传递给另一个函数,有3个方法。

53 (1) 用结构体变量的成员作参数。 例如,用stu[1].num或stu[2].name作函数实参,将实参值传给形参。
用法和用普通变量作实参是一样的,属于“值传递”方式。 应当注意实参与形参的类型保持一致。

54 (2) 用结构体变量作实参。 用结构体变量作实参时,将结构体变量所占的内存单元的内容全部按顺序传递给形参,形参也必须是同类型的结构体变量
在函数调用期间形参也要占用内存单元。这种传递方式在空间和时间上开销较大 在被调用函数期间改变形参(也是结构体变量)的值,不能返回主调函数 一般较少用这种方法

55 (3)用指向结构体变量(或数组元素)的指针作实参,将结构体变量(或数组元素)的地址传给形参。

56 例9.7 有n个结构体变量,内含学生学号、姓名和3门课程的成绩。要求输出平均成绩最高的学生的信息(包括学号、姓名、3门课程成绩和平均成绩)。

57 解题思路:将n个学生的数据表示为结构体数组。按照功能函数化的思想,分别用3个函数来实现不同的功能:
用input函数输入数据和求各学生平均成绩 用max函数找平均成绩最高的学生 用print函数输出成绩最高学生的信息 在主函数中先后调用这3个函数,用指向结构体变量的指针作实参。最后得到结果。 本程序假设n=3

58 #include <stdio.h> #define N 3 struct Student { int num; char name[20]; float score[3]; float aver; }; 4个成员 输入前3个成员值 计算最后成员值

59 int main() { void input(struct Student stu[]); struct Student max(struct Student stu[]); void print(struct Student stu); struct Student stu[N],*p=stu; input(p); print(max(p)); return 0; }

60 void input(struct Student stu[]) { int i; printf("请输入各学生的信息: 学号、姓名、三门课成绩:\n"); for(i=0;i<N;i++) {scanf("%d %s %f %f %f", &stu[i].num,stu[i].name, &stu[i].score[0],&stu[i].score[1], &stu[i].score[2]); stu[i].aver=(stu[i].score[0]+ stu[i].score[1]+stu[i].score[2])/3.0; } i=0 输入第1个成员值 输入第2个成员值 输入第3个成员值 计算第4个成员值 stu[0] stu 10101 Li 88.33 stu[1] stu[2]

61 void input(struct Student stu[]) { int i; printf("请输入各学生的信息: 学号、姓名、三门课成绩:\n"); for(i=0;i<N;i++) {scanf("%d %s %f %f %f", &stu[i].num,stu[i].name, &stu[i].score[0],&stu[i].score[1], &stu[i].score[2]); stu[i].aver=(stu[i].score[0]+ stu[i].score[1]+stu[i].score[2])/3.0; } i=1 输入第1个成员值 输入第2个成员值 输入第3个成员值 计算第4个成员值 stu[0] stu 10101 Li 88.33 10103 Wang 84.83 stu[1] stu[2]

62 void input(struct Student stu[]) { int i; printf("请输入各学生的信息: 学号、姓名、三门课成绩:\n"); for(i=0;i<N;i++) {scanf("%d %s %f %f %f", &stu[i].num,stu[i].name, &stu[i].score[0],&stu[i].score[1], &stu[i].score[2]); stu[i].aver=(stu[i].score[0]+ stu[i].score[1]+stu[i].score[2])/3.0; } i=2 输入第1个成员值 输入第2个成员值 输入第3个成员值 计算第4个成员值 stu[0] stu 10101 Li 88.33 10103 Wang 84.83 stu[1] 10106 Sun 84.5 stu[2]

63 struct Student max(struct Student stu[]) {int i,m=0; for(i=0;i<N;i++) if (stu[i].aver>stu[m].aver) m=i; return stu[m]; } 返回 最大 stu[0] stu 10101 Li 88.33 10103 Wang 84.83 stu[1] 10106 Sun 84.5 stu[2]

64 score num name aver stud
void print(struct Student stud) { printf("\n成绩最高的学生是:\n"); printf("学号:%d\n姓名:%s\n 三门课成绩:%5.1f,%5.1f,%5.1f\n 平均成绩:%6.2f\n”, stud.num, stud.name,stud.score[0], stud.score[1],stud.score[2],stud.aver); } score num name aver stud stu[0] 10101 Li 88.33 10103 Wang 84.83 stu[1] 10106 Sun 84.5 stu[2]

65 以上3个函数的调用,情况各不相同: 调用input函数时,实参是指针变量,形参是结构体数组,传递的是结构体元素的地址,函数无返回值。
调用max函数时,实参是指针变量,形参是结构体数组,传递的是结构体元素的地址,函数的返回值是结构体类型数据。 调用print函数时,实参是结构体变量,形参是结构体变量,传递的是结构体变量中各成员的值,函数无返回值。

66 9.4 用指针处理链表 9.4.1 什么是链表 9.4.2 建立简单的静态链表 9.4.3 建立动态链表 9.4.4 输出链表

67 9.4.1 什么是链表 链表是一种常见的重要的数据结构 它是动态地进行存储分配的一种结构 各结点地址不连续 head 1249 1356
1475 1021 A B C D 1249 1356 1475 1021 \0 表尾 头指针 各结点含有两个部分

68 9.4.1 什么是链表 链表是一种常见的重要的数据结构 它是动态地进行存储分配的一种结构 链表必须利用指针变量才能实现

69 struct Student { int num; float score; struct Student *next; }a,b,c;
10101 89.5 10103 90 10107 85 score next a.next=&b; b.next=&c;

70 9.4.2 建立简单的静态链表 例9.8 建立一个如图所示的简单链表,它由3个学生数据的结点组成,要求输出各结点中的数据。 a结点 b结点
建立简单的静态链表 例9.8 建立一个如图所示的简单链表,它由3个学生数据的结点组成,要求输出各结点中的数据。 a结点 b结点 c结点 num 10101 89.5 10103 90 10107 85 score next

71 9.4.2 建立简单的静态链表 解题思路: head=&a; a.next=&b; b.next=&c; c.next=NULL; head
建立简单的静态链表 解题思路: head=&a; a.next=&b; b.next=&c; c.next=NULL; head a结点 b结点 c结点 num 10101 89.5 10103 90 10107 85 score next NULL

72 #include <stdio.h> struct Student { int num; float score; struct Student *next; };

73 int main() { struct Student a,b,c,*head,*p; a. num=10101; a.score=89.5; b. num=10103; b.score=90; c. num=10107; c.score=85; head=&a; a.next=&b; b.next=&c; c.next=NULL; p=head; do {printf(“%ld%5.1f\n”,p->num,p->score); p=p->next; }while(p!=NULL); return 0; }

74 p=head; do {printf(“%ld%5
p=head; do {printf(“%ld%5.1f\n”,p->num,p->score); p=p->next; }while(p!=NULL); return 0; } head a结点 b结点 c结点 10101 89.5 10103 90 10107 85 num p score next NULL 相当于p=&b;

75 p=head; do {printf(“%ld%5
p=head; do {printf(“%ld%5.1f\n”,p->num,p->score); p=p->next; }while(p!=NULL); return 0; } head a结点 p b结点 c结点 10101 89.5 10103 90 10107 85 num score next NULL 相当于p=&b;

76 p=head; do {printf(“%ld%5
p=head; do {printf(“%ld%5.1f\n”,p->num,p->score); p=p->next; }while(p!=NULL); return 0; } head a结点 p b结点 c结点 10101 89.5 10103 90 10107 85 num score next NULL 相当于p=&c;

77 p=head; do {printf(“%ld%5
p=head; do {printf(“%ld%5.1f\n”,p->num,p->score); p=p->next; }while(p!=NULL); return 0; } head a结点 b结点 p c结点 10101 89.5 10103 90 10107 85 num score next NULL 相当于p=&c;

78 p=head; do {printf(“%ld%5
p=head; do {printf(“%ld%5.1f\n”,p->num,p->score); p=p->next; }while(p!=NULL); return 0; } 静态链表 head a结点 b结点 p c结点 10101 89.5 10103 90 10107 85 num score next NULL 相当于p=NULL;

79 建立动态链表 所谓建立动态链表是指在程序执行过程中从无到有地建立起一个链表,即一个一个地开辟结点和输入各结点数据,并建立起前后相链的关系。

80 建立动态链表 例9.9 写一函数建立一个有3名学生数据的单向动态链表。

81 解题思路: 定义3个指针变量:head,p1和p2,它们都是用来指向struct Student类型数据
struct Student *head,*p1,*p2;

82 解题思路: 用malloc函数开辟第一个结点,并使p1和p2指向它 p1=p2=(struct Student*)malloc(LEN);

83 解题思路: 读入一个学生的数据给p1所指的第一个结点 scanf("%ld,%f",&p1->num,&p1->score);
10101 89.5 p2

84 解题思路: 读入一个学生的数据给p1所指的第一个结点 使head也指向新开辟的结点
scanf("%ld,%f",&p1->num,&p1->score); head p1 10101 89.5 p2

85 解题思路: 再开辟另一个结点并使p1指向它,接着输入该结点的数据 head p1 10101 89.5 p2

86 解题思路: 再开辟另一个结点并使p1指向它,接着输入该结点的数据 p1=(struct Student*)malloc(LEN);
scanf("%ld,%f",&p1->num,&p1->score); head p1 10101 89.5 10103 90 p2

87 解题思路: 使第一个结点的next成员指向第二个结点,即连接第一个结点与第二个结点 使p2指向刚才建立的结点 p2->next=p1;
head p1 10101 89.5 10103 90 p2

88 解题思路: 使第一个结点的next成员指向第二个结点,即连接第一个结点与第二个结点 使p2指向刚才建立的结点 p2->next=p1;
head p2 p1 10101 89.5 10103 90

89 解题思路: 再开辟另一个结点并使p1指向它,接着输入该结点的数据 head p2 p1 10101 89.5 10103 90

90 解题思路: 再开辟另一个结点并使p1指向它,接着输入该结点的数据 p1=(struct Student*)malloc(LEN);
scanf("%ld,%f",&p1->num,&p1->score); head p2 p1 10101 89.5 10103 90 10107 85

91 解题思路: 使第二个结点的next成员指向第三个结点,即连接第二个结点与第三个结点 使p2指向刚才建立的结点 p2->next=p1;
head p2 p1 10101 89.5 10103 90 10107 85

92 解题思路: 使第二个结点的next成员指向第三个结点,即连接第二个结点与第三个结点 使p2指向刚才建立的结点 p2->next=p1;
head p2 p1 10101 89.5 10103 90 10107 85

93 解题思路: 再开辟另一个结点并使p1指向它,接着输入该结点的数据 head p2 p1 10101 89.5 10103 90 10107
85

94 解题思路: 再开辟另一个结点并使p1指向它,接着输入该结点的数据 p1=(struct Student*)malloc(LEN);
scanf("%ld,%f",&p1->num,&p1->score); head p2 p1 10101 89.5 10103 90 10107 85

95 解题思路: 输入的学号为0,表示建立链表的过程完成,该结点不应连接到链表中 p2->next=NULL; head p2 p1
10101 89.5 10103 90 10107 85 NULL

96 struct Student类型数据的长度
#include <stdio.h> #include <stdlib.h> #define LEN sizeof(struct Student) struct Student { long num; float score; struct Student *next; }; int n;

97 struct Student. creat(void) { struct Student. head,. p1,
struct Student *creat(void) { struct Student *head,*p1,*p2; n=0; p1=p2=( struct Student*) malloc(LEN); scanf(“%ld,%f”,&p1->num,&p1->score); head=NULL; while(p1->num!=0) {n=n+1; if(n==1) head=p1; else p2->next=p1; p2=p1; p1=(struct Student*)malloc(LEN); } p2->next=NULL; return(head); p1总是开辟新结点 p2总是指向最后结点 用p2和p1连接两个结点

98 int main() { struct Student
int main() { struct Student *pt; pt=creat(); printf(“\nnum:%ld\nscore:%5.1f\n”, pt->num,pt->score); return 0; }

99 9.4.4 输出链表 例9.10 编写一个输出链表的函数print。 1001 67.5 1003 87 1005 99 p NULL

100 解题思路: 输出p所指的结点 使p后移一个结点 printf("%ld %5.1f\n",p->num,p->score);
1001 67.5 1003 87 1005 99 p NULL

101 解题思路: 输出p所指的结点 使p后移一个结点 printf("%ld %5.1f\n",p->num,p->score);
p=p->next; p 1001 67.5 1003 87 1005 99 NULL

102 解题思路: 输出p所指的新结点 使p后移一个结点 printf("%ld %5.1f\n",p->num,p->score);
1001 67.5 1003 87 1005 99 NULL

103 解题思路: 输出p所指的新结点 使p后移一个结点 printf("%ld %5.1f\n",p->num,p->score);
p=p->next; p 1001 67.5 1003 87 1005 99 NULL

104 解题思路: 输出p所指的新结点 使p后移一个结点 printf("%ld %5.1f\n",p->num,p->score);
p=p->next; 相当于p=NULL; p 1001 67.5 1003 87 1005 99 NULL

105 void print(struct Student
void print(struct Student *p) { printf("\nThese %d records are:\n",n); if(p!=NULL) do { printf("%ld %5.1f\n", p->num,p->score); p=p->next; }while(p!=NULL); }

106 9.5 共用体类型 9.5.1 什么是共用体类型 9.5.2 引用共用体变量的方式 9.5.3 共用体类型数据的特点

107 9.5.1 什么是共用体类型 有时想用同一段内存单元存放不同类型的变量。 使几个不同的变量共享同一段内存的结构,称为 “共用体”类型的结构。
1000 1001 1002 1003 字符ch 实 型 变 量 f 整 型 变 量 i

108 定义共用体类型变量的一般形式为: union 共用体名 { 成员表列 }变量表列;  例如: union Data
{ int i; char ch; float f;  }a,b,c; union Data { int i; char ch; float f;  }; union Data a,b,c;

109 “共用体”与“结构体”的定义形式相似,但它们的含义是不同的。
结构体变量所占内存长度是各成员占的内存长度之和,每个成员分别占有其自己的内存单元。而共用体变量所占的内存长度等于最长的成员的长度。

110 9.5.2 引用共用体变量的方式 只有先定义了共用体变量才能引用它,但应注意,不能引用共用体变量,而只能引用共用体变量中的成员。
例如,前面定义了a,b,c为共用体变量,下面的引用方式是正确的: a.i a.ch a.f

111 9.5.3 共用体类型数据的特点 在使用共用体类型数据时要注意以下一些特点:
共用体类型数据的特点 在使用共用体类型数据时要注意以下一些特点: (1) 同一个内存段可以用来存放几种不同类型的成员,但在每一瞬时只能存放其中一个成员,而不是同时存放几个。

112 共用体类型数据的特点 在使用共用体类型数据时要注意以下一些特点: (2)可以对共用体变量初始化,但初始化表中只能有一个常量。

113 9.5.3 共用体类型数据的特点 在使用共用体类型数据时要注意以下一些特点:
共用体类型数据的特点 在使用共用体类型数据时要注意以下一些特点: (3)共用体变量中起作用的成员是最后一次被赋值的成员,在对共用体变量中的一个成员赋值后,原有变量存储单元中的值就取代。

114 9.5.3 共用体类型数据的特点 在使用共用体类型数据时要注意以下一些特点: (4) 共用体变量的地址和它的各成员的地址都是同一地址。
共用体类型数据的特点 在使用共用体类型数据时要注意以下一些特点: (4) 共用体变量的地址和它的各成员的地址都是同一地址。 (5) 不能对共用体变量名赋值,也不能企图引用变量名来得到一个值。

115 9.5.3 共用体类型数据的特点 在使用共用体类型数据时要注意以下一些特点:
共用体类型数据的特点 在使用共用体类型数据时要注意以下一些特点: (6) 以前的C规定不能把共用体变量作为函数参数,但可以使用指向共用体变量的指针作函数参数。C99允许用共用体变量作为函数参数。

116 9.5.3 共用体类型数据的特点 在使用共用体类型数据时要注意以下一些特点:
共用体类型数据的特点 在使用共用体类型数据时要注意以下一些特点: (7) 共用体类型可以出现在结构体类型定义中,也可以定义共用体数组。反之,结构体也可以出现在共用体类型定义中,数组也可以作为共用体的成员。

117 共用体类型数据的特点 例9.11 有若干个人员的数据,其中有学生和教师。学生的数据中包括:姓名、号码、性别、职业、班级。教师的数据包括:姓名、号码、性别、职业、职务。要求用同一个表格来处理。

118 解题思路: 学生和教师的数据项目多数是相同的,但有一项不同。现要求把它们放在同一表格中

119 解题思路: 如果job项为s,则第5项为class。即Li是501班的。如果job项是t,则第5项为position。Wang是prof(教授)。

120 解题思路: 对第5项可以用共用体来处理(将class和position放在同一段存储单元中)

121 #include <stdio.h> struct { int num; char name[10]; char sex; char job; union { int clas; char position[10]; }category; }person[2]; 共用体变量 外部的结构体数组

122 #include <stdio.h> union Categ { int clas; char position[10]; }; struct { int num; char name[10]; char sex; char job; union Categ category }person[2]; 声明共用体类型 定义共用体类型变量

123 int main() {int i; for(i=0;i<2;i++) {scanf("%d %s %c %c“,&person[i]
int main() {int i; for(i=0;i<2;i++) {scanf("%d %s %c %c“,&person[i].num, &person[i].name, &person[i].sex,&person[i].job); if(person[i].job == 's') scanf("%d“,&person[i].category.clas); else if(person[i].job == 't‘) scanf(“%s”,person[i].category.position); else printf(“Input error!”); } printf("\n");

124 for(i=0;i<2;i++) {if (person[i]
for(i=0;i<2;i++) {if (person[i].job == ‘s’) printf("%-6d%-10s%-4c%-4c% -10d\n",person[i].num,person[i]. name,person[i].sex,person[i].job, person[i].category.clas); else -10s\n",person[i].num,person[i]. name,person[i].sex, person[i].job, person[i].category.position); } return 0;

125 9.6 使用枚举类型 如果一个变量只有几种可能的值,则可以定义为枚举类型
所谓“枚举”就是指把可能的值一一列举出来,变量的值只限于列举出来的值的范围内

126 9.6 使用枚举类型 声明枚举类型用enum开头。 例如: 枚举元素 enum Weekday{sun,mon,tue,
wed,thu,fri,sat}; 声明了一个枚举类型enum Weekday 然后可以用此类型来定义变量 enum Weekday workday,weekend; 枚举元素 枚举变量

127 9.6 使用枚举类型 workday=mon; 正确 weekend=sun; 正确 weekday=monday; 不正确

128 说明: (1) C编译对枚举类型的枚举元素按常量处理,故称枚举常量。不要因为它们是标识符(有名字)而把它们看作变量,不能对它们赋值。例如: sun=0; mon=1; 错误

129 (2) 每一个枚举元素都代表一个整数,C语言编译按定义时的顺序默认它们的值为0,1,2,3,4,5…
说明: (2) 每一个枚举元素都代表一个整数,C语言编译按定义时的顺序默认它们的值为0,1,2,3,4,5… 在上面定义中,sun的值为0,mon的值为1,…sat的值为6 如果有赋值语句: workday=mon; 相当于workday=1;

130 (2) 每一个枚举元素都代表一个整数,C语言编译按定义时的顺序默认它们的值为0,1,2,3,4,5…
说明: (2) 每一个枚举元素都代表一个整数,C语言编译按定义时的顺序默认它们的值为0,1,2,3,4,5… 也可以人为地指定枚举元素的数值,例如: enum Weekday{sun=7,mon=1,tue, wed,thu,fri,sat}workday,week_end; 指定枚举常量sun的值为7,mon为1,以后顺序加1,sat为6。

131 说明: (3) 枚举元素可以用来作判断比较。例如: if(workday==mon)… if(workday>sun)…
枚举元素的比较规则是按其在初始化时指定的整数来进行比较的。 如果定义时未人为指定,则按上面的默认规则处理,即第一个枚举元素的值为0,故mon>sun,sat>fri

132 例9.12 口袋中有红、黄、蓝、白、黑5种颜色的球若干个。每次从口袋中先后取出3个球,问得到3种不同颜色的球的可能取法,输出每种排列的情况。

133 解题思路:

134 解题思路:

135 #include <stdio.h> int main() {enum Color{red,yellow,blue,white,black}; enum Color i,j,k,pri; int n,loop; n=0; for (i=red;i<=black;i++) for (j=red;j<=black;j++) if (i!=j) { for (k=red;k<=black;k++) if ((k!=i) && (k!=j)) { n=n+1; printf(“%-4d”,n);

136 for (loop=1;loop<=3;loop++) {switch (loop) { case 1: pri=i;break; case 2: pri=j;break; case 3: pri=k;break; default:break; }

137 switch (pri) {case red: printf(“%-10s”,“red”); break; case yellow:printf("%-10s","yellow"); case blue: printf(“%-10s”,“blue”); case white: printf(“%-10s”,“white”); case black: printf("%-10s","black"); }

138 } printf("\n"); printf("\ntotal:%5d\n",n); return 0;

139 9.7 用typedef声明新类型名 1.简单地用一个新的类型名代替原有的类型名 typedef int Integer;
typedef float Real; int i,j; float a,b; 与 Integer i,j; Real a,b; 等价

140 9.7 用typedef声明新类型名 2.命名一个简单的类型名代替复杂的类型表示方法 (1)命名一个新的类型名代表结构体类型:
typedef struct { int month; int day; int year; }Date; Date birthday; Date *p;

141 9.7 用typedef声明新类型名 2.命名一个简单的类型名代替复杂的类型表示方法 (2) 命名一个新的类型名代表数组类型
typedef int Num[100]; Num a;

142 9.7 用typedef声明新类型名 2.命名一个简单的类型名代替复杂的类型表示方法 (3)命名一个新的类型名代表一个指针类型
typedef char *String;  String p,s[10];

143 9.7 用typedef声明新类型名 2.命名一个简单的类型名代替复杂的类型表示方法 (4)命名一个新的类型名代表指向函数的指针类型
typedef int (*Pointer)();  Pointer p1,p2;

144 9.7 用typedef声明新类型名 归纳起来,声明一个新的类型名的方法是 ① 先按定义变量的方法写出定义体(int i;)
② 将变量名换成新类型名(将i换成Count) ③ 在最前面加typedef (typedef int Count) ④ 用新类型名去定义变量

145 9.7 用typedef声明新类型名 以定义上述的数组类型为例来说明: ① 先按定义数组变量形式书写:int a[100];
② 将变量名a换成自己命名的类型名:int Num[100]; ③ 在前面加上typedef,得到typedef int Num[100]; 用来定义变量:Num a; 相当于定义了:int a[100];

146 9.7 用typedef声明新类型名 对字符指针类型,也是: char *p; char *String;
typedef char *String; String p;

147 9.7 用typedef声明新类型名 说明: (1)以上的方法实际上是为特定的类型指定了一个同义字(synonyms)。例如
①typedef int Num[100]; Num a; Num是int [100]的同义词 ②typedef int (*Pointer)(); Pointer p1; Pointer是int (*)()的同义词

148 9.7 用typedef声明新类型名 说明: (2) 用typedef只是对已经存在的类型指定一个新的类型名,而没有创造新的类型。
(3)用tyoedef声明数组类型、指针类型,结构体类型、共用体类型、枚举类型等,使得编程更加方便。 (4)typedef与#define表面上有相似之处

149 9.7 用typedef声明新类型名 说明: (5) 当不同源文件中用到同一类型数据时,常用typedef声明一些数据类型。可以把所有的typedef名称声明单独放在一个头文件中,然后在需要用到它们的文件中用#include指令把它们包含到文件中。这样编程者就不需要在各文件中自己定义typefef名称了。

150 9.7 用typedef声明新类型名 说明: (6) 使用typedef名称有利于程序的通用与移植。有时程序会依赖于硬件特性,用typedef类型就便于移植。


Download ppt "第9章 用户自己建立数据类型 9.1 定义和使用结构体变量 9.2 使用结构体数组 9.3 结构体指针 9.4 用指针处理链表"

Similar presentations


Ads by Google