例题4-6 师兄帮帮忙(A Typical Homework, UVa 12412)题解——146行代码
欢迎访问我的Uva题解目录哦 https://blog.****.net/richenyunqi/article/details/81149109
题目描述
题意解析
编写一个成绩管理系统(SPMS)。最多有100个学生,每个学生有如下属性。
- SID:学生编号,包含10位数字。
- CID:班级编号,为不超过20的正整数。
- 姓名:不超过10的字母和数字组成,第一个字符为大写字母。名字中不能有空白字符。
- 4门课程(语文、数学、英语、编程)成绩,均为不超过100的非负整数。
1 - Add
2 - Remove
3 - Query
4 - Show ranking
5 - Show Statistics
0 - Exit
- 选择1之后,会出现添加学生记录的提示信息: Please enter the SID, CID, name and four scores. Enter 0 to finish. 然后等待输入。本题保证输入总是合法的,但可能会输入重复SID。在这种情况下,需要输出一行提示: Duplicated SID. 不过名字是可以重复的。你的程序应当不停地打印前述提示信息,直到用户输入单个0。然后应当再次打印主菜单。
- 选择2之后,会出现如下提示信息: Please enter SID or name. Enter 0 to finish. 然后等待输入,在数据库中删除能匹配上述SID或者名字的所有学生,并且打印如下信息(xx可以等于0): xx student(s) removed. 你的程序应当不停地打印前述提示信息,直到用户输入单个0,然后再次打印主菜单。
- 选择3之后,会出现如下提示信息: Please enter SID or name. Enter 0 to finish. 然后等待输入。如果数据库中没有能匹配上述SID或者名字的学生,什么都不要做;否则输出所有满足条件的学生,按照进入数据库的顺序排列。输出格式和添加的格式相同,但增加3列:年级排名(第一列)、总分和平均分(最后两列)。所有班级中总分最高的学生获得第1名,如果有两个学生并列第2名,则下一个学生的排名为4(而非3)。你的程序应当不停地打印前述提示信息,直到用户输入单个0。然后应当再次打印主菜单。
- 选择4之后,会出现如下提示信息: Showing the ranklist hurts students' self-esteem. Don't do that. 然后自动返回主菜单。
- 选择5之后,会出现如下提示信息: Chinese Average Score: xx.xx Number of passed students: xx Number of failed students: xx …(为了节约篇幅,此处省略了Mathematics、English和Programming的统计信息) Overall: Number of students who passed all subjects: xx Number of students who passed 3 or more subjects: xx Number of students who passed 2 or more subjects: xx Number of students who passed 1 or more subjects: xx Number of students who failed all subjects: xx 然后自动回到主菜单。
- 选择0之后,程序终止。
注意,单科成绩和总分都应格式化为整数,但平均分应恰好保留两位小数。
提示:这个程序适合直接运行,用键盘与之交互,然后从屏幕中看到输出信息。但正因为如此,作为一道算法竞赛的题目,其输出看上去会比较乱。
算法设计
这道题目比较综合,算法思维上的要求并不难,只需按题目要求一步步实现各个功能函数即可。但是因为要注意许多格式上的要求才能AC(事实上这样的格式要求在实际的管理系统中并不多,毕竟大多数的管理系统都是设计了图形用户界面的),所以就显得比较麻烦,比较需要耐心了,不过还是建议大家真正独立地去实现一下这道题目,对编程水平的提高也有很大好处。以下直接附代码。
这道题的测试样例非常有用,如果能做到和测试样例的输出一致,这里的一致包括输出的换行以及空格的数量和位置完全相同,基本就能AC。但是肉眼检测自己程序的输出和样例输出是否一致是很困难,所以在这里推荐一种通过输入输出重定向和windows批处理文件比较程序输出和正确输出的方法,我就是用的这种方法在保证和样例输出完全一致后,提交就AC了。读者也不妨尝试一下。
C++代码
#include<bits/stdc++.h>
using namespace std;
const double limit=1e-6;
struct Student{
long long SID;
int CID,score[4],rank=1,totalScore=0;
double averageScore=0.0;
string name;
Student(long long s,int c,string n,int a[]):SID(s),CID(c),name(n){
for(int i=0;i<4;++i){
score[i]=a[i];
totalScore+=a[i];
}
averageScore=totalScore/4.0;
}
};
vector<Student>students;
void split(string&line,vector<string>&s){
string temp="";
for(int i=0;i<=line.size();++i)
if(i==line.size()||line[i]==' '){
s.push_back(temp);
temp="";
}else
temp+=line[i];
}
void outputMainMenu(){
printf("Welcome to Student Performance Management System (SPMS).\n\n1 - Add\n"
"2 - Remove\n3 - Query\n4 - Show ranking\n5 - Show Statistics\n0 - Exit\n\n");
}
void addStudent(){
printf("Please enter the SID, CID, name and four scores. Enter 0 to finish.\n");
string input;
while(getline(cin,input)&&input!="0"){
vector<string>s;
split(input,s);
long long SID=stoll(s[0]);
if(find_if(students.begin(),students.end(),[SID](const Student&stu){
return stu.SID==SID;})!=students.end())
printf("Duplicated SID.\n");
else{
int score[4];
for(int i=0;i<4;++i)
score[i]=stoi(s[i+3]);
students.push_back(Student(SID,stoi(s[1]),s[2],score));
}
printf("Please enter the SID, CID, name and four scores. Enter 0 to finish.\n");
}
}
void removeStudent(){
printf("Please enter SID or name. Enter 0 to finish.\n");
string input;
while(getline(cin,input)&&input!="0"){
int num=0,SID=-1;
if(isdigit(input[0]))
SID=stoll(input);
for(auto i=students.begin();i!=students.end();){
if(i->SID==SID||i->name==input){
i=students.erase(i);
++num;
}else
++i;
}
printf("%d student(s) removed.\n",num);
printf("Please enter SID or name. Enter 0 to finish.\n");
}
}
void queryStudent(){
printf("Please enter SID or name. Enter 0 to finish.\n");
vector<pair<int,int>>rank;
for(int i=0;i<students.size();++i)
rank.push_back({students[i].totalScore,i});
sort(rank.begin(),rank.end(),[](const pair<int,int>&a,const pair<int,int>&b){
return a.first>b.first;});
for(int i=1;i<rank.size();++i)
if(rank[i].first==rank[i-1].first)
students[rank[i].second].rank=students[rank[i-1].second].rank;
else
students[rank[i].second].rank=i+1;
string input;
while(getline(cin,input)&&input!="0"){
int SID=-1;
if(isdigit(input[0]))
SID=stoll(input);
for(Student&stu:students)
if(stu.SID==SID||stu.name==input)
printf("%d %010lld %d %s %d %d %d %d %d %.2f\n",stu.rank,stu.SID,stu.CID,
stu.name.c_str(),stu.score[0],stu.score[1],stu.score[2],
stu.score[3],stu.totalScore,stu.averageScore+limit);
printf("Please enter SID or name. Enter 0 to finish.\n");
}
}
void showStatistics(){
printf("Please enter class ID, 0 for the whole statistics.\n");
int input,pass[5]={0};
double statistics[4][3]={0.0};
string subject[4]={
"Chinese", "Mathematics", "English" , "Programming"
};
scanf("%d",&input);
for(Student&stu:students){
if(input==0||stu.CID==input){
int passNum=0;
for(int i=0;i<4;++i){
statistics[i][0]+=stu.score[i]*1.0;
if(stu.score[i]>=60){
++passNum;
++statistics[i][1];
}else
++statistics[i][2];
}
if(passNum>0)
for(int i=passNum;i>0;--i)
++pass[i];
else
++pass[0];
}
}
for(int i=0;i<4;++i){
statistics[i][0]/=statistics[i][1]+statistics[i][2];
printf("%s\nAverage Score: %.2f\nNumber of passed students: %.0f\n"
"Number of failed students: %.0f\n\n",
subject[i].c_str(),statistics[i][0]+limit,statistics[i][1],statistics[i][2]);
}
printf("Overall:\nNumber of students who passed all subjects: %d\n"
"Number of students who passed 3 or more subjects: %d\n"
"Number of students who passed 2 or more subjects: %d\n"
"Number of students who passed 1 or more subjects: %d\n"
"Number of students who failed all subjects: %d\n\n",
pass[4],pass[3],pass[2],pass[1],pass[0]);
}
int main(){
outputMainMenu();
int input;
while(~scanf("%d",&input)&&input!=0){
getchar();
if(input==1) addStudent();
else if(input==2) removeStudent();
else if(input==3) queryStudent();
else if(input==4)
printf("Showing the ranklist hurts students\' self-esteem. Don\'t do that.\n");
else if(input==5) showStatistics();
outputMainMenu();
}
return 0;
}