📄 学生成绩2.cpp
字号:
#include<iostream>
#include<iomanip>
#include<string>
#include<fstream>
using namespace std;
template<class TElem>//元素与关系描述
struct LInkNode
{
TElem info;
LInkNode *next;
};
template<class TElem>//链表类的模板
class LInkList
{
protected:
public:
LInkNode<TElem> *head;
LInkList();
bool IsEmpty();//检查链表是否为空。
LInkNode<TElem>*InsertEnd(LInkNode<TElem>*p);//将值为*p的学生信息插入到链表最后面。并返回头结点。
LInkNode<TElem>* InsertFront(LInkNode<TElem>*p);//将值为*p的学生信息插入到链表头结点后面。并返回头结点。
LInkNode<TElem>* Release();//删除链表内容,但是保留头结点.
};
template<class TElem>
LInkList<TElem>::LInkList()
{
head=new LInkNode<TElem>;
head->next=NULL;
}
template<class TElem>
LInkNode<TElem>* LInkList<TElem>::Release()
{
LInkNode<TElem>*q,*p;
q=p=new LInkNode<TElem>;
p=head->next;
head->next=NULL;
while(q!=NULL)
{
q=p->next;
delete p;
p=q;
}
cout<<"删除链表成功。"<<endl<<endl;
return head;
}
template<class TElem>
bool LInkList<TElem>::IsEmpty()
{
if(head->next==NULL)return true;
else return false;
}
template<class TElem>
LInkNode<TElem>* LInkList<TElem>::InsertFront(LInkNode<TElem>*p)
{
p->next=head->next;
head->next=p;
cout<<"添加数据成功."<<endl<<endl;
return head;
}
template<class TElem>
LInkNode<TElem>* LInkList<TElem>::InsertEnd(LInkNode<TElem>*p)
{
if(head->next==NULL){head->next=p;cout<<"添加数据成功."<<endl;return head;}
LInkNode<TElem>*q;
q=new LInkNode<TElem>;
for(q=head->next;q->next!=NULL;q=q->next);
q->next=p;
cout<<"添加数据成功."<<endl;
return head;
}
//1:先按学期,班级对学生成绩录入(链表)。录入的学生成绩信息可包括:
// 学号,姓名,科目1..5成绩(用数组),平均分,……
class STudent
{
protected:
long number;
char name[20];
float score[5];//学生的成绩数组
float average;//学生平均分
public:
void GetValue();//给当前学生对象赋值
LInkNode<STudent>* LocateNum(LInkNode<STudent>*head);//用学号查找学生.
LInkNode<STudent>* LocateName(LInkNode<STudent>*head);//用姓名查找学生.
void LocateFail(LInkNode<STudent>*head);//查找不及格学生
void Countaverage();//计算学生的平均分
void MarkSort(LInkNode<STudent>*head);//学生平均分排序
friend void Display(LInkNode<STudent>* head,char*filename) ;//将链表中的数据贮存到文件中.
friend LInkNode<STudent> *FileGetValue(LInkNode<STudent>* head,char*FileName);//将文件中的数据读入链表.
friend void Display(LInkNode<STudent>* head);//屏幕上显示链表中的学生信息.
friend void ClassInfo(LInkNode<STudent>*head);//统计该学生所在班的情况.成绩0为缺考.
};
void STudent::GetValue()
{
cout<<"请输入该学生的学号:";
cin>>number;
cout<<"请输入该学生的姓名:";
cin>>name;
cout<<"请依次输入3门课程的成绩:";
for(int i=0;i<3;i++)
cin>>score[i];
}
LInkNode<STudent>* STudent::LocateNum(LInkNode<STudent>*head)
{
cout<<"请输入该学生的学号(输入0时结束):";
cin>>number;
if(number==0)return NULL;//考虑用户错误操作,一旦错误的进入学号查询,可以立刻输入结束符号0,来退回菜单。
LInkNode<STudent>*p;
p=new LInkNode<STudent>;
for(p=head->next;p!=NULL;p=p->next)
if(p->info.number==number)
{
cout<<endl;
cout<<"找到该学生。"<<endl;
cout<<"该学生的学号:";
cout<<(p->info).number<<endl;
cout<<"该学生的姓名:";
cout<<(p->info).name<<endl;
cout<<"3门课程的成绩:";
for(int i=0;i<3;i++)
cout<<(p->info).score[i]<<" ";
cout<<endl<<endl;
return p;//一有找到该姓名的学生就退出循环。
}
if(p==NULL)cout<<"数据有误,没有该学生的资料."<<endl<<endl;
return NULL;
}
LInkNode<STudent>* STudent::LocateName(LInkNode<STudent>*head)
{
cout<<"请输入该学生的姓名(输入0时结束):";
cin>>name;
if(name=="0")return NULL;//考虑用户错误操作,一旦错误的进入姓名查询,可以立刻输入结束符号0,来退回菜单。
LInkNode<STudent>*p;
p=new LInkNode<STudent>;
for(p=head->next;p!=NULL;p=p->next)
if(strcmp(p->info.name,name)==0)
{
cout<<endl;
cout<<"找到该学生。"<<endl;
cout<<"该学生的学号:";
cout<<(p->info).number<<endl;
cout<<"该学生的姓名:";
cout<<(p->info).name<<endl;
cout<<"3门课程的成绩:";
for(int i=0;i<3;i++)
cout<<(p->info).score[i]<<" ";
cout<<endl<<endl;
return p;//一有找到该姓名的学生就退出循环。
}
if(p==NULL)cout<<"数据有误,没有该学生的资料."<<endl<<endl;
return NULL;
}
void STudent::LocateFail(LInkNode<STudent>*head)
{
int n=0;//统计不及格的学生人次.
cout<<"该班的学生不及格情况是:"<<endl;
LInkNode<STudent>*p;
p=new LInkNode<STudent>;
p=head->next;
while(p)
{
for(int i=0;i<3;i++)
if(p->info.score[i]<60){cout<<p->info.name<<"的课程"<<i+1<<"不及格."<<endl;n++;}
p=p->next;
}
cout<<endl;
if(n==0)cout<<"该班非常优秀,没有不及格学生."<<endl<<endl;
return;
}
void STudent::Countaverage()
{
average=0;
for(int i=0;i<3;i++)
average+=score[i];
average=average/3.0;
}
void STudent::MarkSort(LInkNode<STudent>*head)
{
int i,j,k,n;
LInkNode<STudent>*p;
p=new LInkNode<STudent>;
LInkNode<STudent> stud,stu[30];
for(n=0,p=head->next;p!=NULL;p=p->next,n++)
{
p->info.Countaverage();
stu[n]=*p;
}
for(i=0;i<n-1;i++)
{
k=i;
for(j=i+1;j<n;j++)
if(stu[j].info.average<stu[k].info.average)k=j;
stud=stu[k];stu[k]=stu[i];stu[i]=stud;
}
for(p=head->next,i=0;i<n;i++,p=p->next)
p->info=stu[i].info;
cout<<"排序成功."<<endl;
}
void Display(LInkNode<STudent>* head)
{
if(head->next==NULL){cout<<"当前链表为空。"<<endl<<endl;return;}
LInkNode<STudent>* p;
p=new LInkNode<STudent>;
p=head->next;
while(p!=NULL)
{
cout<<endl;
cout<<"该学生的学号:";
cout<<(p->info).number<<endl;
cout<<"该学生的姓名:";
cout<<(p->info).name<<endl;
cout<<"3门课程的成绩:";
for(int i=0;i<3;i++)
cout<<(p->info).score[i]<<" ";
cout<<endl;
p=p->next;
}
cout<<endl<<endl;
}
void Display(LInkNode<STudent>* head,char*FileName) //保存文件(在文件中显示),其实跟在屏幕上显示一样的。
{//重载display(),在文件中保存。
ofstream ofile(FileName,ios::out);
if(!ofile)
{
cerr<<"open error!";
exit(1);
}
ofile.clear();
LInkNode<STudent> *p;
p=head->next;
while(p!=NULL)
{
ofile<<setw(15)<<left<<p->info.number;
ofile<<setw(10)<<left<<p->info.name;
for(int i=0;i<3;i++)
ofile<<setw(5)<<left<<p->info.score[i];
ofile<<endl;
p=p->next;
}
cout<<endl<<"保存数据到文件成功!"<<endl<<endl;
}
LInkNode<STudent> *FileGetValue(LInkNode<STudent>* head,char*FileName)//从文件中读取数据给链表。
{
ifstream infile(FileName,ios::in);
if(!infile)
{
cerr<<"无法打开!"<<endl;
exit(1);
}
LInkNode<STudent> *p;
long number;
char name[20];
float score[5];
infile.seekg(0);
while(!infile.eof())
{
infile>>number;
if(head->next!=NULL&&number==(head->next->info.number)){cout<<"从文件读取数据成功。"<<endl<<endl;return head;}//后面又读多个,具体讲是重复读了最后一个两次,没办法只好一重复就结束.
infile>>name;
for(int i=0;i<3;i++)
infile>>score[i];
p=new LInkNode<STudent>;
p->info.number=number;
strcpy(p->info.name,name);
for(i=0;i<3;i++)
p->info.score[i]=score[i];
p->next=head->next;
head->next=p;
}
cout<<"从文件读取数据成功。"<<endl<<endl;
return head;
}
LInkNode<STudent>* InPut(LInkList<STudent>List)
{
char FileName[20];
cout<<"请输入想用来贮存的数据文件名,格式例如:“成绩03信计06班.dat”"<<endl;
cin>>FileName;
cout<<endl;
LInkNode<STudent> *p;
char c='y';
while(c=='y'||c=='Y')
{
p=new LInkNode<STudent>;
p->info.GetValue();
List.InsertFront(p);
cout<<"继续输入学生数据请按y或者y,放弃输入请按n或者N:";
cin>>c;
}
Display(List.head,FileName);
return List.head;
}
void ClassInfo(LInkNode<STudent>*head)
{
float scave[5],scallave=0;
for(int i=0;i<3;i++)scave[i]=0;
int attenda=0,attend[5],lack[5];
for(i=0;i<3;i++)attend[i]=lack[i]=0;
int n=0;
LInkNode<STudent>*p;
p=new LInkNode<STudent>;
p=head->next;
while(p!=NULL)
{
n++;
for(i=0;i<3;i++)
{
scave[i]+=p->info.score[i];
if(p->info.score[i]!=0)attend[i]++;
}
p=p->next;
}
for(i=0;i<3;i++)
scallave+=scave[i];
for(i=0;i<3;i++)
attenda+=attend[i];
scallave=scallave/attenda;
for(i=0;i<3;i++)
scave[i]=scave[i]/attend[i];
for(i=0;i<3;i++)
lack[i]=n-attend[i];
cout<<right<<setfill('-')<<setw(20)<<"该班的情况是"<<setfill('-')<<setw(17)<<"-"<<endl<<endl;
for(i=0;i<3;i++)
{
cout<<"科目"<<i+1<<"的情况是:"<<endl;
cout<<"平均分为:"<<scave[i]<<endl;
cout<<"考试人数为:"<<attend[i]<<endl;
cout<<"缺考人数为:"<<lack[i]<<endl<<endl;
}
cout<<"该班的总平均分为:"<<scallave<<endl<<endl;
}
int main()
{
LInkList<STudent>List;
LInkNode<STudent>*head;
STudent *stu;
stu=new STudent;
char *filename;
int choice1,choice2=1;
while(1)
{
cout<<right<<setfill('-')<<setw(25)<<"主菜单"<<setfill('-')<<setw(25)<<"-"<<endl<<endl;
cout<<setfill(' ')<<setw(30)<<left<<"1:学生信息输入.";
cout<<setfill(' ')<<setw(30)<<left<<"2:在链表尾部插入数据."<<endl<<endl;
cout<<setfill(' ')<<setw(30)<<left<<"3:学生成绩查询.";
cout<<setfill(' ')<<setw(30)<<left<<"4:统计班级的整体情况."<<endl<<endl;
cout<<setfill(' ')<<setw(30)<<left<<"5:从文件读取数据,存入链表.";
cout<<setfill(' ')<<setw(30)<<left<<"6:在屏幕上显示链表信息."<<endl<<endl;
cout<<setfill(' ')<<setw(30)<<left<<"7:对班级的学生平均分排序.";
cout<<setfill(' ')<<setw(30)<<left<<"8:释放链表(但是保留头结点)."<<endl<<endl;
cout<<0<<":结束程序."<<endl<<endl;
cout<<setw(50)<<setfill('-')<<'-'<<endl<<endl;
cout<<"请选择n:";
cin>>choice1;
switch(choice1)
{
case 0:return 0;
case 1:head=InPut(List);break;
case 2:LInkNode<STudent>*p;
p=new LInkNode<STudent>;
p->info.GetValue();
p->next=NULL;
List.InsertEnd(p);
Display(List.head,filename);
break;
case 3:while(choice2)
{
cout<<right<<setfill('-')<<setw(17)<<"查询菜单"<<setfill('-')<<setw(17)<<"-"<<endl;
cout<<1<<"学号查询。"<<endl<<endl;
cout<<2<<":姓名查询."<<endl<<endl;
cout<<3<<":查看不及格科目及学生名单."<<endl<<endl;
cout<<0<<":返回上一层."<<endl;
cout<<setw(34)<<setfill('-')<<'-'<<endl;
cout<<"请选择:";
cin>>choice2;
switch(choice2)
{
case 1:stu->LocateNum(List.head);break;
case 2:stu->LocateName(List.head);break;
case 3:stu->LocateFail(List.head);break;
case 0:cout<<endl;break;
default:"输入数据错误.";break;
}
}break;
case 4:cout<<"请输入您想查看的班级文件名,格式例:“成绩03信计06班.dat”"<<endl;
filename=new char[30];
cin>>filename;
List.head=FileGetValue(List.head,filename);
ClassInfo(List.head);
break;
case 5: cout<<"请输入您想查看的文件名,格式例:“成绩03信计06班.dat”"<<endl;
filename=new char[30];
cin>>filename;
List.head=FileGetValue(List.head,filename);
break;
case 6:Display(List.head);break;
case 7:stu->MarkSort(List.head);break;
case 8:List.head=List.Release();break;
default:cout<<"数据有误."<<endl;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -