学生成绩信息管理系统(c++)
2014-06-25 11:06
369 查看
现有学生成绩信息文件1(1.txt),内容如下:
姓名 学号 语文 数学 英语
张明明 01 67 78 82
李成友 02 78 91 88
张辉灿 03 68 82 56
王露 04 56 45 77
陈东明 05 67 38 47
…… ……
学生成绩信息文件2(2.txt),内容如下:
姓名 学号 语文 数学 英语
陈果 31 57 68 82
李华明 32 88 90 68
张明东 33 48 42 56
李明国 34 50 45 87
陈道亮 35 47 58 77
…… ……
试编写一个管理系统,要求如下:
1) 要求使用链表或数组等实现上述要求
2) 实现对两个文件数据进行合并,生成新文件3.txt
3) 可实现学生成绩信息的输入、修改、删除功能
4) 抽取出三科成绩中有补考的学生并保存在一个新文件4.txt
5) 对合并后的文件3.txt中的数据按总分降序排序(至少采用两种排序方法实现)
6)输入一个学生姓名后,能查找到此学生的信息并输出结果(至少采用两种查找方法实现)
7)统计输出各门课程的平均分,最高分、最低分
8)统计各门课程优秀、良好、中等、及格、不及格的人数及百分比
总结:
1. 考虑到所操作数据的特性,所以才用了常规的结构体数组进行基础数据的存放。
2. 由于之前并没有学习过C++对于文件读写的操作,所以在网上已经课本上查阅了大量的文献,对于文件1,2的合并,是用来C++的ifstream类来进行操作,这里遇到了第一个问题对于生成的文件3是由文件1的全部和文件2的去掉标题第一行的部分,所以对于文件1,进行了整体读入,而对于文件2采用了分行读入,这里采用了getline()函数来接收一行,使用for循环来进行计数。当i==0时,用continue来屏蔽掉第一行由此成功写入一个有标题的文件3.txt。
3. 第二个比较头痛的问题出现在使用流读txt文件到结构体中时,首先打开文件,对文件以空格为间隔进行读入,结束条件为!infile.eof(),这里又出现了一个问题,由于文件有标题,所以前五个数据时我们所不需要的,这里经过考虑想到使用一个字符串数组把前五项数据“吸收”进去,从而是数据可以成功录入到结构体数组。
4. 对于生成补考名单的功能首先使用ofstream生成一个对象,ios::trunc 如果文件已存在则先删除该文件.
ifstream ifile("data.dat",ios::in)
ofstream ofile("data.dat",ios::out)
ios::in和ios::out分别表示读打开和写打开
5. 对于添加数据,修改数据,删除数据这几个模块的实现,并没有太多需要注意的情况,对于整体结构体数组的学生个数的计数均由全局变量aNum来进行控制,当“aNum==0”事,相关的几个函数模块将会不执行,返回主程序menu()。
6. 在statistics(统计函数),通过一次遍历对数据进行了计数操作在最后由于要显示百分比,所以使用了setprecisions()函数来控制小数的位数。
7. 在本次课程设计中遇到了很多细节性的问题,还有很多平时在C语言中补偿遇到的状况,在解决问题的过程中增加了我对于C/C++的知识,尤其是在文件作的部分,以及对于结构体有了更深刻的理解。
8. 在开始进行本次试验时还犯了一个比较大的错误,在定义fillstruct()函数时并没有传结构体数组的地址给函数,从而导致了数据无法读入到结构体中,因此而耽误了大量的时间,后来经过反复的debug以及思考想到了可能是由于缺少参数造成了该错误,因此对函数及伺候的函数都加上了地址参数问题就将问题解决了。
9. 在D盘建立文件1和文件2时,先开始以为是要显示的,所以写的1.txt 和2.txt ,后来就和并不了,最后尝试去掉.txt就可以了,这个属于低级失误了。
姓名 学号 语文 数学 英语
张明明 01 67 78 82
李成友 02 78 91 88
张辉灿 03 68 82 56
王露 04 56 45 77
陈东明 05 67 38 47
…… ……
学生成绩信息文件2(2.txt),内容如下:
姓名 学号 语文 数学 英语
陈果 31 57 68 82
李华明 32 88 90 68
张明东 33 48 42 56
李明国 34 50 45 87
陈道亮 35 47 58 77
…… ……
试编写一个管理系统,要求如下:
1) 要求使用链表或数组等实现上述要求
2) 实现对两个文件数据进行合并,生成新文件3.txt
3) 可实现学生成绩信息的输入、修改、删除功能
4) 抽取出三科成绩中有补考的学生并保存在一个新文件4.txt
5) 对合并后的文件3.txt中的数据按总分降序排序(至少采用两种排序方法实现)
6)输入一个学生姓名后,能查找到此学生的信息并输出结果(至少采用两种查找方法实现)
7)统计输出各门课程的平均分,最高分、最低分
8)统计各门课程优秀、良好、中等、及格、不及格的人数及百分比
#include <iostream> #include <fstream> #include <string> #include <iomanip> using namespace std; string str[5] ; //定义一个str字符串来吸收文件2.txt中重复的标题 int aNum=0; //使用全局变量定义学生的人数 struct adent //构建结构体 { char name[10]; //姓名 int id; int chinese; int math; int english; int sum; }a[50],temp; //实现对文件1.txt和文件2.txt数据的合并,生成文件3.txt void Merge() { char* f1 = "d:\\1.txt"; char* f2 = "d:\\2.txt"; char* f3 = "d:\\3.txt"; ifstream inFile1( f1 ); //从磁盘读取文件1.txt ifstream inFile2( f2 ); //从磁盘读取文件2.txt ofstream outFile( f3 ); //写入信息到文件3.xtx outFile << inFile1.rdbuf(); //把文件1.txt中的数据写入到outfile for(int i=0;!inFile2.eof()==true;i++) //遍历文件2.txt的所有数据 { string str; getline(inFile2,str); //读取第一行信息放到str中 if(i==0)continue; //跳过第一行 outFile<<str<<endl; //把后面的信息放入到文件3.txt } inFile1.close(); //关闭文件f1 inFile2.close(); outFile.close(); ifstream f ( f3 ); cout <<"**文件已生成,合并后数据如下**"<<endl; cout << f.rdbuf(); //输出文件3.txt }; //把文件3.txt中的数据读出到结构体中,便于对数据的操作 void FillStruct(adent *p) { int i=aNum, j=0; //这里让i = aNum,假如先添加数据,后合并,则结构体下标中人数i不是从0开始计,而是从先输入的数据的个数aNum开始的 ifstream infile("D:\\3.txt",ios::in); //以读的方式打开文件3.txt if(!infile) //测试是否成功打开 { cerr<<"open error!"<<endl; exit(1); } while(!infile.eof()) //遍历infile,只把数据写入进去,过滤掉第一行的头标题 { while(j<5) //用一个str数组把文件3.txt中的头标题给吸收进去 {infile>>str[j]; j++; } //把磁盘中的文件读出来写入到结构体中 infile >> p[i].name >> p[i].id >> p[i].chinese >> p[i].math >> p[i].english; aNum++; i++; } aNum=aNum-1; //数据读完后因光标移到下一行,等于是多读了一行,所以真实的人数要比计数减一(不知道理解的对不?) infile.close(); //关闭文件 }; //抽取出三科成绩中有补考的学生并保存在一个新文件4.txt int FailList(adent *p) { /*如果先开始进行的操作不是合并或者添加数据,那么其他的操作将无法进行,因为结构体中没有学生数据,返回主菜单*/ if(aNum==0) { cout<<"请先合并或者输入数据"<<endl; return 0; } ofstream in; in.open("d:\\4.txt",ios::trunc); //如不空则清空 in<<"补考名单"<<endl; //用插入器(<<)向文件输出;用析取器(>>)从文件输入 for(int i=0;i<aNum;i++) { if(p[i].chinese<60||p[i].english<60||p[i].math<60) { in<<p[i].name<<"\t"; } } }; void sum(adent *p) //求总和 { for(int i=0;i<aNum;i++) { p[i].sum=p[i].chinese+p[i].english+p[i].math; } } void traversal(adent *p) //遍历输出学生数据 { cout<<"姓名"<<'\t'<<"学号"<<'\t'<<"语文"<<'\t'<<"数学"<<'\t'<<"英语"<<'\t'<<"总分"<<endl; for(int i=0;i<aNum;i++) { cout<<p[i].name<<'\t'<<p[i].id<<'\t'<<p[i].chinese<<'\t'<<p[i].math<<'\t'<<p[i].english<<'\t'<<p[i].sum<<endl; } } //对学生总分按照从高到低的顺序排列 int Sort(adent *p) { if(aNum==0) { cout<<"请先合并或者输入数据"<<endl; return 3; } sum(p); int flag=0; //设标识位 do{ cout<<"请输入排序方式,输入“1”冒泡排序, 输入“2”直接插入排序"<<endl; cin>>flag; if(flag==1)//冒泡 { for(int i=0;i<aNum-1;++i) //外层循环 { for(int k=i;k<aNum-1;++k) //内层循环 { if(p[k].sum <p[k+1].sum) //按照从大到小的顺序进行排列 { temp = p[k]; p[k] = p[k+1]; p[k+1] = temp; } } } traversal(p); //输出排序后的结果 return 1; } if(flag==2)//直接插入 { for(int i=1;i<aNum;i++) { temp=p[i]; //将要比较的关键数赋给哨兵temp int j=i-1; while(j>=0 && temp.sum>p[j].sum) //直到越界或者把哨兵的值和j的值进行比较 { p[j+1]=p[j]; //如果J的值比哨兵的值小,则把j的值向后移动 j--; //j向前移,循环进行比较 } p[j+1]=temp; //直到找到temp的值比j的值小,就把哨兵里的值放在j得后面 } traversal(p); return 1; } if(flag!=1 && flag!=2) { cout<<"输入错误,请重新输入"; flag=3; } }while(flag=3); } //输入一个学生姓名后,能查找到此学生的信息并输出结果 int Select(adent *p) { if(aNum==0) { cout<<"请先合并或者输入数据"<<endl; return 3; } int i=0; cout<<"请输入查询的姓名:"; char sname[10]; cin>>sname; while(i<aNum) { if(strcmp(sname,p[i].name)==0) //通过字符串的比较来搜索要查找的姓名 { cout<<"姓名"<<'\t'<<"学号"<<'\t'<<"语文"<<'\t'<<"数学"<<'\t'<<"英语"<<endl; cout<<p[i].name<<'\t'<<p[i].id<<'\t'<<p[i].chinese<<'\t'<<p[i].math<<'\t'<&l 4000 t;p[i].english<<endl; return 1; } else { i++; if(i==aNum) { cout<<"无此学生返回主菜单"<<endl; return 0; } } }//while } //统计输出各门课程的平均分,最高分、最低分 //统计各门课程优秀、良好、中等、及格、不及格的人数及百分比 int Statistics(adent *p) { if(aNum==0) { cout<<"请先合并或者输入数据"<<endl; return 0; } int flag=0; cout<<"请输入您想进行统计的科目,语文输入“1”,数学输入“2”,英语输入“3”"<<endl; cin>>flag; if(flag==1) { float tempmax=0,tempmin=100,tempsum=0,tempgood=0,tempnormal=0,tempbad=0; for(int i=0;i<aNum;i++) { if(p[i].chinese>tempmax)tempmax=p[i].chinese; //找到最高分 if(p[i].chinese<tempmin)tempmin=p[i].chinese; //找到最低分 if(p[i].chinese>=85)tempgood++; //找到优秀的人数 if(p[i].chinese>=60 &&p[i].chinese<85)tempnormal++; //中等的人数 if(p[i].chinese<60)tempbad++; //不及格的人数 tempsum=tempsum+p[i].chinese; //语文的总分 } cout<<"语文成绩平均分为:"<<setprecision(4)<<tempsum/aNum<<'\t'<<"最高分为:"<<tempmax<<'\t'<<"最低分为:"<<tempmin<<endl; cout<<"优秀的人数:"<<tempgood<<" 普通的人数:"<<tempnormal<<" 不及格的人数:"<<tempbad<<endl; cout<<"优秀(大于等于85)百分比为:"<<setprecision(4)<<tempgood/aNum*100<<'\t'<<"中等(60到85之间)百分比为:"<<tempnormal/aNum*100<<'\t'<<"不及格(小于60)百分比为:"<<tempbad/aNum*100<<endl; } if(flag==2) { float tempmax=0,tempmin=100,tempsum=0,tempgood=0,tempnormal=0,tempbad=0; for(int i=0;i<aNum;i++) { if(p[i].math>tempmax)tempmax=p[i].math; if(p[i].math<tempmin)tempmin=p[i].math; if(p[i].math>=85)tempgood++; if(p[i].math>=60 && p[i].math<85)tempnormal++; if(p[i].math<60)tempbad++; tempsum=tempsum+p[i].math; } cout<<"数学成绩平均分为:"<<setprecision(4)<<tempsum/aNum<<'\t'<<"最高分为:"<<tempmax<<'\t'<<"最低分为:"<<tempmin<<endl; cout<<"优秀的人数:"<<tempgood<<" 普通的人数:"<<tempnormal<<" 不及格的人数:"<<tempbad<<endl; cout<<"优秀(大于等于85)百分比为:"<<setprecision(4)<<tempgood/aNum*100<<'\t'<<"中等(60到85之间)百分比为:"<<tempnormal/aNum*100<<'\t'<<"不及格(小于60)百分比为:"<<tempbad/aNum*100<<endl; } if(flag==3) { float tempmax=0,tempmin=100,tempsum=0,tempgood=0,tempnormal=0,tempbad=0; for(int i=0;i<aNum;i++) { if(p[i].english>tempmax)tempmax=p[i].english; if(p[i].english<tempmin)tempmin=p[i].english; if(p[i].english>=85)tempgood++; if(p[i].english>=60 &&p[i].english<85)tempnormal++; if(p[i].english<60)tempbad++; tempsum=tempsum+p[i].english; } cout<<"英语成绩平均分为:"<<setprecision(4)<<tempsum/aNum<<'\t'<<"最高分为:"<<tempmax<<'\t'<<"最低分为:"<<tempmin<<endl; cout<<"优秀的人数:"<<tempgood<<" 普通的人数:"<<tempnormal<<" 不及格的人数:"<<tempbad<<endl; cout<<"优秀(大于等于85)百分比为:"<<setprecision(4)<<tempgood/aNum*100<<'\t'<<"中等(60到85之间)百分比为:"<<tempnormal/aNum*100<<'\t'<<"不及格(小于60)百分比为:"<<tempbad/aNum*100<<endl; } }; //添加数据 void adda(adent *p) { int aid=0,ac=0,am=0,ae=0;char aname[10]; cout<<"请输入学号:"<<endl; cin>>aid; p[aNum].id=aid; cout<<"请输入姓名:"<<endl; cin>>aname; strcpy(p[aNum].name,aname); cout<<"请输入语文成绩:"<<endl; cin>>ac; p[aNum].chinese=ac; cout<<"请输入数学成绩:"<<endl; cin>>am; p[aNum].math=am; cout<<"请输入英语成绩:"<<endl; cin>>ae; p[aNum].english=ae; cout<<"录入成功"<<endl; aNum++; //学生人数 } //删除数据 int dela(adent *p) { if(aNum==0) { cout<<"请先合并或者输入数据"<<endl; return 3; } int i=0,aid=0; cout<<"请输入要删除学生的学号"<<endl; cin>>aid; while(i<aNum) { if(p[i].id==aid) //找到要删除的id { for(int j=i;j<aNum-1;j++) p[i]=p[i+1]; //向前移动一位 aNum--; //人数减一 cout<<"删除成功"<<endl; return 1; } else { i++; if(i==aNum) { cout<<"无此学生返回主菜单"<<endl; return 0; } } }//while } //修改数据 int altera(adent *p) { if(aNum==0) { cout<<"请先合并或者输入数据"<<endl; return 3; } int aid=0,ac=0,am=0,ae=0,i=0;char aname[10]; cout<<"请输入要修改学生的学号"<<endl; cin>>aid; while(i<aNum) { if(p[i].id==aid) { cout<<"请输入新姓名:"<<endl; cin>>aname; strcpy(p[aNum].name,aname); cout<<"请输入新语文成绩:"<<endl; cin>>ac; p[aNum].chinese=ac; cout<<"请输入新数学成绩:"<<endl; cin>>am; p[aNum].math=am; cout<<"请输入新英语成绩:"<<endl; cin>>ae; p[aNum].english=ae; cout<<"修改成功"<<endl; return 1; } else { i++; if(i==aNum) { cout<<"无此学生返回主菜单"<<endl; return 0; } } }//while } //菜单 void menu() { cout<<"-------------------------------学生成绩管理系统---------------------------------"<<endl; cout<<" 1:对文件进行合并生成3.txt(在D盘下)"<<endl; cout<<" 2:添加数据"<<endl; cout<<" 3:修改数据"<<endl; cout<<" 4:删除数据"<<endl; cout<<" 5:按姓名查找某一学生成绩"<<endl; cout<<" 6:生成需补考学生名单4.txt(在D盘下)"<<endl; cout<<" 7:对学生成绩进行排序"<<endl; cout<<" 8:进行各科成绩的统计(平均分,最高分,最低分,成绩层次分布)"<<endl; cout<<" 9:退出"<<endl; cout<<"--------------------------------------------------------------------------------"<<endl; } //主函数 void main(){ system("color 79"); //系统颜色 int choice; do { menu(); cout<<"请输入您需要操作对应阿拉伯数字(1~9)"<<endl; cin>>choice; switch(choice) { case 1: Merge(); FillStruct(a); break; case 2: adda(a); break; case 3: altera(a); break; case 4: dela(a); break; case 5: Select(a); break; case 6: FailList(a); break; case 7: Sort(a); break; case 8: Statistics(a); break; case 9: exit(0); break; }//switch }while(1); }
总结:
1. 考虑到所操作数据的特性,所以才用了常规的结构体数组进行基础数据的存放。
2. 由于之前并没有学习过C++对于文件读写的操作,所以在网上已经课本上查阅了大量的文献,对于文件1,2的合并,是用来C++的ifstream类来进行操作,这里遇到了第一个问题对于生成的文件3是由文件1的全部和文件2的去掉标题第一行的部分,所以对于文件1,进行了整体读入,而对于文件2采用了分行读入,这里采用了getline()函数来接收一行,使用for循环来进行计数。当i==0时,用continue来屏蔽掉第一行由此成功写入一个有标题的文件3.txt。
3. 第二个比较头痛的问题出现在使用流读txt文件到结构体中时,首先打开文件,对文件以空格为间隔进行读入,结束条件为!infile.eof(),这里又出现了一个问题,由于文件有标题,所以前五个数据时我们所不需要的,这里经过考虑想到使用一个字符串数组把前五项数据“吸收”进去,从而是数据可以成功录入到结构体数组。
4. 对于生成补考名单的功能首先使用ofstream生成一个对象,ios::trunc 如果文件已存在则先删除该文件.
ifstream ifile("data.dat",ios::in)
ofstream ofile("data.dat",ios::out)
ios::in和ios::out分别表示读打开和写打开
5. 对于添加数据,修改数据,删除数据这几个模块的实现,并没有太多需要注意的情况,对于整体结构体数组的学生个数的计数均由全局变量aNum来进行控制,当“aNum==0”事,相关的几个函数模块将会不执行,返回主程序menu()。
6. 在statistics(统计函数),通过一次遍历对数据进行了计数操作在最后由于要显示百分比,所以使用了setprecisions()函数来控制小数的位数。
7. 在本次课程设计中遇到了很多细节性的问题,还有很多平时在C语言中补偿遇到的状况,在解决问题的过程中增加了我对于C/C++的知识,尤其是在文件作的部分,以及对于结构体有了更深刻的理解。
8. 在开始进行本次试验时还犯了一个比较大的错误,在定义fillstruct()函数时并没有传结构体数组的地址给函数,从而导致了数据无法读入到结构体中,因此而耽误了大量的时间,后来经过反复的debug以及思考想到了可能是由于缺少参数造成了该错误,因此对函数及伺候的函数都加上了地址参数问题就将问题解决了。
9. 在D盘建立文件1和文件2时,先开始以为是要显示的,所以写的1.txt 和2.txt ,后来就和并不了,最后尝试去掉.txt就可以了,这个属于低级失误了。
相关文章推荐
- 学生成绩信息管理系统
- jsp学生成绩信息管理系统
- 程序阅读:简单C++学生信息管理系统
- c++ stl list实现简单的学生信息管理系统
- 班级学生成绩管理系统C++
- 简易学生信息管理系统(c++源代码)
- C语言项目--教师信息/学生成绩管理系统
- 学生信息管理系统(c++)
- [置顶] C语言项目--教师信息/学生成绩管理系统
- C语言项目--教师信息/学生成绩管理系统
- 【原创视频教程】学生信息管理系统4--成绩添加
- 【原创视频教程】学生信息管理系统4--成绩添加
- 《C++编写 学生成绩管理系统》
- C++课程设计:学生成绩管理系统
- 【原创视频教程】学生信息管理系统5--学员成绩管理
- 急需学生成绩信息管理系统~~嗷嗷
- C++学生成绩管理系统
- C++学生成绩管理系统
- C++ 简单的学生信息管理系统
- C语言项目--教师信息/学生成绩管理系统