UVA

/*
  这题其实不难,而且很贴近生活啊!等ACM题刷累了的时候,不妨把这个代码再多加些功能,写成一个小小的项目试试,我觉得会挺有意义
  
  体现了的知识点:
  为了避免浮点数的误差,一般在按小数点输入之前,要先将它和一个较小的数EPS(通常用1e-5)相加
  
  打脸了...WA了将近一天,各种调试和找错,整整找了一天,没错,就是整整一天,不是上学的一天,是暑假的一整天,什么都不做专门调这道题的那种一天,好几次都崩溃到想放掉这道题...想着,WA就WA吧,反正真正比赛的时候,应该不会出这种题目
  (这脸打得也太响了,我本来还想着,这道题看思路似乎挺简单,要不就不做了,先自学些数据结构等别的ACM题,结果...太轻视这题了啊!~)
  
  但是想了想,不能这样啊,凡事只有0次和无数次的区别...如果我这次因为一直WA就放弃了,下次就可以因为这个数据结构/算法没学过,这道题太难,这道题一直没思路又没题解根本做不出...等等各种其他的理由放弃掉别的题。要放弃可以有很多理由~可是既然给自己划定了某个目标,就不要畏难,死磕也要磕到底,哪怕是付出再多时间,也一定要磕下来...战线可以拉长,不求在最近就弄明白,可是绝对不能在心里告诉自己:我不管了,太难了,这道题我就是做不出来了...
  
  嗯,对自己还是不能放太多水,平时放的水,最后都会在WA时,变成自己深沉的泪水,hhh~
  
*/


/*
  版本1
  这个题目其实挺好理解,我就不解释我的代码了,来讲讲我究竟是怎么WA的吧!
  
  UVA的输出数据里面,应该有格式或者中西文标点的错误,因为我直接把UVA里面的这句输出复制下来
  
  "Showing the ranklist hurts students’ self-esteem. Don’t do that."
  
  提交代码的时候,就是WA
  
  而我自己敲了这句以后,就只是改了这句,改为
  "Showing the ranklist hurts students' self-esteem. Don't do that."
  
  就AC了...惊不惊喜,意不意外,我会说,没想到还有这个天坑吗! T^T...做这道题一定要注意注意再小心,至少这句话,不要直接从UVA的样例输出里面复制
  (我会说复制,本来就是为了避免出现,中西文标点等看不出差别的问题,UVA的数据居然还这样坑我,真是天坑啊!卒~)
  
  吐槽完毕,上代码...可以说是很艰难的AC了...唉
  (对了,最终真正找到这个bug,还要多亏了命令行的神操作..下次专门写一篇博文讲下,我究竟是怎么发现,错误居然在这里的...最关键的突破点,是因为利用了命令行的txt比较功能)
  
  话说,当时没想到还真的有这个操作,抱着试试的心态随手一搜,居然真的有...搜索引擎可真是个好东西啊!hhhhhhh....(大家多多百度谷歌吧,真的很多时候会有意外的收获呢!)
  
  从此以后,我觉得我就可以借助重定向和这个比较功能,很方便地加各种输出语句来调试了...ohyeah!!~
  
  不知道什么时候能来填(如何利用命令行发现隐藏很深的WA原因)这个坑,就先把这个命令行神操作的网址放着好了
  https://jingyan.baidu.com/article/19020a0a1dd04a529c284272.html
*/

#include <iostream>
#include <iomanip>
#include <string>
#include <cstring>
#include <algorithm>
#include <cstdio>
//#define debug
using namespace std;
const int maxn = 1e5; 
const double EPS = 1e-5;
int n = 0;
int CID, _score[4], sum;
string SID, name, s;
const string course[] = {"Chinese", "Mathematics", "English", "Programming"};
const string words[] = {"Number of students who failed all subjects: ", "Number of students who passed 1 or more subjects: ", "Number of students who passed 2 or more subjects: ", "Number of students who passed 3 or more subjects: ", "Number of students who passed all subjects: "}; 

struct student
{
	int CID, score[5]; // Chinese, Math, English, Programming, total
	bool del;
	double average;
	string name, SID;
}stu[maxn];


void Print_Menu()
{
	cout << "Welcome to Student Performance Management System (SPMS)." << endl << endl << "1 - Add" << endl << "2 - Remove" << endl << "3 - Query" << endl << "4 - Show ranking" << endl << "5 - Show Statistics" << endl << "0 - Exit" << endl << endl; 
}

int valid() // 检查是否合法,如果输入的SID已经输入过了,则该输入不合法,因而不处理该输入 
{
	for (int i = 0; i < n; i++)
	if (!stu[i].del)
	if (stu[i].SID == SID)
	return 0;
	return 1;
}

int Rank (int k)
{
	int cnt = 0;
	for (int i = 0; i < n; i++)
	{
		if ( !stu[i].del && stu[i].score[4] > stu[k].score[4] ) cnt++;
	}
	return cnt + 1;
}

void Add()
{
	while (1)
	{
		sum = 0;
		cout << "Please enter the SID, CID, name and four scores. Enter 0 to finish." << endl;
		cin >> SID;
		if (SID == "0") return;
		cin >> CID >> name;
		for (int i = 0; i < 4; i++)
		{
			cin >> _score[i];
			sum += _score[i];
		}
		if (!valid()) cout << "Duplicated SID." << endl;
		else
		{
			stu[n].SID = SID; stu[n].CID = CID; stu[n].name = name;
			for (int i = 0; i < 4; i++) stu[n].score[i] = _score[i];
			stu[n].score[4] = sum;
			stu[n].average = sum * 1.0 / 4 + EPS;
			stu[n].del = false;
			n++;
		}
	}
}

void Remove()
{
	while (1)
	{
		cout << "Please enter SID or name. Enter 0 to finish." << endl;
		cin >> s;
		if (s == "0") break;
		int cnt = 0;
		for (int i = 0; i < n; i++)
		{
			if ( !stu[i].del && (stu[i].SID == s || stu[i].name == s) )
			{
				stu[i].del = true;
				++cnt;
			}
		}
		cout << cnt << " student(s) removed." << endl;
	}
}

void Query()
{
	while (1)
	{
		cout << "Please enter SID or name. Enter 0 to finish." << endl;
		cin >> s;
		if (s == "0") return;
		for (int i = 0; i < n; i++)
		{
			char c = ' ';
			if ( !stu[i].del && (stu[i].SID == s || stu[i].name == s) )
			{
				cout << Rank(i) << c << stu[i].SID << c << stu[i].CID << c << stu[i].name << c;
				for (int j = 0; j < 5; j++) cout << stu[i].score[j] << c;
				cout << fixed << setprecision(2) << stu[i].average << endl;
			}
		}
	}
}

void Statistics()
{
	cout << "Please enter class ID, 0 for the whole statistics." << endl;
	int cid, i, j, passed, failed, total, cnt, cnt1;
	cin >> cid;
	int p[5]; // p[i]记录通过了i门课程的学生 
	char c;// c == ' '
	memset(p, 0, sizeof(p)); // 每次调用都要清空p,p[i]代表了当前指定的范围的学生中,有p[i]或以上的同学通过了该课程 
	if (!cid) //cid == 0, 0 for the whole statistics,枚举所有学生,不论其班级是什么
	{
		for (int i = 0; i < 4; i++) // 枚举科目 
		{
			passed = 0, failed = 0, total = 0, cnt = 0;
			for (j = 0; j < n; j++)
			{
				if (!stu[j].del) // 枚举没被删除的同学
				{
					cnt++;
					total += stu[j].score[i];
					if (stu[j].score[i] >= 60) passed++;
					else failed++;
				} 
			}
			cout << course[i] << endl << "Average Score: " << fixed << setprecision(2) << (cnt ? total * 1.0 / cnt + EPS : 0) << endl
				 << "Number of passed students: " << passed << endl << "Number of failed students: " << failed << endl << endl;
		}
		
		for (int i = 0; i < n; i++) // 枚举没被删除的学生 
		{
			if (!stu[i].del) 
			{
				cnt1 = 0;
				for (int j = 0; j < 4; j++) // 枚举他上的每门课程,计算多少门及格
				{
					if (stu[i].score[j] >= 60) cnt1++;
				}  
				//更新统计通过i门课(i [0, 4]) 的学生数
				if (!cnt1) p[0]++;
				else
				for (int k = 1; k <= cnt1; k++) p[k]++; 
			}
		}
		cout << "Overall:" << endl;
		for (int i = 4; i >= 0; i--) cout << words[i] << p[i] << endl;
		cout << endl;
	}
	else // 仅找班级号与cid相同的,且没被删除的学生 
	{
		for (int i = 0; i < 4; i++)
		{
			passed = failed = total = cnt = 0;
			for (int j = 0; j < n; j++) 
			{
			 	if (!stu[j].del && stu[j].CID == cid)
			 	{
			 		cnt++;
			 		total += stu[j].score[i];
			 		if (stu[j].score[i] >= 60) passed++;
			 		else failed++;
				}
			}
			cout << course[i] << endl << "Average Score: " << fixed << setprecision(2) << (cnt ? total * 1.0 / cnt + EPS : 0) << endl
				 << "Number of passed students: " << passed << endl << "Number of failed students: " << failed << endl << endl;
			
		}
		
		for (int i = 0; i < n; i++) // 枚举没被删除的,且在指定班级的所有学生 
		{
			if (!stu[i].del && stu[i].CID == cid) 
			{
				cnt1 = 0;
				for (int j = 0; j < 4; j++) // 枚举他上的每门课程,计算多少门及格
				{
					if (stu[i].score[j] >= 60) cnt1++;
				}  
				//更新统计通过i门课(i [0, 4]) 的学生数
				if (!cnt1) p[0]++;
				else
				for (int k = 1; k <= cnt1; k++) p[k]++; 
			}
		}
		cout << "Overall:" << endl;
		for (int i = 4; i >= 0; i--) cout << words[i] << p[i] << endl;
		cout << endl;
	}
}

int main()
{
	cin.tie(0);
	cin.sync_with_stdio(false);
	#ifdef debug
	freopen("E:\in.txt", "r", stdin);
	freopen("E:\out.txt", "w", stdout);
	#endif
	
//	n = 0; 
	int choice;
	bool flag = true;
	while(flag)
	{
		Print_Menu();
		cin >> choice;
		switch(choice)
		{
			case 0: flag = false; break;
			case 1: Add(); break;
			case 2: Remove(); break;
			case 3: Query(); break;
			case 4: cout << "Showing the ranklist hurts students' self-esteem. Don't do that." << endl; break;
			case 5: Statistics(); break;
		}
	}
	
	#ifdef debug
	fclose(stdin);
	fclose(stdout);
	#endif
	return 0;
} 


/*
  版本2
  版本2与版本1的不同点是:
  1. 合并了删除操作和查询操作的大部分代码。因为删除删除操作和查询的输入是一样的,并且,操作上也有大部分的重叠
  2. 输出班级信息的部分,改为了两个函数,并且,将指定班级的输出和所有班级的输出合并了,因此只需要在特定的有选择语句的地方,除了判断输入数字是否与学生的班级号相等,再额外加上判断输入数字是否为0(因为为0时表示输出所有班级的信息,因而不再需要考虑学生的班级是否符合要求,直接全加上即可)...因而,合并了所有班级和指定班级的情况,大大精简了代码
  
  又及,这个改进思路是从这个blog上看到的,然后我再以我最初敲好的代码,借鉴这个思路,作了一些简化和修改
  http://blog.csdn.net/kun768/article/details/43816501
  
  (据说还是汝佳老师的源代码),而且真是很简洁啊!一开始看到这道题的时候,我还以为不到将近200行一定搞不定,没想到...果然汝佳老师的思路就十分清晰,很清楚什么操作可以合并部分代码,什么情况可以合并大部分代码,因此代码也就简洁优美了很多
   
*/ 

#include <iostream>
#include <iomanip>
#include <string>
#include <cstring>
#include <algorithm>
#include <cstdio>
//#define debug
using namespace std;
const int maxn = 1e5;
const double EPS = 1e-5;
int n = 0;
int CID, _score[4], sum;
string SID, name, s;
const string course[] = {"Chinese", "Mathematics", "English", "Programming"};
const string words[] = {"Number of students who failed all subjects: ", "Number of students who passed 1 or more subjects: ", "Number of students who passed 2 or more subjects: ", "Number of students who passed 3 or more subjects: ", "Number of students who passed all subjects: "}; 
struct student
{
	int CID, score[5]; // Chinese, Math, English, Programming, total
	bool del;
	double average;
	string name, SID;
}stu[maxn];


void Print_Menu()
{
	cout << "Welcome to Student Performance Management System (SPMS)." << endl << endl << "1 - Add" << endl << "2 - Remove" << endl << "3 - Query" << endl << "4 - Show ranking" << endl << "5 - Show Statistics" << endl << "0 - Exit" << endl << endl; 
}

