第 9 章 结构体及其应用

71
9 9 第第 第第第第 第第 第第第第 9.1 9.1 第第第第第 第第第第第 9.2 9.2 第第 第第第第第 第第 第第第第第 9.3 9.3 第第 第第 9.4 9.4 第第 第第第第 第第 第第第第 9.5 9.5 第第第第 第第第第 9.6 9.6 第第 第第 第第 第第 9 9

description

第 9 章 结构体及其应用. 9.1 一个程序实例 9.2 结构体类型的使用 9.3 链表 9.4 结构体应用实例 9.5 本章小结 9.6 实训 习题 9. 9.1 一个程序实例. - PowerPoint PPT Presentation

Transcript of 第 9 章 结构体及其应用

Page 1: 第  9  章  结构体及其应用

第 第 9 9 章 结构体及其应用章 结构体及其应用 9.1 9.1 一个程序实例一个程序实例 9.2 9.2 结构体类型的使用结构体类型的使用 9.3 9.3 链表链表 9.4 9.4 结构体应用实例结构体应用实例 9.5 9.5 本章小结本章小结 9.6 9.6 实训实训 习题 习题 99

Page 2: 第  9  章  结构体及其应用

9.1 9.1 一个程序实例一个程序实例 通过前面的学习,我们了解到相同类型的一组数据可用数组存放。通过前面的学习,我们了解到相同类型的一组数据可用数组存放。而现实生活中经常需要处理一些数据类型不同,而又相互关联的一组而现实生活中经常需要处理一些数据类型不同,而又相互关联的一组数据,例如,一个学生的个人信息(有学号、姓名、性别、年龄、住数据,例如,一个学生的个人信息(有学号、姓名、性别、年龄、住址、成绩等数据项) ,一本图书的信息(有分类编号、书名、作者、址、成绩等数据项) ,一本图书的信息(有分类编号、书名、作者、出版社、出版日期、价格、库存量等数据项) ,在描述这些数据类型出版社、出版日期、价格、库存量等数据项) ,在描述这些数据类型不同、但是同一个学生或同一本书的信息时,简单变量或数组都显得不同、但是同一个学生或同一本书的信息时,简单变量或数组都显得力不从心。那么如何描述这些类型不同的相关数据呢力不从心。那么如何描述这些类型不同的相关数据呢 ? ? CC 语言提供了将不同类型数据组合到一起的方法,这就是结构体类语言提供了将不同类型数据组合到一起的方法,这就是结构体类型(型( structurestructure ) 。 ) 。 【例 − 】一个学生的信息包括学号、姓名、平时成绩、期末成绩和【例 − 】一个学生的信息包括学号、姓名、平时成绩、期末成绩和总评成绩,其中总评成绩的计算公式为: 总评成绩,其中总评成绩的计算公式为: 总评成绩总评成绩 == 平时成绩平时成绩 ×30%+×30%+ 期末成绩期末成绩 ×70% ×70% 根据给定的平时成绩和期末成绩计算该生总评成绩,并输出学生的根据给定的平时成绩和期末成绩计算该生总评成绩,并输出学生的信息。 信息。

下一页 返回

Page 3: 第  9  章  结构体及其应用

9.1 9.1 一个程序实例一个程序实例 【编程思路】 【编程思路】 本实例中学生的信息包含 本实例中学生的信息包含 5 5 个数据项,这些数据项具有内在的联系个数据项,这些数据项具有内在的联系(同属于一个学生) ,然而数据类型却不尽相同。面对这种情况,(同属于一个学生) ,然而数据类型却不尽相同。面对这种情况, C C 语言允许编程者自己构造一种数据类型——结构体类型,把多个数据语言允许编程者自己构造一种数据类型——结构体类型,把多个数据项(类型可以相同也可以不相同)组合在一起,作为一个整体进行处项(类型可以相同也可以不相同)组合在一起,作为一个整体进行处理。 理。 根据本题的情况,用以下形式构造名为 根据本题的情况,用以下形式构造名为 student student 的结构体类型。 的结构体类型。 struct student /*student struct student /*student 为结构体类型名为结构体类型名 */ */ { int num{ int num ; ; /*/* 存放学号,为存放学号,为 intint 型型 */ */ char name[10] /*char name[10] /* 存放姓名,用字符数组存放姓名,用字符数组 */ */ float s1float s1 ,, s2s2 ,, scorescore ; ; /*/* 存放存放 33 个成绩,为个成绩,为 floatfloat 型型 */ */ }} ; ;

上一页 下一页 返回

Page 4: 第  9  章  结构体及其应用

9.1 9.1 一个程序实例一个程序实例 struct student struct student 是一种结构体类型,它由 是一种结构体类型,它由 5 5 个数据项组成,此处个数据项组成,此处的数据项称为结构体成员或者域。接下来可以用 的数据项称为结构体成员或者域。接下来可以用 struct student struct student 这这个数据类型定义变量,只有变量才能存储数据。 个数据类型定义变量,只有变量才能存储数据。 例如,下面语句定义了一个结构体变量: 例如,下面语句定义了一个结构体变量: struct student wangstruct student wang ; ; 结构体变量 结构体变量 wang wang 包括学号、姓名、平时成绩、期末成绩和总评包括学号、姓名、平时成绩、期末成绩和总评成绩等 成绩等 5 5 个成员。程序中结构体变量不能整体引用,要引用到其中个成员。程序中结构体变量不能整体引用,要引用到其中的成员。 的成员。 结构体变量中成员的引用形式为:结构体变量结构体变量中成员的引用形式为:结构体变量 .. 成员名。比如:成员名。比如: wawang.numng.num 、、 wang.namewang.name 、、 wang.s1 wang.s1 等。结构体成员在程序中的作等。结构体成员在程序中的作用和用法与普通变量相同。 用和用法与普通变量相同。

上一页 下一页 返回

Page 5: 第  9  章  结构体及其应用

9.1 9.1 一个程序实例一个程序实例 【程序代码】 【程序代码】 #include <stdio.h> #include <stdio.h> #include <string.h> #include <string.h> struct student /*struct student /* 定义结构体类型定义结构体类型 */ */ { { int numint num ; ; char name[10]char name[10] ; ; float s1float s1 ,, s2s2 ,, scorescore ; ; }} ; ; main() main() { { struct student wangstruct student wang ; ; /*/* 定义结构体变量定义结构体变量 */ */ /*/* 以下给变量名为以下给变量名为 wang wang 的学生赋值的学生赋值 */ */

上一页 下一页 返回

Page 6: 第  9  章  结构体及其应用

9.1 9.1 一个程序实例一个程序实例 wang.num=101wang.num=101 ; ; strcpy(wang.namestrcpy(wang.name ,, "wanghai")"wanghai") ; ; wang.s1=92.0wang.s1=92.0 ; ; wang.s2=87.5wang.s2=87.5 ; ; wang.score=wang.s1*0.3+wang.s2*0.7wang.score=wang.s1*0.3+wang.s2*0.7 ; ; /*/* 计算总评成绩计算总评成绩 */ */ /*/* 以下输出该学生信息以下输出该学生信息 */ */ printf("NO.printf("NO. :: %d\n"%d\n" ,, wang.num)wang.num) ; ; printf("NAMEprintf("NAME:: %s\n"%s\n" ,, wang.name)wang.name) ; ; printf("s1=%7.2fprintf("s1=%7.2f ,, s2=%7.2fs2=%7.2f ,, score=%7.2f\n\n"score=%7.2f\n\n" ,, wang.s1wang.s1 ,,wang.s2wang.s2 ,, wang.score)wang.score) ; ; } } 程序输出结果为:程序输出结果为:

上一页 返回

Page 7: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用 结构体类型是一种用户自定义的构造类型。使用时,必须先定义结结构体类型是一种用户自定义的构造类型。使用时,必须先定义结构体类型,然后再用其类型定义结构体变量。 构体类型,然后再用其类型定义结构体变量。 9.2.1 9.2.1 结构体类型的定义结构体类型的定义 定义结构体类型的一般形式为: 定义结构体类型的一般形式为: struct struct 结构体类型名 结构体类型名 { { 类型名类型名 1 1 成员名成员名 1; 1; 类型名类型名 2 2 成员名成员名 2; 2; …… …… 类型名类型名 1 1 成员名成员名 1; 1; }} ; ;

下一页 返回

Page 8: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用 例如: 例如: struct stud struct stud { int num; { int num; char name[20]; char name[20]; char sex; char sex; int age; int age; float score[3]; float score[3]; char address[30]; char address[30]; }} ; ; 说明: 说明: (( 11 )) struct struct 是关键字,标志结构体类型。是关键字,标志结构体类型。 struct struct 后面是所定义后面是所定义的结构体类型的名字,结构体名应符合标识符的命名规则。这里结构的结构体类型的名字,结构体名应符合标识符的命名规则。这里结构体名可以省略,省略后将成为无名结构体。 体名可以省略,省略后将成为无名结构体。

