您的位置:首页 > 编程语言 > C语言/C++

学生成绩信息管理系统(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)统计各门课程优秀、良好、中等、及格、不及格的人数及百分比

 

 

#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就可以了,这个属于低级失误了。

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: