C语言每日一练
2021年11月24日
文章目录
- 题目描述
- 问题分析
- 代码实现
- 运行结果
题目描述
用c语言编写软件完成以下任务:一批选手参加比赛,比赛的规则是最后得分越高,名次越低。当半决赛结束时,要在现场按照选手的出场顺序宣布最后得分和最后名次,获得相同分数的选手具有相同的名次,名次连续编号,不用考虑同名次的选手人数。
例如:
选手序号: 1,2,3,4,5,6,7
选手得分: 5,3,4,7,3,5,6
输出名次为:3,1,2,5,1,3,4
问题分析
题目中要求编写的程序能实现将选手按照分数高低进行排序,又可以根据选手的入场顺序进行排序,对于这种多属性的对象,最好的处理方法便是使用结构体,定义一个结构体struct player
,重定义命名为PLAYER
(重定义的目的是免去重复写struct
的麻烦),该结构体需要三个成员变量:num
(出场编号),score
(比赛得分)和rank
(排名)。
//参赛选手结构体
typedef struct player
{
int num; //出场编号
int score; //总分
int rank; //排名
}PLAYER;
选手的编号可以直接通过一个循环进行顺序赋值(也可以在定义结构体时进行初始化),得分可以手动输入,也可以使用生成随机数的方法(该方法的详细介绍可以看我第61天的练习题),选手的排名需要参考他们的比赛得分,题目要求得分相同的排名也相同,且排名需要连续(比如有两个第一名,那么第三个人就是第二名,而不是第三名)。
我的代码主要包括3个重要的步骤:
- 根据分数对选手进行排序,分数低的排名靠前
第一步,在选手已经得出成绩的情况下(成绩由随机函数生成),调用函数
void Sort_By_Score(PLAYER *players, int len)
该函数会将参赛选手(结构体数组)按照他们分数的高低进行排序,需要注意的是题目要求分数越低的排名越高,该函数排序使用了冒泡排序。 - 获取每个选手的排名,分数相同的排名并列
第一步已经将分数最低的选手排在结构体数组最前面,分数最高的选手放到了数组最后。所以这时只需要对每个成员顺序地分配排名值,唯一需要注意的是,如果两个选手分数相同,那么他们名次也相同。该功能在代码中对应的函数为:
void Get_Ranking(PLAYER *player, int len)
- 将选手按照出场编号重新排列
和第一步类似,只不过现在是按照选手的出场编号对结构体数组进行排序,该功能在代码中对应的函数为:
void Sort_By_Num(PLAYER *players, int len)
该函数用到了选择排序。
代码实现
核心步骤:
- 给选手结构体数组分配编号1~n
- 使用随机函数生成选手的成绩1~10
- 根据分数对选手进行排序,分数低的排名靠前
- 获取每个选手的排名,分数相同的排名并列
- 将选手按照出场编号重新排列
- 依据选手的编号顺序打印他们的成绩和排名
#include <stdio.h>
#include <stdlib.h> //srand()/rand()
#include <time.h> //time()
#define PLAYER_NUMBER 6 //参赛人数
//参赛选手结构体
typedef struct player
{
int num; //出场编号
int score; //总分
int rank; //排名
}PLAYER;
/******************************************************************************
* @brief 根据选手的分数对选手进行排序(使用冒泡排序)
* @param players 选手结构体成员
* @param len 选手结构体数组长度
******************************************************************************/
void Sort_By_Score(PLAYER *players, int len)
{
int i = 0, j = 0;
PLAYER tmp;
//冒泡排序
for(i = 0; i < len - 1; i++)
{
for(j = 0 ; j < len - i - 1; j++)
{
if(players[j].score > players[j + 1].score)
{
tmp = players[j];
players[j] = players[j + 1];
players[j + 1] = tmp;
}
}
}
}
/******************************************************************************
* @brief 根据选手成绩确定选手的排名(分数低的排在前面)
* @param players 选手结构体成员
* @param len 选手结构体数组长度
******************************************************************************/
void Get_Ranking(PLAYER *player, int len)
{
int i = 0, rank = 1;
player[0].rank = rank; //第一名
for(i = 1; i < len; i++) //第二至第len-1名
{
//如果分数与上一名不同,则排名加1,否则排名相同
if(player[i].score != player[i - 1].score)
rank++;
player[i].rank = rank;
}
}
/******************************************************************************
* @brief 根据选手的出场编号对选手进行排序(使用选择排序)
* @param players 选手结构体成员
* @param len 选手结构体数组长度
******************************************************************************/
void Sort_By_Num(PLAYER *players, int len)
{
int i = 0, j = 0;
PLAYER tmp;
//选择排序
for(i = 0; i < len - 1; i++)
{
for(j = i + 1; j < len; j++)
{
if(players[i].num > players[j].num)
{
tmp = players[i];
players[i] = players[j];
players[j] = tmp;
}
}
}
}
int main()
{
int i = 0;
PLAYER players[PLAYER_NUMBER];
//用系统秒数初始化随机数种子
srand((unsigned)time(NULL));
//初始化选手信息
for(i = 0; i < PLAYER_NUMBER; i++)
{
players[i].num = i + 1;
}
//随机生成成员分数
for(i = 0; i < PLAYER_NUMBER; i++)
{
//分数1~10分
players[i].score = rand() % 10 + 1;
}
//根据分数对选手进行排序(分数低的排前面)
Sort_By_Score(players, PLAYER_NUMBER);
//根据分数排序获取选手的排名
Get_Ranking(players, PLAYER_NUMBER);
//根据选手出场编号进行排序
Sort_By_Num(players, PLAYER_NUMBER);
//打印结果
printf("=========================\n");
printf("| 编号\t| 得分\t| 排名\t|\n");
printf("+-----------------------+\n");
for(i = 0; i < PLAYER_NUMBER; i++)
{
printf("| %d\t| %d\t| %d\t|\n", players[i].num,\
players[i].score, players[i].rank);
printf("+-----------------------+\n");
}
return 0;
}