⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 学生成绩2.cpp

📁 设计一个学生成绩管理系统
💻 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 + -