心之所向,素履以往,终至所归
今天学校发了几道题,而这道题罕见的在CSDN里找不到,同时题本身对刚学结构体的同学,也有一定难度所以想和大家分享一下我的一点心得。
6-3 评委打分-n
分数 10
单位 武汉理工大学
题目描述
学校进行新生知识竞赛,最终n名同学进入决赛(n<=20)。为此,学生会邀请了7名德高望重的老教授与10名学生组成的大众评委一起作为评委。同时,也请学习了c语言的你帮忙编写一个程序,将评委给出的成绩,去掉一个最高分,去掉一个最低分后,计算出各位选手的最终得分,并按排名显示。
为方便提取每个学生信息,你设计了一个结构体类型Score,包含学生的编号(id)、姓名(name,不超过10个字符),并以一维数组value存储17名评委给出的成绩,同时将计算出的选手获得的最终成绩finalScore、比赛排名rank也作为成员记录到该结构体中,方便选手查询自己的名次。
定义一个一维数组grade存储10位学生成绩。
需要完成的函数功能为:
GetScore(struct Score grade[], int n): 读入17个评委给出的n个学生成绩;
CalcuScore(struct Score grade[], int n): 计算n个学生的最终成绩finalScore;
Ranking(struct Score grade[], int n):依据最终成绩finalScore,计算出学生当前排名,赋给结构体成员rank;
PrintScore(struct Score grade[], int n): 每行按照 “姓名 编号 第i名 最终成绩”的格式打印所有选手名次。每两部分之间一个空格,最终成绩按6列保留2位小数输出
struct Score { //成员包括学生编号、姓名、评分、总成绩、排名
};
void GetScore( struct Score grade[], int n );
void CalcuScore(struct Score grade[], int n);
void Ranking(struct Score grade[], int n);
void PrintScore(struct Score grade[], int n);
其中,grade[]
和n
都是主调函数传入的参数。grade[]
是结构体数组,n
是选手人数,不超过20。
#include
struct Score { //成员包括学生编号、姓名、评分、总成绩、排名
};
void GetScore( struct Score grade[], int n );
void CalcuScore(struct Score grade[], int n);
void Ranking(struct Score grade[], int n);
void PrintScore(struct Score grade[], int n);
int main()
{
int n;
scanf("%d", &n); //确定参加的选手人数
struct Score grade[20];
GetScore(grade, n);
CalcuScore(grade, n);
Ranking(grade, n);
PrintScore(grade, n);
return 0;
}
/* 请在这里填写答案 */
10
20001 Sandy 82 79 87 64 82 75 72 94 80 94 66 82 95 98 83 83 64
20002 Andy 95 65 83 95 93 65 72 86 66 75 84 73 85 74 84 60 68
20003 Kimmy 90 68 60 98 64 81 84 81 68 74 69 100 64 96 88 86 78
20004 Sussan 82 76 89 65 65 88 90 93 62 95 64 64 80 88 69 65 89
20005 Ryan 93 65 97 80 91 92 92 99 65 91 79 96 100 95 66 85 91
20006 Jone 74 67 68 94 84 86 91 86 63 62 71 96 92 68 74 96 63
20007 Tom 75 78 98 61 100 66 97 88 72 83 97 82 71 67 60 75 60
20008 Pokky 85 73 72 88 81 74 97 81 69 77 66 92 83 78 73 71 68
20009 Adolph 94 92 81 67 80 92 74 72 81 90 88 67 95 67 84 88 77
20010 Scolt 92 93 88 70 60 85 98 97 66 97 61 97 82 65 74 73 67
第1名 20005 Ryan 87.47
第2名 20009 Adolph 81.80
第3名 20001 Sandy 81.20
第4名 20010 Scolt 80.47
第5名 20003 Kimmy 79.27
第6名 20006 Jone 78.47
第7名 20007 Tom 78.00
第8名 20002 Andy 77.87
第9名 20004 Sussan 77.80
第10名 20008 Pokky 77.67
代码长度限制16 KB
时间限制400 ms
内存限制64 MB
首先必须要说的一点是这道题本身就有bug!!!
请看第四个自定义函数要求:
很明显这两者的格式根本不一样!!!!!
而AC的条件则是以样例为准,方法也很简单只需要把样例复制粘贴过去然后把数值所在位置改为对应占位符即可,其实不止这到题,很多题也都最好这样,可以有效防止因为格式过不了。
循环输入即可,而且因为要输入17个人的评分,所以最好再嵌套一个循环
当然你想写17个占位符也是可以的,只是会看着有点冗长。
void GetScore(struct Score grade[], int n)
{
for (int i = 0; i < n; i++) // 每次输入一个同学的所有信息
{
scanf("%d %s", &grade[i].num, grade[i].name);
for (int j = 0; j < 17; j++) //此处是用于17个评委分数的输入
scanf("%d", &grade[i].value[j]);
getchar();
}
}
第二个函数是让你算每个人的平均得分,而且是弃掉一个最高分和一个最低分
那我们当然想到用排序,这里我用的是排序是双指针模式的快排,不了解的可以用冒泡,插入,选择等替代,总之就让17个评委打出的成绩排好顺序,(当然还有个原始方法,用一次循环找到最大最小值,同时也计算所有值的和,最后一减,)
void CalcuScore(struct Score grade[], int n)
{
for (int i = 0; i < n; i++)
{
grade[i].sum = 0;
QuickSort(grade[i].value, 0, 16);
for (int j = 1; j < 16; j++)
grade[i].sum += grade[i].value[j];
grade[i].sum /= 15;
}
}
我是把快排又为封装了两个函数,如下;
void swap(int* a, int* b)
{
int c = *a;
*a = *b; //用于交换数值
*b = c;
}
void QuickSort(int* arr, int begin, int end) //快排的实现
{
int front = begin + 1, behind = begin, key = begin;
if (begin < end)
{
while (front <= end)
{
while (arr[front] > arr[key] && front <= end)
front++;
if (front <= end)
{
swap(&arr[front], &arr[behind + 1]);
behind++;
front++;
}
}
swap(&arr[key], &arr[behind]);
key = behind;
QuickSort(arr, begin, key - 1);
QuickSort(arr, key + 1, end);
}
}
第二个函数的冒泡排序实现如下:
void CalcuScore(struct Score grade[], int n)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < 16; j++)
{
int flag = 0;
for (int z = 0; z < 16-j; z++)
{
double t;
if (grade[i].value[z] > grade[i].value[z + 1])
{
t = grade[i].value[z];
grade[i].value[z] = grade[i].value[z + 1];
grade[i].value[z + 1] = t;
flag = 1;
}
}
if (flag == 0)
break;
}
}
for (int i = 0; i < n; i++)
{
double sum = 0;
for (int j = 1; j < 16; j++)
sum += grade[i].value[j];
grade[i].finalScore = sum / 15;
}
}
第三个其实有个取巧的方法,你只需要把选手按照从成绩高到成绩低来排好序就OK了
如果是和我一个学校的那么请看看你们的这个题目集的6-1,以他为原型稍加改造就可是实现
这个我还是用的冒泡排序(不得不说,冒泡排序对新手真的很友好,真的建议都了解一下)。
void Ranking(struct Score* address, int N)
{
for (int i = 0; i < N - 1; i++)
{
for (int j = 0; j < N - 1 - i; j++)
if (address[j].sum- address[j + 1].sum< 0)
{
struct Score a = address[j];
address[j] = address[j + 1];
address[j + 1] = a;
}
}
}
记得吗我们要给选手们排出名次,题目本意是让我们在结构体中加个存储排名的变量,
but!!我们第三个函数已经给他们排好了顺序,所以只需要将它们一次打印出来就是答案,
至于排名,请看下图的“i+1”,没错!它就是排名,惊不惊喜?意不意外?
为什么是“i+1”不是“i”,别忘了,下标从零开始的。
void PrintScore(struct Score grade[], int n)
{
for (int i = 0; i < n; i++) //看“i+1”
printf("第%d名 %d %s %.2lf\n",i+1,grade[i].num,grade[i].name,grade[i].sum);
}
ok,至此四个函数大功告成啦,
恭喜你能坚持看完,一时半会理解不了也很正常,一个函数一个函数慢慢消化就好。
struct Score {
int num;
char name[20];
int value[20];
double sum;
int rank;
};
void Ranking(struct Score* address, int N)
{
for (int i = 0; i < N - 1; i++)
{
for (int j = 0; j < N - 1 - i; j++)
if (address[j].sum- address[j + 1].sum< 0)
{
struct Score a = address[j];
address[j] = address[j + 1];
address[j + 1] = a;
}
}
}
void swap(int* a, int* b)
{
int c = *a;
*a = *b;
*b = c;
}
void QuickSort(int* arr, int begin, int end)
{
int front = begin + 1, behind = begin, key = begin;
if (begin < end)
{
while (front <= end)
{
while (arr[front] > arr[key] && front <= end)
front++;
if (front <= end)
{
swap(&arr[front], &arr[behind + 1]);
behind++;
front++;
}
}
swap(&arr[key], &arr[behind]);
key = behind;
QuickSort(arr, begin, key - 1);
QuickSort(arr, key + 1, end);
}
}
void GetScore(struct Score grade[], int n)
{
for (int i = 0; i < n; i++)
{
scanf("%d %s", &grade[i].num, grade[i].name);
for (int j = 0; j < 17; j++)
scanf("%d", &grade[i].value[j]);
getchar();
}
}
void CalcuScore(struct Score grade[], int n)
{
for (int i = 0; i < n; i++)
{
grade[i].sum = 0;
QuickSort(grade[i].value, 0, 16);
for (int j = 1; j < 16; j++)
grade[i].sum += grade[i].value[j];
grade[i].sum /= 15;
}
}
void PrintScore(struct Score grade[], int n)
{
for (int i = 0; i < n; i++)
printf("第%d名 %d %s %.2lf\n",i+1,grade[i].num,grade[i].name,grade[i].sum);
}
struct Score {
int id;
char name[20];
double value[17];
double finalScore;
int rank;// 成员包括学生编号、姓名、评分、总成绩、排名
};
void GetScore(struct Score grade[], int n)
{
for (int i = 0; i < n; i++)
{
scanf("%d", &grade[i].id);
scanf("%s", grade[i].name);
for (int j = 0; j < 17; j++)
scanf("%lf", &grade[i].value[j]);
}
}
void CalcuScore(struct Score grade[], int n)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < 17; j++)
{
int flag = 0;
for (int z = 0; z < 16; z++)
{
double t;
if (grade[i].value[z] > grade[i].value[z + 1])
{
t = grade[i].value[z];
grade[i].value[z] = grade[i].value[z + 1];
grade[i].value[z + 1] = t;
flag = 1;
}
}
if (flag == 0)
break;
}
}
for (int i = 0; i < n; i++)
{
double sum = 0;
for (int j = 1; j < 16; j++)
sum += grade[i].value[j];
grade[i].finalScore = sum / 15;
}
}
void Ranking(struct Score grade[], int n)
{
for (int i = n - 1; i >= 0; i--)
{
int flag = 0;
for (int j = n - 1; j > n - 1 - i; j--)
{
struct Score t;
if (grade[j].finalScore > grade[j - 1].finalScore)
{
t = grade[j];
grade[j] = grade[j - 1];
grade[j - 1] = t;
flag = 1;
}
}
if (flag == 0)
break;
}
for (int i = 0; i < n; i++)
grade[i].rank = i + 1;
}
void PrintScore(struct Score grade[], int n)
{
for (int i = 0; i < n; i++)
printf("第%d名 %d %s %.2lf\n", grade[i].rank, grade[i].id, grade[i].name, grade[i].finalScore);
}
我是一名非计科的编程爱好者,如果你也喜欢编程,那么与君共勉!
我之前也有一点基础知识的博客,想了解的同学可以看看哦
【如何正确使用外部变量和函数(文件包含与extern的使用) - CSDN App】http://t.csdnimg.cn/u8OsI
【while——do while——for 分支与循环的使用方法即注意事项(包括continue等关键字的使用) - CSDN App】http://t.csdnimg.cn/sh0Su
谢谢观看
觉得有用的话就点个免费的赞吧,