上一页 下一页 返回

Page 9: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用 (( 22 )结构体的各个成员用花括号括起来,结构体成员的定义方式)结构体的各个成员用花括号括起来,结构体成员的定义方式和变量的定义方式一样,成员名的命名规则和变量相同;各成员之间和变量的定义方式一样,成员名的命名规则和变量相同;各成员之间用分号分隔;结构体类型的定义以分号结束。 用分号分隔;结构体类型的定义以分号结束。 (( 33 )结构体成员的数据类型可以是基本类型的,也可以是构造类)结构体成员的数据类型可以是基本类型的,也可以是构造类型,如数组或其他结构体类型。 型,如数组或其他结构体类型。 9.2.2 9.2.2 结构体变量的定义及引用 结构体变量的定义及引用 有了结构体数据类型,接下来需要定义结构体类型变量,以便存放有了结构体数据类型,接下来需要定义结构体类型变量,以便存放结构体类型的数据。 结构体类型的数据。 1.1. 结构体变量的定义 结构体变量的定义 C C 语言中,结构体变量定义可以采取三种方法。 语言中,结构体变量定义可以采取三种方法。 (( 11 )先声明结构体类型再定义变量名。 )先声明结构体类型再定义变量名。

上一页 下一页 返回

Page 10: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用 例如: 例如: struct stud /*struct stud /* 定义结构体类型定义结构体类型 */ */ { int num; { int num; char name[20]; char name[20]; char sex; char sex; int age; int age; float score[3]; float score[3]; char address[30]; char address[30]; }; }; struct stud student1struct stud student1 ,, student2student2 ; ; /*/* 定义结构体变量定义结构体变量 */ */ 以上定义了两个结构体变量 以上定义了两个结构体变量 student1 student1 和 和 student2student2 , 它们均包, 它们均包含 含 6 6 个成员: 编号、姓名、性别、年龄、个成员: 编号、姓名、性别、年龄、 3 3 门课成绩和地址。 门课成绩和地址。

上一页 下一页 返回

Page 11: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用 与普通变量一样,结构体变量也可以通过初始化赋值。例如: 与普通变量一样,结构体变量也可以通过初始化赋值。例如: struct stud student1={101struct stud student1={101 ,, "ghz""ghz" ,, 'M''M' ,, 1818 ,, 75.475.4 ,, 89.89.33 ,, 92.592.5 ,, "xian"}"xian"} ; ; struct stud student2={102struct stud student2={102 ,, "xh"xhy"y" ,, 'M''M' ,, 1616 ,, 95.195.1 ,, 9999 ,, 9292 ,, "beijing"}"beijing"} ; 结构体变量 ; 结构体变量 ststudent1 udent1 和 和 student2 student2 中各成员的赋值情况如图 中各成员的赋值情况如图 9−1 9−1 所示。 所示。 注意:上面定义的结构体类型有 注意:上面定义的结构体类型有 6 6 个成员,而赋值的时候有 个成员,而赋值的时候有 8 8 项项数据,原因是第 数据,原因是第 5 5 个成员 个成员 score score 是数组,它有 是数组,它有 3 3 个元素,用来存个元素,用来存放 放 3 3 门课成绩。 从门课成绩。 从图 图 9−1 9−1 中可以看到,各成员分配在连续的存储区中可以看到,各成员分配在连续的存储区

域内,而且各个成员所占的字节数之和就是结构体变量的字节数。 域内,而且各个成员所占的字节数之和就是结构体变量的字节数。 (( 22 )定义结构体类型的同时定义结构体变量。 )定义结构体类型的同时定义结构体变量。

上一页 下一页 返回

Page 12: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用 这种方法定义的一般形式为: 这种方法定义的一般形式为: struct struct 结构体名 结构体名 { { 成员表列 成员表列 }} 变量名表列; 变量名表列; 例如,上面的结构体类型 例如,上面的结构体类型 struct stud struct stud 也可以采取以下形式定义: 也可以采取以下形式定义: struct stud struct stud { int num; { int num; char name[20]; char name[20]; char sex; char sex; int age; int age; float score[3]; float score[3]; char address[30]; char address[30]; } student1={101} student1={101 ,, "ghz""ghz" ,, 'M''M',, 1818 ,, 75.475.4,, 89.389.3 ,, 92.92.55 ,, "xian"}"xian"} ,, student2; student2;

上一页 下一页 返回

Page 13: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用 (( 33 )定义无名结构体类型的同时定义结构体变量(即不出现结构体)定义无名结构体类型的同时定义结构体变量(即不出现结构体名) 一般定义形式为: 名) 一般定义形式为: struct struct { { 成员表列 成员表列 }} 变量名表列; 变量名表列; 例如: 例如: struct struct { int num; { int num; char name[20]; char name[20]; char sex; char sex; int age; int age; float score[3]; float score[3]; char address[30]; char address[30]; }student1}student1 ,, student2; student2;

上一页 下一页 返回

Page 14: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用 2. 2. 结构体变量的引用 结构体变量的引用 (( 11 )结构体变量中成员的引用。 )结构体变量中成员的引用。 结构体变量本身不能代表一个特定的值,只有它的成员才会有特定结构体变量本身不能代表一个特定的值,只有它的成员才会有特定的值。因此使用结构体变量时,要引用其成员。 的值。因此使用结构体变量时,要引用其成员。 结构体变量中成员的引用形式是: 结构体变量中成员的引用形式是: 结构体变量结构体变量 .. 成员名 成员名 例如,结构体变量 例如,结构体变量 student1 student1 中各个成员引用形式如下: 中各个成员引用形式如下: student1.numstudent1.num 、、 student1.namestudent1.name 、、 student1.sexstudent1.sex 、、 student1.student1.ageage 、、 student1.address student1.address student1.score[0]student1.score[0] 、、 student1.score[1]student1.score[1] 、、 student1.score[2]student1.score[2]

上一页 下一页 返回

Page 15: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用 结构体中成员的作用与地位相当于普通变量,因此可以进行与普通结构体中成员的作用与地位相当于普通变量,因此可以进行与普通变量一样的操作,比如赋值、输入输出等,例如有以下语句: 变量一样的操作,比如赋值、输入输出等,例如有以下语句: student1.num=101; student1.num=101; scanf(“%d”,&student1.num); scanf(“%d”,&student1.num); printf("%d \n",student1.num); printf("%d \n",student1.num); distance=student1.age- student2.age; distance=student1.age- student2.age; (( 22 )同类型结构体变量可以相互赋值。 )同类型结构体变量可以相互赋值。 对结构体变量不能整体引用,但同类型结构体变量之间可以相互赋对结构体变量不能整体引用,但同类型结构体变量之间可以相互赋值。 值。 【例 − 】结构体变量的引用。 【例 − 】结构体变量的引用。 #include <stdio.h> #include <stdio.h> struct stud /*struct stud /* 定义结构体类型定义结构体类型 stud*/ stud*/ { {

上一页 下一页 返回

Page 16: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用 char xm[10]; char xm[10]; int age; int age; }; }; void main() void main() { { struct stud stu1,stu2; /*struct stud stu1,stu2; /* 定义结构体变量定义结构体变量 */ */ scanf("%s %d",stu1.xm,&stu1.age); /*scanf("%s %d",stu1.xm,&stu1.age); /* 结构体变量引用到成结构体变量引用到成员员 */ */ printf("stu1-->%s:%d\n",stu1.xm,stu1.age); /*printf("stu1-->%s:%d\n",stu1.xm,stu1.age); /* 结构体变量结构体变量引用到成员引用到成员 */ */ stu2=stu1; /* stu2=stu1; /* 把变量把变量 stu1stu1各成员的值赋给变量各成员的值赋给变量 stu2stu2 的相应成的相应成员员 */ */ printf("stu2---%s:%d\n",stu2.xm,stu2.age); /*printf("stu2---%s:%d\n",stu2.xm,stu2.age); /* 结构体变量引结构体变量引用到成员用到成员 */ */ } } 程序运行时输入“程序运行时输入“ zhangsan 20” zhangsan 20” ,输出结果为:,输出结果为:

上一页 下一页 返回

Page 17: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用 3. 3. 结构体类型嵌套 结构体类型嵌套 以上给出的例子中,结构体成员的类型都是基本类型和数组类型。以上给出的例子中,结构体成员的类型都是基本类型和数组类型。实际上,成员的类型可以是任何数据类型。下面给出成员类型是另一实际上,成员的类型可以是任何数据类型。下面给出成员类型是另一个结构体类型的例子。 个结构体类型的例子。 例如: 例如: struct date /*struct date /* 日期结构日期结构 */ */ { { int year; int year; int month; int month; int day; int day; }; }; struct studentstruct student

上一页 下一页 返回

Page 18: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用

{ int num; { int num; char name[20]; char name[20]; char sex; char sex; int age; int age; struct date birthday; /* struct date struct date birthday; /* struct date 为结构体类型为结构体类型 */ */ char address[30]; char address[30]; }stu={102,"xhy",'M',16,1977,5,8,"beijing"}; }stu={102,"xhy",'M',16,1977,5,8,"beijing"}; 上例中结构体变量 上例中结构体变量 stu stu 的存储结构如的存储结构如图 图 9−2 9−2 所示。 当成员本身又所示。 当成员本身又属于一个结构体类型,引用时要逐级找到最低一级成员,只能对最低属于一个结构体类型,引用时要逐级找到最低一级成员,只能对最低级的成员进行赋值或存取操作。 级的成员进行赋值或存取操作。 例如,对上面定义的结构体变量 例如,对上面定义的结构体变量 stustu ,可以这样访问其中的日期成,可以这样访问其中的日期成员: 员: stu. birthday. year stu. birthday. year stu.birthday.month stu.birthday.month stu.birthday. day stu.birthday. day

上一页 下一页 返回

Page 19: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用 9.2.3 9.2.3 结构体数组结构体数组 在例 在例 9−1 9−1 中一个结构体变量只能处理一个人的信息(如一个学生中一个结构体变量只能处理一个人的信息(如一个学生的学号、姓名、成绩等数据) 。但在实际应用中经常需要处理一批人的学号、姓名、成绩等数据) 。但在实际应用中经常需要处理一批人的信息,这时应该使用结构体类型的数组。 的信息,这时应该使用结构体类型的数组。 定义结构体数组与定义结构体变量的方法相同。例如: 定义结构体数组与定义结构体变量的方法相同。例如: struct student struct student {{ int num; int num; char name[20]; char name[20]; char sex; char sex; int age; int age; float score[3]; float score[3]; char address[30]; char address[30]; } stu[3]; } stu[3];

上一页 下一页 返回

Page 20: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用 以上定义了一个数组 以上定义了一个数组 stustu , 它有 , 它有 3 3 个元素 个元素 stu[0]stu[0] 、 、 stu[1]stu[1] 、 、 ststu[2]u[2] , 类型均为 , 类型均为 struct student struct student 类型。 结构体数组中成员的引用类型。 结构体数组中成员的引用方式与结构体变量相同, 下面以元素 方式与结构体变量相同, 下面以元素 stu[0]stu[0] 为例,给出各个成员的为例,给出各个成员的引用形式: 引用形式: stu[0].numstu[0].num 、、 stu[0].namestu[0].name 、、 stu[0].sexstu[0].sex 、、 stu[0].age stu[0].astu[0].age stu[0].address ddress stu[0].score[0]stu[0].score[0] 、、 stu[0].score[1]stu[0].score[1] 、、 stu[0].score[2] stu[0].score[2] 可见,结构体数组元素也是通过数组名和下标来引用的。因为各个可见,结构体数组元素也是通过数组名和下标来引用的。因为各个元素都是结构体类型,因此对结构体数组元素的引用与对结构体变量元素都是结构体类型,因此对结构体数组元素的引用与对结构体变量的引用一样,也要逐级引用,只能对最低的成员进行存取和运算。 的引用一样,也要逐级引用,只能对最低的成员进行存取和运算。 【例 − 】候选人得票统计程序。设有 【例 − 】候选人得票统计程序。设有 3 3 个候选人,个候选人, 10 10 个投票人,个投票人,输入得票人的名字并进行统计,最后输出各人得票结果。 输入得票人的名字并进行统计,最后输出各人得票结果。

上一页 下一页 返回

Page 21: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用 #include <string.h> #include <string.h> #include <stdio.h> #include <stdio.h> struct person struct person { { char name[20]; /*char name[20]; /* 候选人姓名候选人姓名 */ */ int count; /*int count; /* 候选人票数候选人票数 */ */ }leader[3]={"star",0,"mery",0,"sun",0}; /*}leader[3]={"star",0,"mery",0,"sun",0}; /* 定义结构体数组并初始定义结构体数组并初始化化 */ */ main() main() { { int i,j; int i,j; char leader_name[20]; char leader_name[20]; for(i=1;i<=10;i++) for(i=1;i<=10;i++)

上一页 下一页 返回

Page 22: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用 { { scanf("%s",leader_name); scanf("%s",leader_name); for(j=0;j<3;j++) for(j=0;j<3;j++) if(strcmp(leader_name,leader[j].name)==0) /*if(strcmp(leader_name,leader[j].name)==0) /* 比较输入的名字与候比较输入的名字与候选人的名字选人的名字 * * leader[j].count++; /*leader[j].count++; /* 相当于相当于 leader[j].count= leader[j].count +leader[j].count= leader[j].count +

1;*/ 1;*/ } } printf("\n"); printf("\n"); for(i=0;i<3;i++) for(i=0;i<3;i++) printf("%5sprintf("%5s :: %d\n",leader[i].name,leader[i].count); %d\n",leader[i].name,leader[i].count); } } 程序运行结果为: 程序运行结果为:

上一页 下一页 返回

Page 23: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用 9.2.4 9.2.4 结构体指针结构体指针 结构体指针是指基类型为结构体类型的指针变量。通过结构体指针可结构体指针是指基类型为结构体类型的指针变量。通过结构体指针可以间接访问结构体中的成员。 下面通过实例说明结构体指针的应用。 以间接访问结构体中的成员。 下面通过实例说明结构体指针的应用。 【例 − 】使用结构体指针输出学生基本信息。 【例 − 】使用结构体指针输出学生基本信息。 【程序代码】 【程序代码】 #include <string.h> #include <string.h> #include <stdio.h> #include <stdio.h> main() main() { { struct student /* struct student /* 定义一个结构体类型定义一个结构体类型 */ */ { { long num; long num; char name[20]; char name[20]; char sex; char sex; float score; float score;

上一页 下一页 返回

Page 24: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用 }; }; struct student stu,*p; /* struct student stu,*p; /* 定义结构体变量定义结构体变量 stustu 和结构体指针和结构体指针 p p */ */ p=&stu; /* p=&stu; /* 结构体指针结构体指针 pp 指向结构体变量指向结构体变量 stu */ stu */ stu.num=101; stu.num=101; strcpy(stu.name,"Xuhuayu"); strcpy(stu.name,"Xuhuayu"); stu.sex='M'; stu.sex='M'; stu.score=90.0; stu.score=90.0; printf("No.:%ld\nname:%s\nsex:%c\nscore:%f\n",stu.num,printf("No.:%ld\nname:%s\nsex:%c\nscore:%f\n",stu.num,stu.name,stu.sex,stu.score); stu.name,stu.sex,stu.score); printf("No.:%ld\nname:%s\nsex:%c\nscore:%f\n",(*p).nuprintf("No.:%ld\nname:%s\nsex:%c\nscore:%f\n",(*p).num,(*p).name,(*p).sex,(*p).score); m,(*p).name,(*p).sex,(*p).score); } } 程序运行结果为:程序运行结果为:

上一页 下一页 返回

Page 25: 第  9  章  结构体及其应用

9.2 9.2 结构体类型的使用结构体类型的使用 【程序分析】 【程序分析】 程序中将结构体变量 程序中将结构体变量 stu stu 的地址赋给指针变量 的地址赋给指针变量 pp ,也就是使 ,也就是使 p p 指指向 向 stustu ,然后对 ,然后对 stu stu 的各成员赋值,第一个 的各成员赋值,第一个 printf()printf() 函数输出 函数输出 stu stu 的各个成员的值,第二个 的各个成员的值,第二个 printfprintf 函数也是用来输出 函数也是用来输出 stu stu 各成员的值,各成员的值,但使用的是(但使用的是( *p).num *p).num 这样的形式。 这样的形式。 通过结构体指针引用成员的方式有两种: 通过结构体指针引用成员的方式有两种: ① ① (*p).(*p). 成员名 成员名 ② ② p−>p−> 成员名 (−成员名 (− >> 为指向运算符) 为指向运算符) 指针变量可以指向结构体变量,当然也可以指向结构体数组,其使指针变量可以指向结构体变量,当然也可以指向结构体数组,其使用方法与指向数组的指针的使用方法类似,只不过把普通数组换成了用方法与指向数组的指针的使用方法类似,只不过把普通数组换成了结构体数组。 结构体数组。

上一页 返回

Page 26: 第  9  章  结构体及其应用

9.3 9.3 链 表链 表 9.3.1 9.3.1 链表的基本结构 链表的基本结构 链表是一种动态数据结构,可根据需要动态地开辟存储空间,随时链表是一种动态数据结构,可根据需要动态地开辟存储空间,随时释放不再需要的存储空间。这样可以有效利用存储空间,提高存储空释放不再需要的存储空间。这样可以有效利用存储空间,提高存储空间利用率。 间利用率。 图 图 9−3 9−3 是一种单向链表结构示意图。链表中的每个元素是一种单向链表结构示意图。链表中的每个元素

称为链表的结点,每个结点中包括两部分内容,即用户需要的数据和称为链表的结点,每个结点中包括两部分内容,即用户需要的数据和下一个结点的地址,也就是说,链表中的每个结点是由数据域和指针下一个结点的地址,也就是说,链表中的每个结点是由数据域和指针域组成。 在链表中通常用一个指针指向链表开头的结点,该指针称为域组成。 在链表中通常用一个指针指向链表开头的结点,该指针称为头指针。图 头指针。图 9−39−3 中 中 head head 即为头指针,它指向第一个结点。 即为头指针,它指向第一个结点。 单向链表中前一个结点的指针域指向后一个结点,这样可以通过前单向链表中前一个结点的指针域指向后一个结点,这样可以通过前一个结点引用后一个结点。最后一个结点不再指向其他结点,称为尾一个结点引用后一个结点。最后一个结点不再指向其他结点,称为尾结点(即表尾) ,它的指针域的值是 结点(即表尾) ,它的指针域的值是 NULLNULL (空指针) ,表示整个(空指针) ,表示整个链表到此结束。 链表到此结束。

下一页 返回

Page 27: 第  9  章  结构体及其应用

9.3 9.3 链 表链 表 从链表的特点来看,结构体类型最适合描述链表。例如,有以下结从链表的特点来看,结构体类型最适合描述链表。例如,有以下结构体类型定义: 构体类型定义: struct node struct node { { int num; int num; float score; float score; struct node *next; struct node *next; }; }; 其中成员 其中成员 num num 和 和 score score 用来存放结点中的有用数据(即数据用来存放结点中的有用数据(即数据域) ,域) , next next 是指针域,它的类型是 是指针域,它的类型是 struct node struct node 类型,用来指向类型,用来指向一个结点。 一个结点。

上一页 下一页 返回

Page 28: 第  9  章  结构体及其应用

9.3 9.3 链 表链 表 【例 − 】建立一个简单链表如【例 − 】建立一个简单链表如图 图 9−4 9−4 所示,它由 所示,它由 3 3 个存放学生数据个存放学生数据(包括学号和姓名)的结点组成,然后输出各个结点数据。 (包括学号和姓名)的结点组成,然后输出各个结点数据。 【程序代码】 【程序代码】 #include "stdio.h" #include "stdio.h" struct node struct node { { int num; /* int num; /* 存储学生学号 存储学生学号 */ */ float score; /* float score; /* 存储学生成绩 存储学生成绩 */ */ struct node *next; /* struct node *next; /* 定义结构体指针,指向下一个结点 定义结构体指针,指向下一个结点 */ */ }; }; main() main() { { struct node astruct node a ,, bb ,, cc ,, *head*head ,, *p; *p;

上一页 下一页 返回

Page 29: 第  9  章  结构体及其应用

9.3 9.3 链 表链 表 a.num=101;a.score=85.4; /* a.num=101;a.score=85.4; /* 给结点给结点 aa 的的 numnum 和和 scorescore 域赋值 域赋值 **/ / b.num=103;b.score=96.1; /* b.num=103;b.score=96.1; /* 给结点给结点 bb的的 numnum 和和 scorescore 域赋值 域赋值 */ */ c.num=105;c.score=77.5; /* c.num=105;c.score=77.5; /* 给结点给结点 cc 的的 numnum 和和 scorescore 域赋值 域赋值 */ */ head=&a; /* head=&a; /* 头指针头指针 headhead指向结点指向结点 a */ a */ a.next=&b; /* a.next=&b; /* 链接结点链接结点 bb和和 aa 结点结点 */ */ b.next=&c; /* b.next=&c; /* 链接结点链接结点 cc 和和 bb结点结点 */ */ c.next=NULL; /* c.next=NULL; /* 结点结点 cc 为尾结点为尾结点 */ */ p=head; /* p=head; /* 使使 pp指针指向第一个结点指针指向第一个结点 */ */ do /* do /* 依次输出各结点数据 依次输出各结点数据 */ */ {printf("{printf(" 学号:学号: %d %d 成绩:成绩: %5.2f\n"%5.2f\n" ,, p->nump->num ,, p->score); p->score); p=p->next; /* p=p->next; /* 指针指针 pp后移,指向下一结点后移,指向下一结点 */ */ }while (p!=NULL); }while (p!=NULL); } } 程序运行结果为:程序运行结果为: 上一页 下一页 返回

Page 30: 第  9  章  结构体及其应用

9.3 9.3 链 表链 表 9.3.2 9.3.2 链表的基本操作链表的基本操作 1.1.动态分配和释放存储区 动态分配和释放存储区 动态开辟存储空间需要使用 动态开辟存储空间需要使用 malloc()malloc() 函数,释放存储空间使用 函数,释放存储空间使用 frfree()ee() 函数。这些函数包含在头文件“函数。这些函数包含在头文件“ stdlib.h”stdlib.h” 中。 中。 (( 11 )) malloc()malloc()函数。函数调用的一般形式为:函数。函数调用的一般形式为: malloc(size) malloc(size) 功能:在内存申请分配一个 功能:在内存申请分配一个 size size 字节的存储区。调用结果为新分配字节的存储区。调用结果为新分配的存储区的首地址,是一个 的存储区的首地址,是一个 void*void* 类型指针,若申请失败,则返回 类型指针,若申请失败,则返回 NULLNULL 。 。 void*void* 类型指针是一个指向非具体数据类型的指针,称为无类型指针是一个指向非具体数据类型的指针,称为无类型指针,因此一般在使用该函数时,要用强制类型转换将其转换为类型指针,因此一般在使用该函数时,要用强制类型转换将其转换为所需要的类型。例如: 所需要的类型。例如: int *p; int *p; p=(int*)malloc(2); p=(int*)malloc(2);

上一页 下一页 返回

Page 31: 第  9  章  结构体及其应用

9.3 9.3 链 表链 表 上面语句完成向内存申请 上面语句完成向内存申请 2 2 字节的存储区,用来存放一个整数,并字节的存储区,用来存放一个整数,并让指针 让指针 pp指向存储区的首部。 指向存储区的首部。 struct node *p; struct node *p; p=(struct node *)malloc(sizeof(struct node)); p=(struct node *)malloc(sizeof(struct node)); 上面语句中上面语句中 sizeofsizeof 是是 CC 语言的运算符, 功能是计算数据类型或变语言的运算符, 功能是计算数据类型或变量所占的字节数,量所占的字节数, sizeof(struct node)sizeof(struct node) 是计算是计算 struct nodestruct node 类型所类型所占的字节数,那么占的字节数,那么 malloc(sizeof(struct node))malloc(sizeof(struct node)) 的功能是申请分配的功能是申请分配一个一个 struct nodestruct node 类型所需大小的存储区。 由于类型所需大小的存储区。 由于 malloc()malloc() 的返回值的返回值是无类型指针,而指针是无类型指针,而指针 pp 的基类型是的基类型是 struct nodestruct node 类型,因此需要进类型,因此需要进行强制类型转换,将行强制类型转换,将 malloc()malloc() 函数的返回值转换为指向函数的返回值转换为指向 struct nodstruct nodee 类型的指针。 类型的指针。 (( 22 )) free()free() 函数。函数调用的一般形式为:函数。函数调用的一般形式为: free(p) free(p) 功能:释放指针 功能:释放指针 p p 所指向的动态存储区。 所指向的动态存储区。

上一页 下一页 返回

Page 32: 第  9  章  结构体及其应用

9.3 9.3 链 表链 表 2. 2. 建立单向链表 建立单向链表 建立动态链表是指在程序执行过程中从无到有地建立起一个链表,建立动态链表是指在程序执行过程中从无到有地建立起一个链表,即一个一个地开辟结点和输入结点数据,并建立起前后链接关系。 即一个一个地开辟结点和输入结点数据,并建立起前后链接关系。 【例 − 】建立链表函数。 建立一个有若干名学生数据的单向动态链表,【例 − 】建立链表函数。 建立一个有若干名学生数据的单向动态链表,当输入的学生学号为零时结束操作。 当输入的学生学号为零时结束操作。 【程序代码】 【程序代码】 #include "stdio.h" #include "stdio.h" #include "stdlib.h" #include "stdlib.h" struct node struct node { { int num; int num; float score; float score; struct node *next; struct node *next; }; }; struct node *create() struct node *create() { {

上一页 下一页 返回

Page 33: 第  9  章  结构体及其应用

9.3 9.3 链 表链 表

struct node *head,*s,*p; struct node *head,*s,*p; int c; int c; float x; float x; head=(struct node *)malloc(sizeof(struct node)); /*head=(struct node *)malloc(sizeof(struct node)); /* 生成头结生成头结点点 */ */ p=head; /*p=head; /* 尾指针指向第一个结点尾指针指向第一个结点 */ */ printf("printf(" 输入学生结点信息输入学生结点信息 (( 学号和成绩学号和成绩 ),),学号为学号为 00 时输入结束:时输入结束: \\n"); n"); scanf("%d%f",&c,&x); /*scanf("%d%f",&c,&x); /* 输入学生数据输入学生数据 */ */ while(c!=0) while(c!=0) { { s=(struct node *)malloc(sizeof(struct node)); /*s=(struct node *)malloc(sizeof(struct node)); /* 生成新结点生成新结点 ss*/ */ s->num=c; /*s->num=c; /* 将读入的学生学号存放到新结点将读入的学生学号存放到新结点 ss 的数据域中的数据域中 */ */

上一页 下一页 返回

Page 34: 第  9  章  结构体及其应用

9.3 9.3 链 表链 表 s->score=x; /*s->score=x; /* 将读入的学生成绩存放到新结点将读入的学生成绩存放到新结点 ss 的数据域中的数据域中 */ */ p->next=s; /*p->next=s; /* 将新结点将新结点 ss 插入到表尾插入到表尾 */ */ p=s; /*p=s; /* 修改尾指针修改尾指针 pp指向当前的尾结点指向当前的尾结点 */ scanf("%d%*/ scanf("%d%f",&c,&x); /*f",&c,&x); /* 输入新的学生数据输入新的学生数据 */ */ } } p->next=NULL; /*p->next=NULL; /* 将最后一个结点的指针域置为空将最后一个结点的指针域置为空 */ */ return(head); /*return(head); /* 返回头指针返回头指针 */ */ } } 【程序分析】 【程序分析】 (( 11 )本例链表建立采用的是尾插法,即新结点始终链接在链表的)本例链表建立采用的是尾插法,即新结点始终链接在链表的尾部。 尾部。

上一页 下一页 返回

Page 35: 第  9  章  结构体及其应用

9.3 9.3 链 表链 表 (( 22 )链表建立的具体过程为:首先用 )链表建立的具体过程为:首先用 malloc()malloc() 函数申请头结点,函数申请头结点,并将指针 并将指针 pp 也指向头结点,如也指向头结点,如图 图 9−59−5((aa))所示,然后输入学生数据,所示,然后输入学生数据,判断学号是否为 判断学号是否为 00 ,并由此进入循环体,在循环体中为新结点 ,并由此进入循环体,在循环体中为新结点 s s 申申请空间并存入数据,如图 请空间并存入数据,如图 9−59−5 (( bb )所示,将新结点链接到链表尾)所示,将新结点链接到链表尾部,如图 部,如图 9−59−5 (( cc ) ,移动指针 ) ,移动指针 p p 使其指向新的链尾结点,如图 使其指向新的链尾结点,如图 9−59−5 (( dd ) ,然后开始下一轮操作,如图 ) ,然后开始下一轮操作,如图 9−59−5 (( ee )和如图 )和如图 9−59−5(( ff )所示,如此反复,当用户输入 )所示,如此反复,当用户输入 0 0 时候,表示操作结束,此时 时候,表示操作结束,此时 p p 依然指向链表的结尾,将其指针域置为 依然指向链表的结尾,将其指针域置为 NULLNULL ,整个链表建立结,整个链表建立结束,返回头指针束,返回头指针。 。

上一页 下一页 返回

Page 36: 第  9  章  结构体及其应用

9.3 9.3 链 表链 表 3. 3. 输出链表 输出链表 【例 − 】输出链表函数。 【例 − 】输出链表函数。 【程序代码】 【程序代码】 void print(struct node *head) void print(struct node *head) { { struct node *p; struct node *p; printf("\t printf("\t 输出学生结点信息输出学生结点信息 \n"); \n"); p=head->next; /* p=head->next; /* 指针指针 pp指向第一个结点指向第一个结点 */ */ while (p!=NULL) while (p!=NULL) { { printf("printf(" 学号:学号: %d%d 成绩:成绩: %5.1f\n"%5.1f\n" ,, p->nump->num ,, p->score); p->score); p=p->next; /* p=p->next; /* 指针指针 pp后移,指向下一结点 后移,指向下一结点 */ */ } } } }

上一页 下一页 返回

Page 37: 第  9  章  结构体及其应用

9.3 9.3 链 表链 表 4. 4. 删除链表中的结点 删除链表中的结点 从链表中删去一个结点,首先要找到这个结点,然后把它从链表中从链表中删去一个结点,首先要找到这个结点,然后把它从链表中分离开来,撤销原来的链接关系,同时保证原有链表的链接关系。 分离开来,撤销原来的链接关系,同时保证原有链表的链接关系。 【例 − 】删除结点函数,删除链表中学号为 【例 − 】删除结点函数,删除链表中学号为 num num 的结点。 的结点。 【编程思路】 【编程思路】 (( 11 )删除结点操作分两步完成。第一步查找要删除的结点,第二)删除结点操作分两步完成。第一步查找要删除的结点,第二步进行删除。 步进行删除。 (( 22 )查找结点时,从 )查找结点时,从 p p 指向的第一个结点开始,检查该结点中的 指向的第一个结点开始,检查该结点中的 num num 值是否等于输入的要求删除的那个学号,如果相等,就找到了值是否等于输入的要求删除的那个学号,如果相等,就找到了要删除的结点,如不相等,就将 要删除的结点,如不相等,就将 p p 后移一个结点,直到找到要删除后移一个结点,直到找到要删除的结点或者遇到链尾为止。在移动 的结点或者遇到链尾为止。在移动 p p 的同时移动 的同时移动 qq ,使用 ,使用 q q 记录 记录 p p 的前驱结点,如图 的前驱结点,如图 9−69−6((aa))所示。 所示。 (( 33 )找到待删除结点后,使 )找到待删除结点后,使 q q 指向要删除结点 指向要删除结点 p p 的后继结点,的后继结点,如如 图 图 9−69−6 (( bb )所示,然后释放结点 )所示,然后释放结点 p p 的内存空间,如图 的内存空间,如图 9−69−6(( cc )所示。 )所示。

上一页 下一页 返回

Page 38: 第  9  章  结构体及其应用

9.3 9.3 链 表链 表 【程序代码】 【程序代码】 struct node *del(struct node *headstruct node *del(struct node *head ,, int num) int num) { { struct node *p,*q; struct node *p,*q; q=head; q=head; p=head->next; p=head->next; while(num!=p->num&&p!=NULL) while(num!=p->num&&p!=NULL) { { q=p; q=p; p=p->next; p=p->next; } } if(num==p->num) if(num==p->num)

上一页 下一页 返回

Page 39: 第  9  章  结构体及其应用

9.3 9.3 链 表链 表 { { q->next=p->next; q->next=p->next; free(p); free(p); } } else else printf("printf(" 没有找到学号为没有找到学号为 %d%d 的结点!的结点! \n"\n" ,, num); num); return(head); return(head); } } 5. 5. 在链表中插入结点 在链表中插入结点 对链表的插入是指将一个结点插入到一个已有的链表中,为了能做对链表的插入是指将一个结点插入到一个已有的链表中,为了能做到正确插入,必须解决两个问题:如何找到插入的位置;如何实现插到正确插入,必须解决两个问题:如何找到插入的位置;如何实现插入。 入。

上一页 下一页 返回

Page 40: 第  9  章  结构体及其应用

9.3 9.3 链 表链 表 struct node *ins(struct node *headstruct node *ins(struct node *head ,, int cint c ,, float x) float x) { { struct node *pstruct node *p ,, *q*q,, *s; *s; s=(struct node *)malloc(sizeof(struct node)); /*s=(struct node *)malloc(sizeof(struct node)); /* 生成新结点生成新结点 s*/ s*/ s->num=c; /*s->num=c; /* 将要插入的学生学号存放到新结点将要插入的学生学号存放到新结点 ss 的数据域中的数据域中 */ */ s->score=x; /*s->score=x; /* 将要插入的学生成绩存放到新结点将要插入的学生成绩存放到新结点 ss 的数据域中的数据域中 */ */ q=head; q=head; p=head->next; p=head->next; while (p!=NULL&&c>p->num) while (p!=NULL&&c>p->num) { { q=p; q=p; p=p->next; p=p->next; } }

上一页 下一页 返回

Page 41: 第  9  章  结构体及其应用

9.3 9.3 链 表链 表 q->next=s; q->next=s; if(p!=NULL) if(p!=NULL) s->next=p; s->next=p; else else s->next=NULL; s->next=NULL; return(head); return(head); } } 【程序分析】 【程序分析】 首先定义一个新结点存储待插入的结点信息(如首先定义一个新结点存储待插入的结点信息(如图 图 9−7 9−7 中的结点 中的结点 ss ) ) ,从指针,从指针 p p 指向第一个结点开始,将 指向第一个结点开始,将 p->num p->num 与 与 c c 相比较,如果 相比较,如果 cc>> p->nump->num ,将 ,将 p p 后移,并使 后移,并使 q q 始终指向 始终指向 p p 的前驱结点,如图 的前驱结点,如图 9−79−7(( aa )所示,直到 )所示,直到 p-num->c p-num->c 为止,这时找到新结点的插入位置。 为止,这时找到新结点的插入位置。 如果插入位置是链表的尾部,将新结点插到链尾即可。 如果插入位置是链表的尾部,将新结点插到链尾即可。 如果插入位置在链表中间,则让 如果插入位置在链表中间,则让 s->next s->next 指向 指向 p p 结点,如图 结点,如图 9−79−7(( bb)所示,然后让 )所示,然后让 q->next q->next 指向 指向 s s 结点,如图 结点,如图 9−79−7 (( cc )所示。 )所示。

上一页 下一页 返回

Page 42: 第  9  章  结构体及其应用

9.3 9.3 链 表链 表 9.3.3 9.3.3 链表综合应用 链表综合应用 【例 − 】编制主函数,调用链表建立函数,输出函数,删除函数及【例 − 】编制主函数,调用链表建立函数,输出函数,删除函数及插入函数,完成链表的基本操作。 插入函数,完成链表的基本操作。 【程序代码】 【程序代码】 main() main() { { struct node *h; struct node *h; int del_numint del_num ,, in_num; in_num; float in_score; float in_score; h=create(); /*h=create(); /* 建立链表建立链表 */ */ print(h); /*print(h); /* 输出链表输出链表 */ */

上一页 下一页 返回

Page 43: 第  9  章  结构体及其应用

9.3 9.3 链 表链 表 printf("\nprintf("\n 输入要删除的学生结点的学号:输入要删除的学生结点的学号: \n"); \n"); scanf("%d"scanf("%d" ,, &del_num); &del_num); h=del(hh=del(h ,, del_num); /*del_num); /* 删除链表结点删除链表结点 */ */ print(h); /*print(h); /* 输出链表输出链表 */ */ printf("\nprintf("\n 输入要插入的学生结点信息:输入要插入的学生结点信息: \n"); \n"); scanf("%d%f"scanf("%d%f" ,, &in_num&in_num ,, &in_score); &in_score); h=ins(hh=ins(h ,, in_numin_num ,, in_score); /*in_score); /* 插入结点插入结点 */ */ print(h); /*print(h); /* 输出链表输出链表 */ */ } } 程序运行过程为: 程序运行过程为:

上一页 返回

Page 44: 第  9  章  结构体及其应用

9.4 9.4 结构体应用实例结构体应用实例 【例 − 】某班有 【例 − 】某班有 45 45 名学生,现在对他们的期末考试成绩进行统计。名学生,现在对他们的期末考试成绩进行统计。假定期末考 假定期末考 3 3 门课,分别为物理、数学和化学,要求计算每个学生门课,分别为物理、数学和化学,要求计算每个学生的平均成绩和总成绩,最后计算本班每门课的平均成绩。 的平均成绩和总成绩,最后计算本班每门课的平均成绩。 【编程思路】 【编程思路】 (( 11 )本程序分成三部分:学生数据输入(包括计算学生平均成绩)本程序分成三部分:学生数据输入(包括计算学生平均成绩和总成绩) 、学生成绩单输出、本班每门课总成绩和平均成绩的计算和总成绩) 、学生成绩单输出、本班每门课总成绩和平均成绩的计算和输出,分别由三个函数来实现,在主程序中调用这三个函数。 和输出,分别由三个函数来实现,在主程序中调用这三个函数。 (( 22 )定义结构体来存储学生数据,包括学生基本信息,学生三门)定义结构体来存储学生数据,包括学生基本信息,学生三门课成绩(利用数组) ,平均成绩,总成绩。 课成绩(利用数组) ,平均成绩,总成绩。 (( 33 )将结构体数组地址作为实参传递给函数,以便在函数中使用)将结构体数组地址作为实参传递给函数,以便在函数中使用结构体指针对学生数据进行操作。 结构体指针对学生数据进行操作。

下一页 返回

Page 45: 第  9  章  结构体及其应用

9.4 9.4 结构体应用实例结构体应用实例 【程序代码】 【程序代码】 #include "stdio.h" #include "stdio.h" #include "conio.h" #include "conio.h" #include "string.h" #include "string.h" #define NU 3 /*#define NU 3 /* 以以 33 名学生为例名学生为例 */ */ struct student struct student { { long num; /*long num; /* 定义成员变量,存储学生学号定义成员变量,存储学生学号 */ */ char name[10]; /*char name[10]; /* 定义成员变量,存储学生姓名定义成员变量,存储学生姓名 */ */ float score[3]; /*float score[3]; /* 定义成员变量,存储学生定义成员变量,存储学生 33门课的成绩门课的成绩 */ */ float aver_person; /*float aver_person; /* 定义成员变量,存储学生平均成绩定义成员变量,存储学生平均成绩 */ */ float sum_person; /*float sum_person; /* 定义成员变量,存储学生总成绩定义成员变量,存储学生总成绩 */ */

上一页 下一页 返回

Page 46: 第  9  章  结构体及其应用

9.4 9.4 结构体应用实例结构体应用实例 }; }; void print(struct student *p) /*void print(struct student *p) /* 输出个人成绩单 输出个人成绩单 */ */ { { int i; int i; for(i=0;i<NU;p++for(i=0;i<NU;p++ ,, i++) i++) { { printf("\t\t printf("\t\t 学生成绩单学生成绩单 \n"); \n"); printf("\t printf("\t 学号:学号: %ld\n"%ld\n" ,, p->num); p->num); printf("\t printf("\t 姓名:姓名: %s\n"%s\n" ,, p->name); p->name); printf("\t printf("\t 数学:数学: %5.1f |"%5.1f |" ,, p->score[0]); p->score[0]); printf(" printf(" 物理:物理: %5.1f |"%5.1f |" ,, p->score[1]); p->score[1]); printf(" printf(" 化学:化学: %5.1f\n"%5.1f\n" ,, p->score[2]); p->score[2]); printf("\t printf("\t 平均成绩:平均成绩: %5.1f\n"%5.1f\n" ,, p->aver_personp->aver_person); );

上一页 下一页 返回

Page 47: 第  9  章  结构体及其应用

9.4 9.4 结构体应用实例结构体应用实例 printf("\t printf("\t 总成绩:总成绩: %5.1f\n"%5.1f\n" ,, p->sum_person); p->sum_person); printf("--------------------------------------------------------------\printf("--------------------------------------------------------------\n"); n"); } } } } void scan(struct student *p) /*void scan(struct student *p) /* 输入学生数据同时计算个人的平输入学生数据同时计算个人的平均成绩和总成绩 均成绩和总成绩 */ */ { { int iint i ,, j; j; printf(" printf(" 学生信息录入学生信息录入 \n"); \n"); for(i=0;i<NU;p++for(i=0;i<NU;p++ ,, i++) i++) { { p->sum_person=0; p->sum_person=0;

上一页 下一页 返回

Page 48: 第  9  章  结构体及其应用

9.4 9.4 结构体应用实例结构体应用实例 printf("printf(" 学号:学号: "); "); scanf("%ld"scanf("%ld" ,, &p->num); /*&p->num); /* 使用结构体指针输入学生学号使用结构体指针输入学生学号*/ */ printf("printf(" 姓名:姓名: "); "); scanf("%s"scanf("%s" ,, &p->name); /*&p->name); /* 输入学生姓名输入学生姓名 */ */ printf("printf(" 成绩录入:成绩录入: \n"); \n"); for(j=0;j<3;j++) for(j=0;j<3;j++) { { printf("\t printf("\t 第第 %d%d 门成绩:门成绩: "" ,, j+1); j+1); scanf("%f"scanf("%f" ,, &p->score[j]); /*&p->score[j]); /* 输入学生第输入学生第 jj 门课成绩门课成绩*/ */ p->sum_person=p->sum_person+p->score[j]; /*p->sum_person=p->sum_person+p->score[j]; /* 学生学生成绩累加求和成绩累加求和 */ */ } }

上一页 下一页 返回

Page 49: 第  9  章  结构体及其应用

9.4 9.4 结构体应用实例结构体应用实例 p->aver_person=p->sum_person/3; /*p->aver_person=p->sum_person/3; /* 计算单个学生的平均成计算单个学生的平均成绩绩 */ */ } } printf("--------------------------------------------------------------\n"); printf("--------------------------------------------------------------\n"); } } void average(struct student *p) /* void average(struct student *p) /* 计算本班每门课的总成绩计算本班每门课的总成绩和平均成绩 和平均成绩 */ */ { { int iint i ,, j; j; float sum[3]={0}float sum[3]={0} ,, aver[3]; aver[3]; for(i=0;i<NU;p++for(i=0;i<NU;p++ ,, i++) i++) for(j=0;j<3;j++) for(j=0;j<3;j++) sum[j]=sum[j]+p-> score[j]; /*sum[j]=sum[j]+p-> score[j]; /* 学生成绩累加求和学生成绩累加求和 */ */ for(j=0;j<3;j++) for(j=0;j<3;j++)

上一页 下一页 返回

Page 50: 第  9  章  结构体及其应用

9.4 9.4 结构体应用实例结构体应用实例 aver[j]=sum[j]/3; /*aver[j]=sum[j]/3; /* 分别计算每门课的平均成绩分别计算每门课的平均成绩 */*/ printf("\t\t printf("\t\t 本班成绩信息统计本班成绩信息统计 \n"); \n"); printf("\t printf("\t 数学总成绩:数学总成绩: %7.1f%7.1f ,平均成绩:,平均成绩: %5.1f \n"%5.1f \n" ,, sum[0]sum[0] ,, aver[0]);aver[0]); printf("\t printf("\t 物理总成绩:物理总成绩: %7.1f%7.1f ,平均成绩:,平均成绩: %5.1f \n"%5.1f \n" ,, sum[1]sum[1] ,, aver[1]);aver[1]); printf("\t printf("\t 化学总成绩:化学总成绩: %7.1f%7.1f ,平均成绩:,平均成绩: %5.1f \n"%5.1f \n" ,, sum[2]sum[2] ,, aver[2]);aver[2]); printf("--------------------------------------------------------------\n"); printf("--------------------------------------------------------------\n"); } } void main() void main() { { struct student stu[NU]; struct student stu[NU];

上一页 下一页 返回

Page 51: 第  9  章  结构体及其应用

9.4 9.4 结构体应用实例结构体应用实例 scan (stu); /*scan (stu); /* 调用函数调用函数 scan ()scan () ,输入学生信息并计算平均成绩,输入学生信息并计算平均成绩*/ */ print(stu); /*print(stu); /* 调用函数调用函数 print()print() ,输出学生成绩单,输出学生成绩单 */ */ average(stu); /*average(stu); /* 调用函数调用函数 average()average() ,计算并输出全班的平,计算并输出全班的平均成绩均成绩 */ */ } } 程序测试时以 程序测试时以 3 3 个学生为例,即 个学生为例,即 NU=3NU=3 ,运行结果为: ,运行结果为:

上一页 返回

Page 52: 第  9  章  结构体及其应用

9.5 9.5 本章小结本章小结 通过本章学习,读者应掌握以下内容: 通过本章学习,读者应掌握以下内容: (( 11 )结构体类型的概念。把多个不同类型的数据组合在一起表示)结构体类型的概念。把多个不同类型的数据组合在一起表示一个对象时,可以用结构体类型实现。 一个对象时,可以用结构体类型实现。 (( 22 )结构体变量、结构体数组、结构体指针的定义与使用。结构)结构体变量、结构体数组、结构体指针的定义与使用。结构体变量一般不能整体引用,需要引用到成员,结构体成员与普通变量体变量一般不能整体引用,需要引用到成员,结构体成员与普通变量的用法相同。 结构体成员有 的用法相同。 结构体成员有 3 3 种引用形式,例如: 种引用形式,例如: struct date struct date { int year{ int year ,, monthmonth ,, day;}dday;}d ,, *p=&d; *p=&d; ① ① 用结构体变量名的引用形式: 用结构体变量名的引用形式: d.year d.month d.day d.year d.month d.day

下一页 返回

Page 53: 第  9  章  结构体及其应用

9.5 9.5 本章小结本章小结 ② ② 用结构体指针变量的引用形式: 用结构体指针变量的引用形式: (*p).year (*p).month (*p).day (*p).year (*p).month (*p).day p->year p->month p->day p->year p->month p->day (( 33 )结构体类型作函数参数。实参为结构体类型数据时,形参也)结构体类型作函数参数。实参为结构体类型数据时,形参也应该是同结构的结构体类型。 应该是同结构的结构体类型。 (( 44)链表。链表是一种动态存储结构,可根据需要动态地开辟存)链表。链表是一种动态存储结构,可根据需要动态地开辟存储空间,随时释放不再需要的存储空间。链表的基本操作有创建链表,储空间,随时释放不再需要的存储空间。链表的基本操作有创建链表,输出链表,在链表中插入新结点,删除链表中的废弃结点。 输出链表,在链表中插入新结点,删除链表中的废弃结点。 (( 55 )用结构体类型解决实际问题的方法。 )用结构体类型解决实际问题的方法。

上一页 返回

Page 54: 第  9  章  结构体及其应用

9.6 9.6 实 训实 训 实 训 实 训 1 1 【实训内容】结构体程序设计。 【实训内容】结构体程序设计。 【实训目的】使用结构体编写程序,解决简单问题 【实训目的】使用结构体编写程序,解决简单问题 【实训题目】下面程序的功能是计算某日在本年中是第几天。阅读【实训题目】下面程序的功能是计算某日在本年中是第几天。阅读程序并上机调试。 程序并上机调试。 【编程点拨】 【编程点拨】 (( 11 )定义一个结构体变量(包括年、月、日)解决日期的存储问题。)定义一个结构体变量(包括年、月、日)解决日期的存储问题。 (( 22 )判断输入的年份是否是闰年,因为闰年的 )判断输入的年份是否是闰年,因为闰年的 2 2 月是 月是 29 29 天。 天。 (( 33 )计算用户输入的月份之前的天数,这些月份都是整月的。 )计算用户输入的月份之前的天数,这些月份都是整月的。 (( 44 )将整月的天数和当前日子加上就是我们要计算的天数)将整月的天数和当前日子加上就是我们要计算的天数。 。

下一页 返回

Page 55: 第  9  章  结构体及其应用

9.6 9.6 实 训实 训 #include "stdio.h" #include "stdio.h" struct birthday struct birthday { { int year; int year; int month; int month; int day; int day; }; }; main() main() { { struct birthday td; struct birthday td; int iint i ,, sum=0; sum=0; int a[13]={0int a[13]={0 ,, 3131 ,, 2828 ,, 3131 ,, 3030 ,, 3131 ,, 3030 ,, 3131 ,, 3131 ,, 3030 ,,3131 ,, 3030 ,, 31}; 31};

上一页 下一页 返回

Page 56: 第  9  章  结构体及其应用

9.6 9.6 实 训实 训

printf("printf(" 请输入年份:请输入年份: "); "); scanf("%d"scanf("%d" ,, &td.year); &td.year); printf("printf(" 请输入月份:请输入月份: "); "); scanf("%d"scanf("%d" ,, &td.month); &td.month); printf("printf(" 请输入日期:请输入日期: "); "); scanf("%d"scanf("%d" ,, &td.day); &td.day); printf("printf(" 您输入的日期是:您输入的日期是: %d−%d−%d"%d−%d−%d" ,, td.yeartd.year ,, td.montd.monthth ,, td.day); td.day); if(td.year%4==0&&td.year%100!=0||td.year%400==0) if(td.year%4==0&&td.year%100!=0||td.year%400==0) a[2]=29; a[2]=29; for(i=1;i<td.month;i++) for(i=1;i<td.month;i++) sum=sum+a[i]; sum=sum+a[i]; sum=sum+td.day; sum=sum+td.day; printf("printf(" 这是今年的第这是今年的第 %d%d 天天 "" ,, sum); sum); } }

上一页 下一页 返回

Page 57: 第  9  章  结构体及其应用

