目录
1.题目
考试说明
- 考试时间:合计2小时。允许提前交卷。
- 考试过程中,不能连接未经指定网站或服务器。
- 闭卷考试部分,不能查阅任何类型的参考资料。
- 开卷考试部分,可以查阅纸质文档,不能查阅任何类型的电子文档。
- 考试过程中,不得使用任何形式的电子存储设备,不可使用手机。
- 违反上述2-5条者,视为考试作弊。
编程题提交方式(100分,开卷)
- 提交前务必关闭vs2005、vs2008或vs2010编程环境。
- 所有源程序内容必须仅包含在一个源程序文件(CPP文件)中。
- 在浏览器的地址栏中输入http://192.168.125.3,点击相应链接进入提交页面。
- 按要求输入两遍自己的学号。
- 点击“选择文件”按钮,选择自己的源程序文件。点击“提交”按钮提交。
- 如提交成功,系统会显示相关信息。如果提交不成功,请重复步骤16-18。
- 提交成功后,可点击“查看内容”按钮检查提交的内容。
按以下要求编写程序
题目说明
请各位考生从课程信息发布网站下载数据文件input.txt,然后将该数据文件手动保存在D盘根目录下。该文件中的数据以文本形式存储,其中包含了若干个同学的期中考试成绩记录,每个人最多有三门课,分别为Math、English和C++,每门课的成绩占一行,每行包括学号、课程名称和成绩,三者之间用‘\t’分开。
请按要求依次完成如下操作:
- 编写一个函数ReadFile。读取input.txt文件中的所有记录,并将它们存放在struct mark结构体类型的marks向量中。
- 编写一个函数ShowData。显示第1步中生成的marks向量的前5条。要求学号占15列左对齐,课程名称占10列左对齐,成绩占8列右对齐,本函数如果调用时不指定显示条数,则显示marks向量的前3条(当数据不足3条时,则全部显示)。
- 编写一个函数Filter,将marks向量中所有不合法的数据删除,所谓不合法的数据就是考试成绩小于0或者大于100,然后在屏幕上显示删除的条数。
- 编写一个函数FillData,将marks向量中所有数据按学号和课程名称汇总到struct student类型的向量stus中,汇总规则是:1)在stus中每个学号的学生只有一个元素;2)在stus中每个元素有三个成绩;3)汇总时如果某个学号在marks中不足三个成绩,对应stus中元素的对应成绩数据填0。
- 编写一个函数SortData,对向量stus按照三门课的总分从高到低排序,当总分相同时,按照学号从小到大排序。
- 编写一个函数ShowData,将stus向量中的最后5行数据显示在屏幕上(如果不足5行,则显示全部),要求学号占15列左对齐,Math成绩占5列右对齐,English占5列右对齐,C++占5列右对齐。
- 编写一个函数WriteFile。将经过第5步处理的向量stus中所有数据写入到指定文本文件result.txt中,要求学号占15列左对齐,Math成绩占5列右对齐,English占5列右对齐,C++占5列右对齐。
涉及结构体定义如下:
struct mark
{
string xh;//学号
string kc;//课程名称
int cj;//成绩
};
struct student
{
string xh; //学号
int math; //数学成绩
int english; //英语成绩
int cplusplus; //C++成绩
};
main函数如下:
int main()
{
vector <struct mark> marks;
ReadFile("d:\\input.txt", marks); //读取文件的数据到marks
cout << "数据总条数为:" << marks.size() << endl; //显示数据总数
ShowData(marks,5);
int count=Filter(marks);//删除其中不合法的数据
cout << "合计删除了" << count << "条不合法成绩" << endl;
vector<struct student> stus=FillData(marks);
cout <<"汇总结果合计有"<< stus.size()<<"人"<< endl;
SortData (stus);
cout << "总分最低的5人信息为" << endl;
ShowData(stus,5);
WriteFile("d:\\res.txt",stus);
return 0;
}
注意: 不允许修改main函数,每修改一处,扣3分;
评分标准
(编程题满分为80分)
大项 | 子项 | 评分项 | 应得分 | 实得分 |
正 确 性 70分 | 结果(70分) 含编译子项5分 | 读成绩的ReadFile函数 | 10 | |
ShowData函数(struct mark向量版本) | 8 | |||
Filter函数 | 12 | |||
FillData函数 | 12 | |||
SortData函数 | 10 | |||
ShowData函数(struct student向量版本) | 8 | |||
WriteFile函数 | 10 | |||
上述各项都不得分 | 见编译子项 | 本项不得分 | ||
程序运行出现异常 | -10 | |||
程序死循环 | -10 | |||
修改main函数 | -3(每处修改) | |||
编译(5分) | 编译连接均通过(无warning) | 5 | ||
编译连接均通过(有warning) | 3 | |||
编译通过、连接不通过 | 2 | |||
编译、连接均不通过 | 0 | |||
可 读 性 10分 | 缩进对齐(4分) | 正确运用缩进对齐规则 | 4 | |
有缩进对齐但不完全符合要求 | 3 | |||
没有使用缩进对齐规则 | 2 | |||
注释(3分) | 有详细且正确的注释 | 3 | ||
有注释,但不够详细 | 2 | |||
完全没有注释 | 0 | |||
变量命名(3分) | 变量命名有规则 | 3 | ||
变量命名有规则、但规则使用不一致 | 2 | |||
变量命名无规则 | 0 |
2. 解题代码
#include <iostream>
#include <vector>
#include<fstream>
#include<iomanip>
#include<algorithm>
using namespace std;
struct mark
{
string xh;//学号
string kc;//课程名称
int cj;//成绩
};
struct student
{
string xh; //学号
int math; //数学成绩
int english; //英语成绩
int cplusplus; //C++成绩
};
void ReadFile(string path, vector<struct mark>&Marks){
ifstream ifile(path);
while(!ifile.eof()){
mark m;
if(ifile>>m.xh>>m.kc>>m.cj){
Marks.push_back(m);
}
}
ifile.close();
}
void ShowData(const vector<struct mark>&Marks, int n=3){
//要求学号占15列左对齐,课程名称占10列左对齐,成绩占8列右对齐
for(int i=0;i<Marks.size();i++){
cout<<left<<setw(15)<<Marks[i].xh;
cout<<left<<setw(10)<<Marks[i].kc;
cout<<right<<setw(8)<<Marks[i].cj;
cout<<endl;
if(i+1==n){break;}
}
}
int Filter(vector<struct mark>&Marks){
//所谓不合法的数据就是考试成绩小于0或者大于100
vector<struct mark>::iterator it;
int tempc;
tempc=0;
for(it=Marks.begin();it!=Marks.end();){
if(it->cj<0 or it->cj>100){
it=Marks.erase(it);
tempc++;
}
else{
it++;
}
}
return tempc;
}
vector<struct student>FillData( const vector<struct mark>&Marks){
vector<struct student>newv;
for(int i=0;i<Marks.size();i++){
int j;
for(j=0;j<newv.size();j++){
if(newv[j].xh==Marks[i].xh){
break;
}
}
if(j==newv.size()){
student v;
v.xh=Marks[i].xh;
v.math=v.english=v.cplusplus=0;
if(Marks[i].kc=="Math"){
v.math=Marks[i].cj;
}
else if (Marks[i].kc=="English"){
v.english=Marks[i].cj;
}
else{
v.cplusplus=Marks[i].cj;
}
newv.push_back(v);
}
else{
if(Marks[i].kc=="Math"){
newv[j].math=Marks[i].cj;
}
else if (Marks[i].kc=="English"){
newv[j].english=Marks[i].cj;
}
else{
newv[j].cplusplus=Marks[i].cj;
}
}
}
return newv;
}
bool cmp(student a, student b){
//对向量stus按照三门课的总分从高到低排序
//按照学号从小到大排序
if((a.cplusplus+a.english+a.math)==(b.cplusplus+b.english+b.math)){
return a.xh<b.xh;
}
else{
return (b.cplusplus+b.english+b.math)<(a.cplusplus+a.english+a.math);
}
}
void SortData(vector<struct student>&Stus){
sort(Stus.begin(),Stus.end(),cmp);
}
void ShowData(const vector<struct student>&Stus,int n=5){
//将stus向量中的最后5行数据显示在屏幕上(如果不足5行,则显示全部)
for(int i=0;i<n;i++){
int l=Stus.size()-1-i;
//要求学号占15列左对齐,Math成绩占5列右对齐,English占5列右对齐,C++占5列右对齐。
cout<<left<<setw(15)<<Stus[l].xh;
cout<<right<<setw(5)<<Stus[l].math;
cout<<right<<setw(5)<<Stus[l].english;
cout<<right<<setw(5)<<Stus[l].cplusplus<<endl;
if(l==0){break;}
}
}
void WriteFile(string path,const vector<struct student>&Stus){
ofstream ofile(path);
for(int i=0;i<Stus.size();i++){
ofile<<left<<setw(15)<<Stus[i].xh;
ofile<<right<<setw(5)<<Stus[i].math;
ofile<<right<<setw(5)<<Stus[i].english;
ofile<<right<<setw(5)<<Stus[i].cplusplus<<endl;
}
ofile.close();
}
int main()
{
vector <struct mark> marks;
ReadFile("/Users/apple/Downloads/1-1/input.txt", marks); //读取文件的数据到marks
cout << "数据总条数为:" << marks.size() << endl; //显示数据总数
ShowData(marks,5);
int count=Filter(marks);//删除其中不合法的数据
cout << "合计删除了" << count << "条不合法成绩" << endl;
vector<struct student> stus=FillData(marks);
cout <<"汇总结果合计有"<< stus.size()<<"人"<< endl;
SortData (stus);
cout << "总分最低的5人信息为" << endl;
ShowData(stus,5);
WriteFile("/Users/apple/Downloads/1-1/res.txt",stus);
return 0;
}
3. 问题总结
(1) 如何在不用全局变量的条件下在函数中修改主函数中的内容?
答:引用。引用相当于给主函数中传进来的变量起了个别名,两者还是相关联的。这个别名不能给主函数中的别的变量使用。
(2)记得读完文件进行close()操作,养成良好习惯从我做起~