C语言小练习 2 成绩排名问题

  • Post author:
  • Post category:其他


因为最近好多小伙伴问我实验报告五的第1题(熊老师课堂是实验报告六),所以专门来更新一篇博客~

题目是这样哒:

1.成绩排名

假设有五位同学四门功课的成绩如下,现要求得每位同学的总分,并按照总分从高到低的顺序进行排序,输出其名次,如果总分相同,则按语文和数学分数之和高者排前,低者排后,但名次一样。


姓  名


语 文


数 学


英 语


综 合

张大明

120

130

110

280

李小红

110

120

105

290

王志强

108

128

126

278

汪晓成

112

135

122

286

李 丹

100

120

108

276

因为大家还没有学到指针那一章节,所以下面的讲解内容将用数组来代替指针~

首先我们来看看这道题需要实现的功能有哪些:

1、读入所有姓名、科目、成绩信息

2、计算每位同学总分

3、按总分进行排序,若总分相同,按语数和排序

4、输出排名,要求相同分数排名一致

5、输出最终结果

接下来我们先实现第一步:

我们把这个表看做一个二维数组,我们可以把姓名一栏看做为数组的行标,科目一栏看做数组的列标,每一个成绩就是一个数组元素的值

比如李丹的数学成绩就是a[4][1]。(其实想写score[][],做图片的时候做错了,懒得改了╮(╯▽╰)╭)

这样子的话姓名和科目都有一个固定的数字去表示了,但是最后的结果虽然不用输出科目名称,但是需要输出学生姓名,所以我们再单独声明一个name[5]字符串数组,用于存放每个人的姓名,其姓名编号和上图中编号一致。第一步就完成啦。

接下来是第二步,计算每位同学的总分,为了方便总分的存储,所以我们在声明上面那个数组的同时,需要多声明一列,进行存储总分,他的编号就是4啦。

计算时,我们设置一个for循环,每次对每一行进行处理,将每一行的前面四个数的和计算出来放到第五个元素里面去,这样第二步就完成了。

下面是第3步,排序。

排序的方法比较多种多样,我们这里采用选择排序,即每次从前往后进行遍历,遍历到的数分别与后面的数依次比较,只要比后面的数小就和它交换。

但是这是一个二维数组,我们是要对每个同学的所有信息进行排序,所以每次交换需要交换一行。如果依次交换每一个行里的每一个元素,虽然也可以做到,但是会很麻烦,所以在这里为大家介绍在数据库管理中非常常用的索引法。

我们先建立一个索引数组index[5],对它进行循环赋值,使得它的每一个元素的值等于其下标。如果用相同的数字构建它与原来二维数组的关系的话,就可以看做每一个元素指向二维数组的每一行。

我们把index[]的每一个行标当做排名,每一个元素的值所代表的数字代表每一个人的姓名,每一个姓名都有其对应的每一个科目的成绩,及一行,那么每一个index[]就可以看做指向每一行的索引或者说指针。交换每一行的时候不必交换整行的数据,只用改变每一个index元素所指向的行就行了,也就是改变每一个下标(排名位置)所对应index的值(指向的行)。

这里要注意两点,一是数组下标是从0开始的,第二的时候是交换行的交换方式,就像指针变量与指针指向变量的值的区别一样,交换交换的是index索引,但是选择排序的比较过程是比较的每一行的总分成绩

总分成绩相等的时候,我们就加入一个if条件,其中的比较项就变成了语文和数学的成绩和,同样根据列下标进行引用就行,也要注意,比较的是成绩a[][]的值,交换的是索引index的值

第四步,因为相同总分虽然顺序不同,但是名词一样,所以我们要用rank排名数组进行处理,下标和名次(值)一样(注意,这里名次要与前面对应,所以是从0开始),在for循环时,遇到两个相同的时候就对此次下标对应的值自减一次。

(后来发现这里还是有缺陷的。。。比如出现三个一样的成绩的时候。。。加一个变量作为计数器,再循环自减计数器次数就行,不过我懒得改了。。。╮(╯▽╰)╭感觉自己好懒呀~)

第五步,循环输出所有信息就好啦~

下面是源代码:

#include<stdio.h>
int main()
{
	int score[5][5]=  //输入成绩 
	{
		{120, 130, 110, 280, 0},
		{110, 120, 105, 290, 0},
		{108, 128, 126, 278, 0},
		{112, 135, 122, 286, 0},
		{100, 120, 108, 276, 0}
	};
	int index[5], rank[5];  //建立索引和排名数组 
	int i,j,temp=0;
	char name[10][10] =  //建立姓名数组 
	{
		{"张大明"},
		{"李小红"},
		{"王志强"},
		{"汪晓成"},
		{"李  丹"} 
	};  
	
	for (i=0; i<=4; i++)  //计算每位同学的总分 
	{
		for(j=0; j<=3; j++)
		    temp += score[i][j];
		score[i][4] = temp;
        temp = 0;
	}
	
	for(i=0; i<=4; i++)
	    index[i] = i;  //初始化索引数组
	
	for(i=0; i<=3; i++)
	{
		for(j=i+1; j<=4; j++)
		{
			if(score[index[i]][4]<score[index[j]][4])  //按总分进行选择排序 
			{
				temp = index[i];
				index[i] = index[j];
				index[j] = temp;
			}
			else if(score[index[i]][4]==score[index[j]][4])  //如果出现总分相同,按语数和排序 
			{
				if((score[index[i]][0]+score[index[i]][1])<(score[index[j]][0]+score[index[j]][1]))
				{
				    temp = index[i];
				    index[i] = index[j];
			     	index[j] = temp;
			    }
			}
			else; 
		}
	}
	
	rank[0] = 1; //初始化排序数组首个元素 
	for(i=1; i<=4; i++)
	{
		rank[i] = i+1;
		if(score[index[i]][4]==score[index[i-1]][4])  //分数成绩相等的将名次一致 
		    rank[i]--;  //注意这里是有缺陷的,如果3个一样就没办法了 
	}                  //加个计数器就好了,但是我懒得改了╮(╯▽╰)╭ 
	
	for(i=0; i<=4; i++)  //输出结果 
	{
		printf("%s", name[index[i]]);
		printf("  total score=%d",score[index[i]][4]);
		printf("  rank:%d\n",rank[i]);
	}
	return 0;
} 



版权声明:本文为xiaomingxiansen原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。