int valid() // 检查是否合法,如果输入的SID已经输入过了,则该输入不合法,因而不处理该输入 
{
	for (int i = 0; i < n; i++)
	{
		if (!stu[i].del && stu[i].SID == s) return 0;
	}
	return 1;
}

int Rank (int k)
{
	int cnt = 0;
	for (int i = 0; i < n; i++)
	{
		if ( !stu[i].del && stu[i].score[4] > stu[k].score[4] ) cnt++;
	}
	return cnt + 1;
}

void Add()
{
	while (1)
	{
		cout << "Please enter the SID, CID, name and four scores. Enter 0 to finish." << endl;
		sum = 0;
		student in;
		cin >> s;
		in.SID = s;
		if (s == "0") break;
		cin >> in.CID >> in.name;
		for (int i = 0; i < 4; i++)
		{
			cin >> in.score[i];
			sum += in.score[i];
		}
		if (!valid()) cout << "Duplicated SID." << endl;
		else
		{
			in.score[4] = sum;
			in.average = sum / 4.0 + EPS; 
			in.del = false;
			stu[n++] = in;
		}
	}
}

void DQ(const int op) // op代表操作,如果为 0,表明输出的是要删除的,如果为 1,表明输入的只是需要查询 
{
	while (1)
	{
		cout << "Please enter SID or name. Enter 0 to finish." << endl;
		cin >> s;
		if (s == "0") break;
		int cnt = 0;
		for (int i = 0; i < n; i++)
		{
			if ( !stu[i].del && (stu[i].SID == s || stu[i].name == s) )
			{
				if (!op) //删除 
				{
					stu[i].del = true;
					++cnt;
				}
				else
				{
					char c = ' ';
					cout << Rank(i) << c << stu[i].SID << c << stu[i].CID << c << stu[i].name << c;
					for (int j = 0; j < 5; j++) cout << stu[i].score[j] << c;
					cout << fixed << setprecision(2) << stu[i].average << endl;
				}
				
			}
		}
		if (!op) cout << cnt << " student(s) removed." << endl;
	}
}

void output (const int no, const int type)
{
	int sum = 0, cnt1 = 0, cnt2 = 0;
	for (int i = 0; i < n; i++)
	if ( !stu[i].del && (no == 0 || no == stu[i].CID) )
	{
		sum += stu[i].score[type];
		if (stu[i].score[type] >= 60) cnt1++;
		else cnt2++; 
	}
	//#改到这里啦! 
	cout << "Average Score: " << fixed << setprecision(2) <<( (cnt1 + cnt2 != 0)?(sum * 1.0 / (cnt1 + cnt2) + EPS ): 0 )<< endl
		 << "Number of passed students: " << cnt1 << endl << "Number of failed students: " << cnt2 << endl << endl;
	
}

void Print()
{
	int p[5];
	memset(p, 0, sizeof(p));
	cout << "Please enter class ID, 0 for the whole statistics." << endl;
	int num; cin >> num;
	for (int i = 0; i < 4; i++)
	{
		cout << course[i] << endl;
		output(num, i);
	}
	cout << "Overall:" << endl;
	for (int i = 0; i < n; i++)
	{
		if ( !stu[i].del && ( num == 0 || stu[i].CID == num ) )
		{
			int tp = 0;
			for (int j = 0; j < 4; j++)
			if (stu[i].score[j] >= 60)
			tp++;
			
			if (!tp) p[0]++;
			else
			{
				for (int k = 1; k <= tp; k++)
				p[k]++;
			}
		}
	}
	for (int i = 4; i >= 0; i--)
	cout << words[i] << p[i] << endl;
	cout << endl;
}

int main()
{
	cin.tie(0);
	cin.sync_with_stdio(false);
	#ifdef debug
	freopen("E:\in.txt", "r", stdin);
	freopen("E:\out.txt", "w", stdout);
	#endif
	
	int choice;
	bool flag = true;
	n = 0;
	while(flag)
	{
		Print_Menu();
		cin >> choice;
		switch(choice)
		{
			case 0: flag = false; break;
			case 1: Add(); break;
			case 2: DQ(0); break;
			case 3: DQ(1); break;
			case 4: cout << "Showing the ranklist hurts students' self-esteem. Don't do that." << endl; break;
			case 5: Print(); break;
		}
	}
	
	#ifdef debug
	fclose(stdin);
	fclose(stdout);
	#endif
	return 0;
} 


原文地址:https://www.cnblogs.com/mofushaohua/p/7789530.html