第 9 章 结构
9.1 教学要点
本章主要介绍结构的基本概念与定义(含嵌套结构)、结构变量的定义和使用、结构数 组的应用、结构指针的概念和使用等知识。其中,重点介绍结构的定义与成员引用方式、结 构数组的应用、结构指针的基本概念与使用,而嵌套结构的定义、结构指针作为函数参数是 难点。
9.1 节通过综合示例程序“输出平均分最高的学生信息”,引出结构的概念和主要知识点,
教师在讲授时,先介绍和分析该示例程序的总体框架结构,结合程序把各知识点引出即可,
不需要对源代码进行详细分析,可以让学生课后自己细读。然后重点介绍结构的概念,并与 数组进行对比,并举例说明结构定义(包括嵌套结构)的具体方法。结构变量主要介绍定义、
初始化以及使用方式。在介绍结构变量的定义时,要举例讲解三种定义方式。介绍结构变量 初始化时,要讲清楚结构变量数据在内存中的存储情形。在介绍结构变量的使用时,重点介 绍三种情况:结构成员引用方式、相同类型结构变量的相互赋值、结构变量作为函数参数。
9.2 节通过示例程序“学生成绩排序”,介绍结构数组的概念、定义、初始化、成员引用 以及应用编程。要结合示例重点向学生讲清楚结构数组的概念以及结构数组成员的引用方式。
9.3 节通过示例程序“修改学生成绩”,重点介绍结构指针的概念,以及通过结构指针变 量间接访问数据的方式,特别是通过对比介绍结构指针指向运算符“->”的使用方法。此外,
还要结合示例详细介绍结构指针作为函数参数的使用方法,并分析其特点。
讲授学时:4 学时,实验学时同讲授学时。
本章的知识能力结构图见图9.1。
图 9.1 知识能力结构图 结构定义
(含嵌套结构 )
结 构
结构变量
结构数组
结构指针
定义方式 初始化 变量使用
结构成员引用
结构变量赋值 结构变量作为 定义 函数参数
初始化 数组成员引用
结构指针 指向操作
结构指针作为 函数参数
能 够 根 据 实 际 情 况 合理定义结构
能 够 使 用 结 构 变 量 与 结 构 数 组 进 行 熟 练编程
掌 握 结 构 指 针 的 操作,并应用于函 数参数传递
9.2 讲稿
1
Chap 9 结构
9.1 输出平均分最高的学生信息 9.2 学生成绩排序
9.3 修改学生成绩
本章分3 节。
通过示例程序引导的方式分别介绍结构 相关的知识。
2
本章要点
n什么是结构?结构与数组有什么差别?
n有几种结构的定义形式,它们之间有什么不同?
n什么是结构的嵌套?
n什么是结构变量和结构成员变量?如何引用结构成 员变量?
n结构变量如何作为函数参数使用?
n什么是结构数组?如何定义和使用结构数组?
n什么是结构指针?它如何实现对结构分量的操作?
n结构指针是如何作为函数的参数的?
提出本章的学习要点。
3
9.1输出平均分最高的学生信息
9.1.1 程序解析
9.1.2 结构的概念与定义 9.1.3 结构的嵌套定义
9.1.4 结构变量的定义和初始化 9.1.5 结构变量的使用
通过示例程序“输出平均分最高的学生信 息”,介绍结构的概念与一般定义方式,
结构的嵌套定义方法,结构变量的定义、
初始化和使用。
4
9.1.1 程序解析
例9-1 输出平均分最高的学生信息
n假设学生的基本信息包括学号、姓名、三 门课程成绩以及个人平均成绩。输入n 个 学生的成绩信息, 计算并输出平均分最高 的学生信息。
介绍示例程序“输出平均分最高的学生信 息”。
在课堂上无需详细的代码分析,只要运行 演示该程序,并分析程序的整体结构和结 构相关语句即可,可以让学生在课后自己 认真细读此示例程序。
5
9.1.1 程序解析
#include<stdio.h>
struct student{ /* 学生信息结构定义 */
int num; /* 学号 */
char name[10]; /* 姓名 */
int computer, english, math; /* 三门课程成绩 */
double average; /* 个人平均成绩 */
};
展示结构类型的定义。
6
int main(void) { int i, n;
struct student s1,max; /* 定义结构变量 */
printf("Input n: ");
scanf("%d", &n);
printf("Input the student’s number, name and course scores\n");
for(i = 1; i <= n; i++){
printf("No.%d: ", i);
scanf("%d%s%d%d%d",&s1.num,s1.name,&s1.math,&s1.english,&s1.c omputer);
s1.average=(s1.math+ s1.english+ s1.computer) / 3.0;
if(i == 1) max = s1; /* 结构变量 操作 */
if(max.average < s1.average) max = s1;
}
printf("num:%d, name:%s, average:%.2lf\n", max.num, max.name, max.average);
return 0;
}
介绍程序中结构变量的定义与使用语句。
结构的概念和相关定义语法规则在后面 展开介绍。
7
9.1.2 结构的概念与定义
n使用结构来表示学生信息:
struct student{
int num; /* 学号 */
char name[10]; /* 姓名 */
int computer, english, math; /* 三门课程成绩 */
double average; /* 个人平均成绩 */
};
n结构是C语言中一种新的构造数据类型,它能够 把有内在联系的不同类型的数据统一成一个整体,
使它们相互关联
n结构又是变量的集合,可以按照对基本数据类型 的操作方法单独使用其变量成员。
结构与数组比较:
•都是构造类型,是多个变 量的集合
•数组成员类型相同,结构 成员类型不同
介绍结构的概念,指出:结构是C 语言中
一种新的构造数据类型,能够将不同类型 的数据统一成一个整体,每个成员都是一 个变量,可以单独操作。
分析结构与数组的区别:数组成员类型必 须相同,而结构成员类型可以不同。
8
9.1.2 结构的概念与定义
n结构类型定义的一般形式为:
struct struct
结构名结构名{
{ 类型名
类型名结构成员名1结构成员名1;; 类型名
类型名结构成员名结构成员名2;
2
;•
••••• 类型名
类型名结构成员名结构成员名n;
n
;};
}; 束,C束,结构的定义以分号结结构的定义以分号结C语言中把结构的语言中把结构的 定义看作是一条语句 定义看作是一条语句 关键字struct和它后面 的结构名一起组成一个
新的数据类型名
要说清楚结构类型定义中各部分的含义。
关键字 struct 和它后面的结构名一起组 成一个新的数据类型名。
结构的定义以分号结束,C 语言中把结构 的定义看作是一条语句。
9
9.1.2 结构的概念与定义
n例如,平面坐标结构:
struct point {
float x;
float y;
};
•虽然x、y的类型相同,也 可以用数组的方式表示,
但采用结构进行描述,更 贴近事物本质,从而增加 了程序的可读性,使程序 更易理解
••结构比较适合用于描述具结构比较适合用于描述具 有多个属性的实体或对象 有多个属性的实体或对象
举例说明结构的定义,并对比分析采用结 构方式来描述事物,表述更加准确,更贴 近事物本质,从而增强程序的可读性,易 于理解。
进一步分析和总结什么情况下更适合用 结构来描述事物。
10
9.1.3 结构的嵌套定义
n在我们的实际生活中,一个较大的实体可能由多 个成员构成,而这些成员中有些又有可能是由一 些更小的成员构成。
n在学生信息中可以再增加一项:“通信地址”,
它又可以再划分为:城市、街道、门牌号、邮政 编码。
学号 姓名
通信地址
计算机 英语 数学 平均 城市 街道 门牌号 邮编 成绩
举例说明什么情况下需要使用嵌套的结 构。
11
9.1.3 结构的嵌套定义
n由此,我们可以对其结构类型进行如下重 新定义:
struct address{
char city[10];
char street[20];
int code;
int zip;
};
struct nest_student{
int num;
char name[10];
struct addressaddr;
int computer, english, math;
double average;
};
•在定义嵌套的结构类型时,必须先定义 成员的结构类型,再定义主结构类型。
需要特别提醒学生,在定义嵌套的结构类 型时,必须先定义成员的结构类型,再定 义主结构类型。
12
9.1.4 结构变量的定义和初始化
n在C语言中定义结构变量的方式有三种:
1.单独定义:先定义一个结构类型,再定义一个具 有这种结构类型的变量
struct student{
int num; /* 学号 */
char name[10]; /* 姓名 */
int computer, english, math; /* 三门课程成绩 */
double average; /* 个人平均成绩 */
};
struct students1,s2;
介绍结构变量定义的三种方式。
特别指出struct student 是类型名,student 是结构名,s1、s2 是结构变量名。
13
9.1.4结构变量的定义和初始化
2. 混合定义:在定义结构类型的同时定义结构变量
struct student{int num; /* 学号 */
char name[10]; /* 姓名 */
int computer, english, math; /* 三门课程成绩 */
double average; /* 个人平均成绩 */
}s1, s2;
3. 无类型名定义:在定义结构变量时省略结构名
struct {int num; /* 学号 */
char name[10]; /* 姓名 */
int computer, english, math; /* 三门课程成绩 */
double average; /* 个人平均成绩 */
} s1, s2;
要给学生分析一下,第2 种和第 3 种定义
方式的差别,即省略结构名的定义方式具 有一定的局限性。
14
9.1.4结构变量的定义和初始化
n结构变量的初始化
struct student s1 = {101, "Zhang", 78, 87, 85};
介绍结构变量的初始化格式。
分析初始化后,结构变量数据在内存中的 存放情况。
15
9.1.5 结构变量的使用
1. 结构变量成员的引用
n 在C语言中,使用结构成员操作符“.”来引用结 构成员,格式为:
结构变量名
.
结构成员名s1.num = 101;
strcpy(s1.name, "Zhang");
nest_s1.addr.zip = 310015;
介绍结构成员运算符“.”的使用方式,并
举例说明。
16
9.1.5 结构变量的使用
2. 结构变量的整体赋值
n 具有相同类型的结构变量可以直接赋值。
赋值时,将赋值符号右边结构变量的每一 个成员的值都赋给了左边结构变量中相应 的成员。
struct student s1= {101, "Zhang", 78, 87, 85}, s2;
s2 = s1;
特别指出:只有具有相同类型的结构变量 才可以相互赋值,并说明赋值后的效果。
17
9.1.5 结构变量的使用
3. 结构变量作为函数参数
n 如果一个C程序的规模较大,功能较多,必然需 要以函数的形式进行功能模块的划分和实现
n 如果程序中含有结构数据,则就可能需要用结 构变量作为函数的参数或返回值,以在函数间 传递数据。
n 例:
double count_average( struct student s );
main():s1.average = count_average ( s1 );
特点:可以传递多个数据 且参数形式较简单 缺点:对于成员较多的大
型结构,参数传递时所 进行的结构数据复制使 得效率较低
说明结构变量作为函数参数的可能和必 要性。
分析结构变量作为函数参数的优缺点。
18
9.2 学生成绩排序
n9.2.1 程序解析
n9.2.2 结构数组操作
通过示例程序“学生成绩排序”介绍结构 数组相关的知识。
19
9.2.1 程序解析
例9-2 输入n(n<50)个学生的成绩信息,按照学生的 个人平均成绩从高到低输出他们的信息。
struct student students[50], temp; /* 定义结构数组 */
/* 输入 */
…
介绍示例程序功能
运行演示程序,介绍总体流程 介绍结构数组students 的定义语句
说明该示例程序中借用了例 9-2 中的自定
义函数 count_average(),并介绍其调用方 式
20
9.2.1 程序解析
/* 结构数组排序,选择排序法*/
for( i = 0; i < n-1; i++ ){
index = i;
for (j = i+1; j <n; j++ )
if (students[j].average > students[index].average) /* 比较平均成绩*/
index = j;
temp = students[index]; /* 交换数组元素 */
students[index] = students[i];
students[i] = temp;
}
/* 输出排序后的信息 */
printf("num\t name\t average\n");
for (i = 0; i < n; i++ )
printf("%d\t%s\t %.2lf\n", students[i].num, students[i].name, students[i].average);
简要介绍结构数组的排序 简要介绍结构数组元素的输出
21
n 一个结构变量只能表示一个实体的信息,
如果有许多相同类型的实体,就需要使用 结构数组。
n 结构数组是结构与数组的结合,与普通数 组的不同之处在于每个数组元素都是一个 结构类型的变量。
9.2.2 结构数组操作
介绍结构数组的概念。
结构数组是结构与数组的结合,每个数组 元素都是一个结构类型的变量。
结构数组可以用于描述多个相同结构类 型的个体。
22
n 结构数组的定义方法与结构变量类似 struct student students[50];
结构数组students,它有50个数组元素,从 students[0]到students[49],每个数组元素 都是一个结构类型struct student的变量
9.2.2 结构数组操作
结构数组的定义格式。
结构数组中每个数组元素都是一个结构 变量,每个变量又都包含多个成员。
23
9.2.2 结构数组操作
n 结构数组的初始化 struct student students[50] = {
{ 101,"zhang", 76, 85, 78 }, {102, "wang", 83, 92, 86} };
students[0] 101 Zhang 76 85 78 students[1] 102 Wang 83 92 86
… … … … … …
students[49]
介绍结构数组的初始化方式。
分析初始化后,结构数组数据在内存中的 存放情况。
24
n 结构数组元素的成员引用 ,其格式为:
结构数组名
[下标] . 结构成员名
n 使用方法与同类型的变量完全相同:
students[i].num = 101;
strcpy(students[i].name, "zhang");
students[i] = students[k]
9.2.2 结构数组操作
结合示例介绍结构数组元素的成员引用 方法。
说明:一个结构数组元素就是一个结构变 量。
25
9.3 修改学生成绩
9.3.1 程序解析 9.3.2 结构指针的概念 9.3.3 结构指针作为函数参数
通过示例程序“修改学生成绩”介绍结构 指针的概念、操作方式、结构指针作为函 数参数等知识。
26 介绍示例程序功能要求
运行演示程序,介绍程序的主流程 重点说明自定义函数 update_score()的功 能,以及结构数组 students 作为其实参的 情况
27
9.3.1程序解析
/* 自定义函数,修改学生成绩 */
int update_score(struct student *p, int n, int num, int course, int score) {
int i,pos;
for(i = 0; i < n; i++, p++) /* 按学号查找 */
if(p->num== num) break;
if(i < n) /* 找到,修改成绩 */
{
switch(course){
case 1: p->math = score; break;
case 2: p->english = score; break;
case 3: p->computer = score; break;
}
pos = i; /* 被修改学生在数组中的下标 */
}
else /* 无此学号 */
pos = -1;
return pos;
}
重点介绍自定义函数 update_score()的形
参,以及通过结构指针p 对结构数组内容
进行访问和操作情况
28
9.3.2结构指针的概念
n指针可以指向任何一种变量,而结构变量 也是C语言中的一种合法变量,因此,指 针也可以指向结构变量,这就是结构指针。
n结构指针就是指向结构类型变量的指针
结构指针的概念:结构指针就是指向结构 类型变量的指针。
9.3.1
9-3 n(n<50)
29
9.3.2结构指针的概念
struct student s1 = {101, "zhang", 78, 87, 85}, *p;
p = &s1;
101 zhang 78 87 85
P
介绍结构指针的定义和赋值
结构图示说明结构指针赋值后的指向情 况
30
9.3.2结构指针的概念
n结构指针的使用
n(1) 用*p访问结构成员。如:
(*p).num = 101;
n(2) 用指向运算符“->”访问指针指向的结构成 员。如:
p->num = 101;
当p指向结构变量s1时,下面 三条语句的效果是一样的:s1.num = 101;
(*p).num = 101;
p->num = 101;
介绍如何使用结构指针对指向的数据进 行操作。
重点介绍运算符“->”的使用方法。
对不同的结构指针使用方式进行比较。
31
9.3.3结构指针作为函数参数
n结构指针的操作是非常灵活的,如果将结构 指针作为函数的参数,可以完成比基本类型 指针更为复杂的操作。
n例9-3 main():
pos = update_score(students, n, num, course, score);
自定义函数:
int update_score(struct student *p, int n, int num, int course, int score)
函数update_score运行完 毕返回主函数后,主函数 中的结构数组students中 的值已被修改
结合例 9-3,详细分析结构指针作为函数
参数的编程方法。包括形参如何书写,实 参如何设定,参数传递含义。
要特别指出:函数 update_score 运行完毕 返 回 主 函 数 后 , 主 函 数 中 的 结 构 数 组 students 中的成员值已经被结构指针通过 间接访问的方式修改了。
32
9.3.3结构指针作为函数参数
n与结构变量作为函数参数相比,用结构指针作为 函数参数的效率更高。
n就例9- 3 而言, 在函数updat e_s cor e( ) 中需要 修改主函数中结构数组s t udent s 的数据,根据第 8章介绍的知识,在此处也只能使用指针作为函数 参数的方式才能通过间接访问操作来实现程序功 能。
与结构变量作为函数参数进行比较,总结 结构指针作为函数参数的特点和优势。
说明:为实现例9-3 修改学生成绩的功能,
不能采用结构变量作为函数参数的方式,
而只能用结构指针作为函数参数的方式。
33 回顾和总结本章的教学要点,提出能力要 求。
9.3 练习与习题参考答案
9.3.1 练习参考答案
9-1 定义一个能够表示复数的结构类型,一个复数包括实数与虚数两个部分。
解答:
struct complex{
float real;
float imaginary;
};
9-2 人的出生日期由年、月、日组成,请在例 9-1 中的学生信息结构中增加一个成员:出生 日期,用嵌套定义的方式重新定义该结构类型。
解答:
struct date{
int year;
int month;
int day;
};
struct nest_student{
int num;
char name[10];
struct date birthday; /* 定义出生日期 */
int computer, english, math;
double average;
};
9-3 例9-1中,如果要计算的是三门课程的课程平均分, 应该如何改写程序?
解答:
int main(void) {
int i, n;
!
!
"
"
"
!
"
!
"
"
"
•
•
•
double math_ave, english_ave, computer_ave;
struct student s1; /* 定义结构变量 */
printf("Input n: ");
scanf("%d", &n);
printf("Input the student’s number, name and course scores\n”);
math_ave = english_ave = computer_ave = 0;
for(i = 1; i <= n; i++){
printf("No.%d: ", i);
scanf("%d%s%d%d%d",&s1.num,s1.name,&s1.math,&s1.english,&s1.computer);
math_ave = s1.math;
english_ave = s1.english;
computer_ave = s1.computer;
}
printf("math_ave:%.2lf, english_ave:%.2lf, computer_ave:%.2lf\n", math_ave, english_ave, computer_ave);
return 0;
}
9-4 定义一个包含 5 名学生信息的结构数组,并对该结构数组的所有元素进行初始化。
解答:
struct student{
int num;
char name[10];
int computer, english, math;
double average;
};
struct student s[5]={{30101, "张一",69,75,84 },{30132, "李二",80,85,90},{40231, "王三
",71,91,74},{40754, "赵四",65,76,87},{50426, "刘五",81,92,73}};
9-5 参考例 9-2,输入并保存 10 个学生的成绩信息,分别输出平均成绩最高和最低的学生 信息。
解答:
#include<stdio.h>
struct student{ /*学生信息结构定义*/
int num; /* 学号 */
char name[10]; /* 姓名 */
int computer, english, math ; /* 三门课程成绩 */
double average; /* 个人平均成绩 */
};
struct student students[10]; /* 定义结构数组 */
int main(void) { int i, max,min;
/* 输入 10 个学生的记录*/
for(i = 0; i < 10; i++){
printf("No %d: ", i+1);
scanf("%d%s%d%d%d", & students[i].num, students[i].name, &students[i].math,
&students[i].english, &students[i].computer);
students[i].average=(students[i].math+students[i].english+students[i].computer)/3.0;
}
/* 查找平均成绩最高、最低分学生的数组下标值 */
max=min=0;
for( i = 1; i < 10; ++i ){
if(students[i].average > students[max].average) max=i;
if(students[i].average < students[min].average) min=i;
}
/*输出平均成绩最高和最低的学生信息*/
printf("最 高 分 学 生 信 息 : 学 号 :%d,姓 名 :%s,数 学 :%d,英 语 :%d,计 算 机 :%d,平 均 分 :%.2lf \n", students[max].num, students[max].name, students[max].math, students[max].english, students[max].computer, students[max].average);
printf("最 低 分 学 生 信 息 : 学 号 :%d,姓 名 :%s,数 学 :%d,英 语 :%d,计 算 机 :%d,平 均 分 :%.2lf \n", students[min].num, students[min].name, students[min].math, students[min].english, students[min].computer, students[min].average);
return 0;
}
9-6 定义一个 struct student 类型的结构指针,用其实现一个学生信息的输入和输出。
解答:
struct student{ /*学生信息结构定义*/
int num; /* 学号 */
char name[10]; /* 姓名 */
int computer, english, math ; /* 三门课程成绩 */
double average; /* 个人平均成绩 */
}s, *p;
p = &s;
scanf("%d%s%d%d%d", &p->num, p->name, &p->math, &p->english, &p->computer);
9-7 改写例 9-3 中的函数 update_score(),将第一个形参改为结构数组形式。
解答:
int update_score(struct student s[ ], int n, int num, int course, int score) {
int i,pos;
for(i = 0; i < n; i++) /* 按学号查找 */
if(s[i].num == num) break;
if(i < n) /* 找到,修改成绩 */
{
switch(course){
case 1: s[i].math = score; break;
case 2: s[i].english = score; break;
case 3: s[i].computer = score; break;
}
pos = i; /* 被修改学生在数组中的下标 */
}
else /* 无此学号 */
pos = -1;
return pos;
}
9.3.2 习题参考答案
一 、 选 择 题
1 2 3 4 5
D B C B A
二 、 填 空 题
1. 成员(分量) 指向 2. stud[i].name
3. &time.hour, &time.minute, &time.second
time.second time.minute++ time.hour == 24 4. 1 2 A B
5. 23, wang, 98.5, wang
三 、 程 序 设 计
1.时间换算:用结构类型表示时间内容(时间以时、分、秒表示),输入一个时间数值,
再输入一个秒数 n(n<60),以 h:m:s 的格式输出该时间再过 n 秒后的时间值(超过 24 点就 从 0 点开始计时)。试编写相应程序。
解答:
#include <stdio.h>
int main(void) {
int n;
int repeat, ri;
struct time{
int hour, minute, second;
}time;
scanf("%d:%d:%d", &time.hour, &time.minute, &time.second);
scanf("%d",&n);
time.second += n;
if(time.second >= 60){
time.minute += time.second / 60;
time.second %= 60;
if(time.minute >= 60){
time.hour += time.minute / 60;
time.minute %= 60;
if(time.hour >= 24) time.hour %= 24;
} }
if(time.hour<10) printf("0%d:",time.hour);
else printf("%d:",time.hour);
if(time.minute<10) printf("0%d:",time.minute);
else printf("%d:",time.minute);
if(time.second<10) printf("0%d",time.second);
else printf("%d",time.second);
return 0;
}
2.计算两个复数之积:编写程序,利用结构变量求解两个复数之积。
提示:求解(a1+a2i)×(b1+b2i),乘积的实部为:a1×b1 - a2×b2,虚部为:a1×b2 + a2×b1。
解答:
#include <stdio.h>
struct complex{
int real;
int imag;
};
struct complex multiply(struct complex x, struct complex y) { struct complex product;
product.real = x.real * y.real - x.imag * y.imag;
product.imag = x.real * y.imag + x.imag * y.real;
return product;
}
int main(void) {
struct complex product, x, y;
scanf("%d%d%d%d", &x.real, &x.imag, &y.real, &y.imag);
product = multiply(x, y);
printf("(%d+%di) * (%d+%di) = %d + %di\n", x.real, x.imag, y.real, y.imag, product.real, product.imag);
return 0;
}
3.平面向量加法:输入两个二维平面向量 V1=(x1, y1)和 V2=(x2, y2)的分量,计算并输出 两个向量的和向量。试编写相应程序。
解答:
#include <stdio.h>
struct vector{
double x;
double y;
};
int main(void)
{
struct vector v1, v2;
double a,b;
scanf("%lf%lf%lf%lf", &v1.x, &v1.y, &v2.x, &v2.y);
a= v1.x+ v2.x;
b= v1.y+v2.y;
if(a>0)
a=(int)((a+0.05)*10);
else
a=(int)((a-0.05)*10);
a=a/10.0;
if(b>0)
b=(int)((b+0.05)*10);
else
b=(int)((b-0.05)*10);
b=b/10.0;
printf("(%.1f, %.1f)\n",a,b);
return 0;
}
4.查找书籍:从键盘输入 10 本书的名称和定价并存入结构数组中,从中查找定价最高和最 低的书的名称和定价,并输出。试编写相应程序。
解答:
#include<stdio.h>
#define NUMBER 10 struct book
{ char name[30];
float price;
};
int main() {
int i,maxl,minl,n;
struct book test[NUMBER];
scanf("%d",&n);
for(i=0; i<n; i++){
getchar();
gets(test[i].name);
scanf("%f",&test[i].price);
}
if(n<=0) return 0;
maxl=minl=0;
for(i=1; i<n; i++)
{ if(test[maxl].price<test[i].price) maxl=i;
if(test[minl] .price >test[i].price) minl=i;
}
printf("%.2f, %s\n", test[maxl].price, test[maxl].name);
printf("%.2f, %s\n", test[minl].price, test[minl].name);
return 0;
}
5.通信录排序:建立一个通讯录,通信录的结构记录包括:姓名、生日、电话号码,其中 生日又包括三项:年、月、日。编写程序,定义一个嵌套的结构类型,输入 n(n<10)个联系 人的信息,再按他们的年龄从大到小的顺序依次输出其信息。试编写相应程序。
解答:
#include<stdio.h>
struct date{
int y, m, d ; };
struct friends_list{
char name[10];
struct date birthday;
char phone[15];
};
int main(void) { int i, n;
struct friends_list friends[10];
void sort(struct friends_list s[], int n);
scanf("%d", &n);
for(i=0; i<n; i++)
scanf("%s%d%d%d%s", friends[i].name, &friends[i].birthday.y, &friends[i].birthday.m,
&friends[i].birthday.d, friends[i].phone);
/*fill_b*/
sort(friends, n);
/*fill_n*/
for(i=0;i<n;i++)
printf("%s %d %s\n", friends[i].name, friends[i].birthday.y*10000+
friends[i].birthday.m*100+ friends[i].birthday.d, friends[i].phone);
return 0;
}
void sort(struct friends_list s[], int n) { int i, j;
long b1, b2;
struct friends_list temp;
for(i=1; i<n; i++)
for(j=0; j<n-i; j++){
b1 = s[j].birthday.y*10000+ s[j].birthday.m*100+ s[j].birthday.d;
b2 = s[j+1].birthday.y*10000+ s[j+1].birthday.m*100+ s[j+1].birthday.d;
if( b1 > b2)
{temp=s[j]; s[j]=s[j+1]; s[j+1]=temp; } }
}
6.按等级统计学生成绩:输入 10 个学生的学号、姓名和成绩,输出学生的成绩等级和不及 格人数。每个学生的记录包括学号、姓名、成绩和等级,要求定义和调用函数 set_grade(),
根据学生成绩设置其等级,并统计不及格人数,等级设置:85~100 为 A,70~84 为 B,60~69 为 C,0~59 为 D。试编写相应程序。
解答:
/* 设置学生成绩等级并统计不及格人数(结构指针作为函数参数) */
#include<stdio.h>
#define N 10 struct student{
int num;
char name[20];
int score;
char grade;
};
int set_grade(struct student *p);
int main(void)
{ struct student stu[N], *ptr;
int i, count;
ptr = stu;
printf("Input the student's number, name and score: \n");
for(i = 0; i < N; i++){
printf("No %d: ", i+1); /* 提示输入第 i 个同学的信息 */
scanf("%d%s%d", &stu[i].num, stu[i].name, &stu[i].score);
}
count = set_grade(ptr);
printf("The count (<60): %d\n", count);
printf("The student grade:\n");
for(i = 0; i < N; i++)
printf("%d %s %c\n", stu[i].num, stu[i].name, stu[i].grade);
return 0;
}
int set_grade(struct student *p) {
int i, n = 0;
for(i = 0; i < N; i++, p++){
if(p->score >= 85) p->grade = 'A';
else if(p->score >= 70)
p->grade = 'B';
else if(p->score >= 60) p->grade = 'C';
else{
p->grade = 'D';
n++;
} } return n;
}
9.4 实验指导教材参考答案
一 、 调 试 示 例
计算职工工资:输入一个正整数 n(3≤n≤10),再输入 n 个职员的信息(表 9.1),要
求 输 出 每 位 职 员 的 姓 名 和 实 发 工 资 ( 实 发 工 资=基本工资+浮动工资-支出)。(源程序 error09_1.c)
表9.1 工资表
姓名 基本工资 浮动工资 支出
zhao 240.00 400.00 75.00 qian 360.00 120.00 50.00 zhou 560.00 150.00 80.00
错误行号: 10 正确语句: struct emp s[10];
错误行号: 16 正确语句: scanf("%s%f%f%f", s[i].name, &s[i].jbgz, &s[i].fdgz, &s[i].zc);
二 、 基 础 编 程 题
(1)时间换算:用结构类型表示时间内容(时间以时、分、秒表示),输入一个时间数值,
再输入一个秒数n(n<60),以 h:m:s 的格式输出该时间再过 n 秒后的时间值(超过 24 点就从 0 点开始计时)。试编写相应程序。
解答:参见习题程序设计第1 题
(2)计算平均成绩:建立一个学生的结构记录,包括学号、姓名和成绩。输入整数 n(n<10),
再输入n 个学生的基本信息,要求计算并输出他们的平均成绩(保留 2 位小数)。试编写相应
程序。
解答:
#include<stdio.h>
struct student{ /*学生信息结构定义*/
int num; /* 学号 */
char name[10]; /* 姓名 */
int score; /* 成绩 */
};
int main(void) {
int i, n;
double ave=0;
struct student s1; /* 定义结构变量 */
printf("n=");
scanf("%d", &n);
for(i = 1; i <= n; i++){
scanf("%d%s%d",&s1.num,s1.name,&s1.score);
ave += s1.score;
}
ave = ave/n;
printf("%.2lf\n", ave);
return 0;
}
(3)计算两个复数之积:利用结构变量求解两个复数之积,输入复数的实部与虚部都为整 数。试编写相应程序。
解答:参见习题程序设计第2 题
(4)查找书籍:从键盘输入 n(n<10)本书的名称和定价并存入结构数组中,从中查找定价最
高和最低的书的名称和定价,并输出。试编写相应程序。
解答:参见习题程序设计第4 题
(5)按等级统计学生成绩:输入 10 个学生的学号、姓名和成绩,输出学生的成绩等级和不
及格人数。每个学生的记录包括学号、姓名、成绩和等级,要求定义和调用函数set_grade(),
根据学生成绩设置其等级,并统计不及格人数,等级设置:85~100 为 A,70~84 为 B,60~69 为C,0~59 为 D。试编写相应程序。
解答:参见习题程序设计第6 题
三 、 改 错 题
找出总分最高的学生:建立一个有 n(3<n≤10)个学生成绩的结构记录,包括学号、
姓名和3 门成绩,输出总分最高学生的姓名和总分。(源程序 error09_2.cpp)
错误行号: 8 正确语句: }student[10];
错误行号: 14 正确语句: student[i].sum=0;
错误行号: 24 正确语句: max=student[i].sum;
四 、 拓 展 编 程 题
(1)通信录排序:通信录的结构记录包括:姓名、生日、电话号码,其中生日又包括三项:
年、月、日。定义一个嵌套的结构类型,输入n(n<10)个联系人的信息,再按他们的年龄从
大到小的顺序依次输出其信息。试编写相应程序。
解答:参见习题程序设计第5 题
(2)有理数比较:编写函数 CompareRational,比较两个有理数的大小。该函数参数为两个
有理数(结构类型)。若第一个有理数小于第二个,返回-1;若相等,返回 0;若第一个有
理数大于第二个,则返回 1。编写程序,接受用户输入的两对整数,分别组成两个有理数,
并调用上述函数进行比较,输出比较结果。试编写相应程序。
解答:
#include<stdio.h>
struct rational{ /*有理数结构定义*/
int num;
int deno;
};
int CompareRational(struct rational r1, struct rational r2){
double a,b;
a=1.0*r1.num/r1.deno;
b=1.0*r2.num/r2.deno;
if(a>b) return 1;
else if(a==b) return 0;
else return -1;
}
int main(void) {
struct rational r1,r2;
char ch;
int n;
scanf("%d/%d", &r1.num, &r1.deno);
scanf("%d/%d", &r2.num, &r2.deno);
n= CompareRational(r1, r2);
if(n==1) ch=’>’;
else if(n==0) ch=’=’;
else ch=’<’;
printf("%d/%d %c %d/%d\n", r1.num, r1.deno, ch, r2.num, r2.deno);
return 0;
}
(3)平面向量加法:输入两个二维平面向量 V1=(x1, y1)和 V2=(x2, y2)的分量,计算并输出两 个向量的和向量。试编写相应程序。
解答:参见习题程序设计第3 题