9.6 9.6 实 训实 训 实 训 实 训 2 2 【实训内容】结构体程序设计。 【实训内容】结构体程序设计。 【实训目的】使用结构体数组编写程序,解决实际问题。 【实训目的】使用结构体数组编写程序,解决实际问题。 【实训题目】编写程序,输入 【实训题目】编写程序,输入 10 10 个职工的职工号、姓名、性别、个职工的职工号、姓名、性别、基本工资、奖金、水电费,计算每个人的实发额(基本工资基本工资、奖金、水电费,计算每个人的实发额(基本工资 ++ 奖金−奖金−水电费) ,输出实发额最高和最低的职工的姓名和实发额。 水电费) ,输出实发额最高和最低的职工的姓名和实发额。 【编程点拨】 【编程点拨】 (( 11 )定义一个结构体数组解决数据存储问题。 )定义一个结构体数组解决数据存储问题。 (( 22 )将程序分成 )将程序分成 3 3 个部分,第一部分完成数据输入,同时计算出个部分,第一部分完成数据输入,同时计算出每个职工的实发额;第二部分完成实发额最高和最低的计算,并记录每个职工的实发额;第二部分完成实发额最高和最低的计算,并记录下它们在数组中的下标。 下它们在数组中的下标。 (( 33 )根据数组的下标输出实发额最高和最低的职工的姓名和实发)根据数组的下标输出实发额最高和最低的职工的姓名和实发额。 额。

上一页 下一页 返回

Page 58: 第  9  章  结构体及其应用

9.6 9.6 实 训实 训 实 训 实 训 3 3 【实训内容】结构体程序设计。 【实训内容】结构体程序设计。 【实训目的】使用结构体指针编写程序,解决复杂问题。 【实训目的】使用结构体指针编写程序,解决复杂问题。 【实训题目】仿照【例 【实训题目】仿照【例 9−59−5 】完成学生期末考试成绩输入,成绩单】完成学生期末考试成绩输入,成绩单输出(包括学生的平均成绩、总成绩、名次) ,假定这三门课分别为输出(包括学生的平均成绩、总成绩、名次) ,假定这三门课分别为物理、数学、化学,主程序已经给出,请将其他子函数补充完整。 物理、数学、化学,主程序已经给出,请将其他子函数补充完整。 【编程点拨】 【编程点拨】 (( 11 )定义一个结构体数组解决数据存储问题,当然成员中应该有)定义一个结构体数组解决数据存储问题,当然成员中应该有表示总成绩、平均成绩、名次的成员。 表示总成绩、平均成绩、名次的成员。 (( 22 )将程序分成若干个模块,每个模块完成一个或者多个功能,)将程序分成若干个模块,每个模块完成一个或者多个功能,用函数来实现每个模块,函数的参数使用结构体数组的地址。 用函数来实现每个模块,函数的参数使用结构体数组的地址。 (( 33 )学生平均成绩和总成绩可以在输入的时候同时计算,名次计)学生平均成绩和总成绩可以在输入的时候同时计算,名次计算方法较多,但是计算复杂,适宜单写一个函数完成;查询可以根据算方法较多,但是计算复杂,适宜单写一个函数完成;查询可以根据学号或者姓名,如果使用字符型变量就要使用到字符串比较函数。 学号或者姓名,如果使用字符型变量就要使用到字符串比较函数。

上一页 下一页 返回

Page 59: 第  9  章  结构体及其应用

9.6 9.6 实 训实 训 #include "stdio.h" #include "stdio.h" #include "conio.h" #include "conio.h" #include "string.h" #include "string.h" #define NU 35 /*#define NU 35 /* 学生总数学生总数 */ */ struct student struct student { { long num; /*long num; /* 定义成员变量,存储学生学号定义成员变量,存储学生学号 */ */ char name[10]; /*char name[10]; /* 定义成员变量,存储学生姓名定义成员变量,存储学生姓名 */ */ float score[3]; /*float score[3]; /* 定义成员变量,存储学生定义成员变量,存储学生 33 门课的成绩门课的成绩 */ */ float aver_person; /*float aver_person; /* 定义成员变量,存储学生平均成绩定义成员变量,存储学生平均成绩 */ */ float sum_person; /*float sum_person; /* 定义成员变量,存储学生总成绩定义成员变量,存储学生总成绩 */ */ int order; /*int order; /* 定义成员变量,存储学生总成绩名次定义成员变量,存储学生总成绩名次 */ */ }; };

上一页 下一页 返回

Page 60: 第  9  章  结构体及其应用

9.6 9.6 实 训实 训 print(struct student *pprint(struct student *p ,, int cx_num) /*int cx_num) /* 根据学号输出个人成根据学号输出个人成绩单绩单 */ */ { { 补充函数体 补充函数体 } } calc_order(struct student *p) /*calc_order(struct student *p) /* 计算每个学生的总成绩排名计算每个学生的总成绩排名 */ */ { { 补充函数体 补充函数体 } } scan(struct student *p) /*scan(struct student *p) /* 输入学生数据同时计算个人的平均成输入学生数据同时计算个人的平均成绩和总成绩绩和总成绩 */ */ { { 补充函数体 补充函数体

上一页 下一页 返回

Page 61: 第  9  章  结构体及其应用

9.6 9.6 实 训实 训 } } main() main() { { struct student stu[NU]; struct student stu[NU]; int xuehao; int xuehao; scan (stu); /*scan (stu); /* 输入学生信息,计算平均成绩和总成绩输入学生信息,计算平均成绩和总成绩 */ */ calc_order(stu); /*calc_order(stu); /* 计算每个学生总成绩的排名计算每个学生总成绩的排名 */ */ do do { { printf("printf(" 输入要查询的学生的学号输入要查询的学生的学号 (( 输入输入 00 表示结束表示结束 )) :: "); "); scanf("%d"scanf("%d" ,, &xuehao); &xuehao); print(stuprint(stu ,, xuehao); xuehao); }while(xuehao!=0); }while(xuehao!=0); } }

上一页 返回

Page 62: 第  9  章  结构体及其应用

习 题 习 题 99

9−1 9−1 定义一个结构体类型,用来描述一个职工的基本信息(包括职定义一个结构体类型,用来描述一个职工的基本信息(包括职工号、姓名、性别、出生年月日、工资、职务) 。 工号、姓名、性别、出生年月日、工资、职务) 。 9−2 9−2 写出下面程序的运行结果。 写出下面程序的运行结果。 (( 11 ) ) struct stu struct stu { { int x; int x; int *y; int *y; }*p; }*p; int dt[4]={10,20,30,40}; int dt[4]={10,20,30,40}; struct stu a[4]={50,&dt[0],60,&dt[1],70,&dt[2],80,&dt[3]}; struct stu a[4]={50,&dt[0],60,&dt[1],70,&dt[2],80,&dt[3]}; main() main() {{

下一页 返回

Page 63: 第  9  章  结构体及其应用

习 题 习 题 99

p=a; p=a; printf("%d,",++p->x); printf("%d,",++p->x); printf("%d,",(++p)->x ); printf("%d,",(++p)->x ); printf("%d\n",++(*p->y)); printf("%d\n",++(*p->y)); } } (( 22 ) ) main() main() { { struct struct { { int x; int x; int y; int y; }d[2]={{1,2},{2,7}}; }d[2]={{1,2},{2,7}}; printf("%d\n",d[0].y/d[0].x*d[1].x); printf("%d\n",d[0].y/d[0].x*d[1].x); } }

上一页 下一页 返回

Page 64: 第  9  章  结构体及其应用

习 题 习 题 99

9−3 9−3 假设有 假设有 6 6 名学生,每个学生的基本信息都包括姓名,性别,名学生,每个学生的基本信息都包括姓名,性别,电话号码。编写程序,输出所有女生的信息。 电话号码。编写程序,输出所有女生的信息。 9−4 9−4 两个链表 两个链表 a a 和 和 bb ,假设结点中包括学号、姓名,编写程序从 ,假设结点中包括学号、姓名,编写程序从 a a 链表中删除与 链表中删除与 b b 链表中相同学号的那些结点。 链表中相同学号的那些结点。

上一页 返回

Page 65: 第  9  章  结构体及其应用

图 图 9-19-1

返回

Page 66: 第  9  章  结构体及其应用

图 图 9-29-2

返回

Page 67: 第  9  章  结构体及其应用

图 图 9-39-3

返回

Page 68: 第  9  章  结构体及其应用

图 图 9-49-4

返回

Page 69: 第  9  章  结构体及其应用

图 图 9-59-5

返回

Page 70: 第  9  章  结构体及其应用

图 图 9-69-6

返回

Page 71: 第  9  章  结构体及其应用

图 图 9-79-7

返回