第六章课后习题
6.1 求学生平均成绩
题目概述:
一个班有 10 个学生的成绩,要求输人这 10 个学生的成绩,然后求出它们的平均成绩
题目思路:
- 本题只要知道数组怎么用就能做出本题
代码实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
float sum = 0.0;
int i = 0;
float arr[10] = {0.0};
for (i = 0; i < 10; i++)
{
scanf("%f", &arr[i]);
}
for (i = 0; i < 10; i++)
{
sum += arr[i];
}
printf("%.2f", sum / 10);
return 0;
}
6.2 6.1中找出成绩最高
题目概述:
在上题基础上求出平均成绩最高的课程(以课程序号表示)及其成绩。
讲真这道题我不知道他在问什么?他要求平均成绩最高的课程,但是上题我们求的是每个学生单科成绩的平均成绩而不是平均成绩中最高的课程???所以我不明白他在问什么,求解答。
6.3 找出最高成绩的同学
题目概述:
已知一个班 10 个学生的成绩,存放在一个一维数组中,要求找出其中成绩最高的学生的成绩和该生的序号。
题目思路:
- 这道题只需要在6.1的基础上修改一下即可,我们假设最高分的就是第一个同学,然后循环类比只要有比他高的就把最高分的分数赋值给他即可
代码实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
float sum = 0.0;
int i = 0;
float arr[10] = {0.0};
float max = 0.0;
for (i = 0; i < 10; i++) //输入数据
{
scanf("%f", &arr[i]);
}
for (i = 0; i < 10; i++) //开始比较
{
if (arr[i] > max)
{
max = arr[i];
}
}
printf("%d\n", i);
printf("%.2f", arr[i - 1]);
return 0;
}
6.4 求平均成绩
题目概述:
有 3 个学生,上4门课,要求输入全部学生的各门课成绩,并分别求出每门课的平均成绩。
题目思路:
- 首先本题说明了有3名学生,上四门课,我们要存放每一位学生的课程成绩,用二维数组是最好的
- 我们用i代表学生,j代表课程,遍历数组输入数据,本题代码部分提供了一组输入数据,便于运行时无需自行输入
- 输入完数据后,我们要算平均成绩,就要把每一个学生的当科成绩加起来再除以3,
- 我们只需要固定j不变,j不变就代表一直都是当科的成绩,只需要循环遍历i就能得到三个考生在同一门课程的成绩总和,用不同的变量存放,最后在输出时除以3就能得到平均成绩
代码实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
/*
94 78 87 96
66 87 75 69
100 98 89 77
提供一组输入数据
*/
int main()
{
int i = 0;
int j = 0;
float sum_a = 0.0;
float sum_b = 0.0;
float sum_c = 0.0;
float sum_d = 0.0;
float arr[3][4] = { 0.0 };
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
scanf("%f", &arr[i][j]);
}
}
for (i = 0; i < 3; i++)
{
sum_a += arr[i][0];
sum_b += arr[i][1];
sum_c += arr[i][2];
sum_d += arr[i][3];
}
printf("first average:%.2f\n", sum_a / 3);
printf("second average:%.2f\n", sum_b / 3);
printf("third average:%.2f\n", sum_c / 3);
printf("forth average:%.2f\n", sum_d / 3);
return 0;
}
优化:
- 后面我发现上段代码是可以优化的,我们可以创建1个4*4的数组,当i=4时,用来存放平均成绩
- 这样就可以优化第二段循环代码,我们固定j不变,可以用嵌套循环先循环j再循环i,如下,这样代码会比上端代码更加灵活。
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
/*
94 78 87 96
66 87 75 69
100 98 89 77
提供一组输入数据
*/
int main()
{
int i = 0;
int j = 0;
float sum = 0.0;
float arr[4][4] = { 0.0 };
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
scanf("%f", &arr[i][j]);
}
}
for (j = 0; j < 4; j++)
{
sum = 0.0;
for (i = 0; i < 3; i++)
{
sum += arr[i][j];
}
arr[3][j] = sum / 3;
printf("%d average:%.2f\n", j + 1, arr[3][j]);
}
return 0;
}
运行结果如下:
6.5 求平均成绩排名
题目概述:
已知5 个学生的4 门课的成绩,要求求出每个学生的平均成绩,然后对平均成绩从高到低将各学生的成绩记录排序(成绩最高的学生的排在数组最前面的行,成绩最低的学生的排在数组最后面的行)。
题目思路:
- 本题较为复杂,需要先计算出平均成绩然后还要进行排序,所以本题会分为两个部分
- 算出平均成绩
- 排序
Part 1:算出平均成绩
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
float arr[5][4] = { {94,78,87,76},{66,87,75,69},{100,98,89,77},{92,58,72,84},{82,73,67,54} };
int i = 0;
int j = 0;
float sum = 0;
int max = 0;
float average[5] = { 0.0 };
for (i = 0; i < 5; i++)
{
sum = 0.0;
for (j = 0; j < 4; j++)
{
sum += arr[i][j];
}
average[i] = sum / 4;
}
for (i = 0; i < 5; i++)
{
printf("%.2f", average[i]);
printf("\n");
}
return 0;
}
运行结果如下:
Part 2:对平均成绩进行排序
本题排序我们用选择排序法,而且是从大到小的选择排序法。
既然用选择排序法,那么选择排序法是什么呢?(以从大到小为例),具体的讲解可以看看别人的从小到大的排序法,我这边是基于从小到大的排序法对本题进行变种
- 选择排序的基本思想是,首先,选出最大的数,放在第一个位置;然后再选出第二小的数,放在第二个位置,再选出第三小的数,放在第三个位置,以此类推。直到所有的数从大到小排序。
- 很明显,要实现选择排序,必须要用到循环。
代码如下:
//选择排序
sz = sizeof(average) / sizeof(average[0]); //算出average的元素个数
for (i = 0; i < sz; i++)
{
max = i;//假设i是最大值下标
//找出最大值的数组下标
for (j = 1 + i; j < sz - 1; j++) //这个解释有点长,详情请看①解释
{
if (average[j] > average[max])
{
max = j; //如果发现arr[j]中的值比arr[max]大,就记录最大值的下标
}
}
//找出最大值下标后,赋值
if (i != max)
{
temp = average[max];
average[max] = average[i];
average[i] = temp;
}
}
for (i = 0; i < 5; i++)
{
printf("%.2f", average[i]);
printf("\n");
}
return 0;
}
- ①由于我们已经假设了i是最大的,也就是arr[0]是最大值,那么j应该从1开始,但是我们每次循环完之后,会把最大值赋给数组最前面的下标,那么等下一趟的时候,其实第一个元素不需要再遍历了,所以j要在+1的基础上再加上一个i,如果我解释的不明白的话可以看看下面的图解
图解实现:
PS:绿色为固定不变的数字,橙色为该趟排序的一开始假定最大值,红色为该趟排序中找到的最大值
第一趟,选择排序
i = 0时
- 忘记改了,记录数组下标,把j赋给max,下同
第二趟选择排序,i=1
- 看表格中的绿色部分,因为经过第一趟选择排序后,遍历了整个数组记录了数组中的最大值,那么91分是整个数组的最大值,这个毋庸置疑,所以在第二趟选择排序的时候,arr[0]就不参与这一次乃至后面的排序了,只需要对剩下四个数组元素排序他们的大小即可
第三趟选择排序,i=2
最后一趟不演示了
最终代码实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main()
{
float arr[5][4] = { {94,78,87,76},{66,87,75,69},{100,98,89,77},{92,58,72,84},{82,73,67,54} };
int i = 0;
int j = 0;
float sum = 0;
float average[5] = { 0.0 };
//选择排序需要用到的变量
float temp = 0;
int max = 0;
int sz = 0;
//计算平均值
for (i = 0; i < 5; i++)
{
sum = 0.0;
for (j = 0; j < 4; j++)
{
sum += arr[i][j];
}
average[i] = sum / 4;
}
//选择排序
sz = sizeof(average) / sizeof(average[0]); //算出average的元素个数
for (i = 0; i < sz; i++)
{
max = i;//假设i是最大值下标
//找出最大值的数组下标
for (j = 1 + i; j < sz - 1; j++)
{
if (average[j] > average[max])
{
max = j; //如果发现arr[j]中的值比arr[max]大,就记录最大值的下标
}
}
//找出最大值下标后,赋值
if (i != max)
{
temp = average[max];
average[max] = average[i];
average[i] = temp;
}
}
for (i = 0; i < 5; i++)
{
printf("%.2f", average[i]);
printf("\n");
}
return 0;
}
运行结果如下: