C++课程设计大作业——学生学籍管理系统(含源码注释详细)

写在前面:欢迎来到「发奋的小张」的博客。我是小张,一名普通的在校大学生。在学习之余,用博客来记录我学习过程中的点点滴滴,也希望我的博客能够更给同样热爱学习热爱技术的你们带来收获!希望大家多多关照,我们一起成长一起进步。也希望大家多多支持我鸭,喜欢我就给我一个关注吧!

[题目] 设计一个学生学籍管理系统
学生信息包括:姓名、学号、性别和英语、数学、程序设计、体育成绩。
从键盘输入数据,建立数据文件student.dat。
实现对学生或学号查询,显示信息。
对所有学生,按照班级计算平均成绩。
分别按照英语、数学、程序设计和体育成绩排序生成结果文件。
[设计]建立student类存储学生信息,并通过vector输入学生数据、输出到文件、从文件读入学生数据,再进行下一步操作

源码:
#include <iostream>
#include <algorithm>
#include <string>
#include <fstream>
#include <vector>
#include <string>
using namespace std;

bool optNext();

//定义student类,存储学生信息
class student{
public:
	//构造函数
	student(fstream &);
	student(string, long, string, int, int, int, int)
	{
		this->name = name;
		this->stuID = stuID;
		this->sex = sex;
		this->enSc = enSc;
		this->maSc = maSc;
		this->peSc = peSc;
		this->prSc = prSc;
	}
	//获取学生信息
	//通过public类型函数访问private类型的学生数据
	int getEn(){
		return enSc;
	}
	int getMa(){
		return maSc;
	}
	int getPr(){
		return prSc;
	}
	int getPe(){
		return peSc;
	}

	//定义操作类
	friend bool disbyID(long);
	friend bool disbyName(string &);
	friend bool add();
	friend bool avgSc();
	friend bool resSc();
	friend bool readFile(fstream &infile);
	friend bool saveFile(ofstream &);
private:
	//定义学生属性
	string name;
	long stuID;
	string sex;
	int enSc;
	int maSc;
	int prSc;
	int peSc;
};


//存放学生信息,遍历学生信息
vector<student> vec;
vector<student>::iterator it;

bool readFile(fstream &infile){
	while (!infile.eof())
	{
		vec.push_back(infile);
		infile.get();
	}
	return true;
}
student::student(fstream &infile) {
	infile >> name;
	infile >> stuID;
	infile >> sex;
	infile >> enSc;
	infile >> maSc;
	infile >> prSc;
	infile >> peSc;
}
bool saveFile(ofstream &outfile){
	bool emptyCheck = true; //标志文件为空
	it = vec.begin();
	while (it != vec.end())
	{
		if (!emptyCheck)  //读入文件
			outfile << endl;  //如果是空文件则不添加回车符,否则先添加回车符再输出下一条学生数据
		outfile << it->name << " " << it->stuID << " " << it->sex
			<< " " << it->enSc << " " << it->maSc << " " << it->prSc << " " << it->peSc;
		it++;
		emptyCheck = false;  //标志文件不为空
	}
	return true;
}
//通过学号查找学生数据
bool disbyID(long id){
	it = vec.begin();
	do{
		if (it->stuID == id)  //如果找到了学号符合的学生数据则输出并结束查找
		{
			cout << it->name << " " << it->stuID << " " << it->sex << " " << it->enSc << " " << it->maSc << " " << it->prSc << " " << it->peSc << endl;
			break;
		}
		else it++;
	} while (it != vec.end());

	if (it == vec.end())  //如果查到最后一条数据也没有找到符合的学生则输出错误信息
	{
		cout << "没有找到符合的学生ID!" << endl;
	}
	return true;
}

//通过学生姓名查找学生数据
bool disbyName(string &name){
	it = vec.begin();
	do{
		if (it->name == name)  //如果找到了姓名符合的学生数据则输出并结束查找
		{
			cout << it->name << " " << it->stuID << " " << it->sex << " " << it->enSc << " " << it->maSc << " " << it->prSc << " " << it->peSc << endl;
			break;
		}
		else it++;
	} while (it != vec.end());

	if (it == vec.end())  //如果查到最后一条数据也没有找到符合的学生则输出错误信息
	{
		cout << "没有找到符合的学生姓名!" << endl;
	}
	return true;
}
//添加一条新的学生数据
bool add(){
	string name;
	long stuID;
	string sex;
	int enSc;
	int maSc;
	int peSc;
	int prSc;

	cout << "请输入学生信息: " << endl;
	cout << "name: ";
	cin >> name;
	cout << "学生 ID: ";
	cin >> stuID;
	cout << "学生 性别[男/女]: ";
	cin >> sex;
	cout << "学生英语成绩: ";
	cin >> enSc;
	cout << "学生数学成绩: ";
	cin >> maSc;
	cout << "学生程序设计成绩: ";
	cin >> prSc;
	cout << "学生体育成绩: ";
	cin >> peSc;

	//将新添加的学生数据压栈入vector
	vec.push_back(student(name, stuID, sex, enSc, maSc, prSc, peSc));
	return true;
}


//计算学生每一门平均成绩
bool avgSc(){
	int i;
	float sumEn = 0, avgEn = 0;
	float sumMa = 0, avgMa = 0;
	float sumPr = 0, avgPr = 0;
	float sumPe = 0, avgPe = 0;
	it = vec.begin();
	for (i = 0; it != vec.end(); it++, i++)
	{
		sumEn += (float)it->enSc;
		sumMa += (float)it->maSc;
		sumPr += (float)it->prSc;
		sumPe += (float)it->peSc;
	}
	avgEn = sumEn / (float)i;
	avgMa = sumMa / (float)i;
	avgPr = sumPr / (float)i;
	avgPe = sumPe / (float)i;

	cout << "英语: " << avgEn << "  数学: " << avgMa << "  程序设计: " << avgPr << "  体育: " << avgPe << endl;
	return true;
}

//按照各门成绩排序方法
bool cmpEnglish(student a, student b)
{
	return a.getEn()>b.getEn();
}
bool cmpMath(student a, student b)
{
	return a.getMa()>b.getMa();
}
bool cmpProgramming(student a, student b)
{
	return a.getPr()>b.getPr();
}
bool cmpPE(student a, student b)
{
	return a.getPe()>b.getPe();
}

//按各门成绩排序并输出文件
bool resSc()
{
	ofstream outfile_en("English.dat", ios::out);  //打开English.dat文件并建立输入流
	if (!outfile_en){
		cout << "open error!" << endl;  //打开失败则报错
		exit(1);
	}
	sort(vec.begin(), vec.end(), cmpEnglish);  //按照英语成绩排序
	vector<student>::iterator iter_en;
	for (iter_en = vec.begin(); iter_en != vec.end(); iter_en++)  //输出到文件
	{
		outfile_en << iter_en->name << " " << iter_en->stuID << " " << iter_en->sex << " " << iter_en->enSc << " " << iter_en->maSc << " " << iter_en->prSc << " " << iter_en->peSc << endl;
	}
	outfile_en.close();  //关闭输入流


	ofstream outfile_ma("Math.dat", ios::out);
	if (!outfile_ma){
		cout << "open error!" << endl;
		exit(1);
	}
	sort(vec.begin(), vec.end(), cmpMath);
	vector<student>::iterator iter_ma;
	for (iter_ma = vec.begin(); iter_ma != vec.end(); iter_ma++)
	{
		outfile_ma << iter_ma->name << " " << iter_ma->stuID << " " << iter_ma->sex << " " << iter_ma->enSc << " " << iter_ma->maSc << " " << iter_ma->prSc << " " << iter_ma->peSc << endl;
	}
	outfile_ma.close();


	ofstream outfile_pro("Program.dat", ios::out);
	if (!outfile_pro){
		cout << "open error!" << endl;
		exit(1);
	}
	sort(vec.begin(), vec.end(), cmpProgramming);
	vector<student>::iterator iter_pr;
	for (iter_pr = vec.begin(); iter_pr != vec.end(); iter_pr++)
	{
		outfile_pro << iter_pr->name << " " << iter_pr->stuID << " " << iter_pr->sex << " " << iter_pr->enSc << " " << iter_pr->maSc << " " << iter_pr->prSc << " " << iter_pr->peSc << endl;
	}
	outfile_pro.close();


	ofstream outfile_pe("PE.dat", ios::out);
	if (!outfile_pe){
		cerr << "open error!" << endl;
		exit(1);
	}
	sort(vec.begin(), vec.end(), cmpPE);
	vector<student>::iterator iter_pe;
	for (iter_pe = vec.begin(); iter_pe != vec.end(); iter_pe++)
	{
		outfile_pe << iter_pe->name << " " << iter_pe->stuID << " " << iter_pe->sex << " " << iter_pe->enSc << " " << iter_pe->maSc << " " << iter_pe->prSc << " " << iter_pe->peSc << endl;
	}
	outfile_pe.close();
	cout << "output succeed!" << endl;
	return true;
}

bool optNext(){
	string opt2;
	int exit_ck = 1;
	while (exit_ck) {  //循环结构,在选择每个选项后再次执行这一步
		cout << "A:查询学生ID" << endl;
		cout << "B:查询学生姓名" << endl;
		cout << "C:统计平均成绩" << endl;
		cout << "D:成绩保存到文件" << endl;
		cout << "X:退出" << endl;
		cin >> opt2;
		if (opt2 == "A") {
			long sID;
			cout << "请输入学生ID: " << endl;
			cin >> sID;
			disbyID(sID);
		}
		if (opt2 == "B") {
			string sName;
			cout << "请输入学生姓名: " << endl;
			cin >> sName;
			disbyName(sName);
		}
		if (opt2 == "C"){
			avgSc();
		}
		if (opt2 == "D"){
			resSc();
		}
		if (opt2 == "X")  //标记退出符号,在下次循环开始时退出
			exit_ck = 0;
	}
	return true;
}
int main()
{
	string opt1;
	cout << "A:读取学生信息" << endl;
	cout << "B:新建学生信息" << endl;

	cin >> opt1;

	if (opt1 == "A") //read from existed file
	{
		cout << "输入学生信息读取文件: " << endl;
		string fileName1;
		cin >> fileName1;

		fstream infile(fileName1);
		if (!infile) {
			cout << "文件打开失败!" << endl;
			exit(0);
		}
		readFile(infile);
		optNext();
	}

	else if (opt1 == "B"){  //enter new student data
		cout << "请输入添加的学生数量: " << endl;
		int n;
		cin >> n;
		for (int i = 0; i < n; ++i)
			add();
		cout << "信息添加成功,请输入保存的文件名: ";
		string fileName2;
		cin >> fileName2;
		ofstream outFile(fileName2, fstream::trunc | fstream::out);
		cout << "保存中......" << endl;
		saveFile(outFile);
		cout << "保存成功!" << endl;
		outFile.close();
		optNext();
	}

	return 0;
}
[小结]

在第一次建立输出到文件的函数时,没有考虑到回车符和eof,导致在最后一条数据输出到文件后多数出了一个回车符,在下次读入时会多读入一条空数据,解决方案是加入一个bool标记标志文件是否为空,当文件为空时不输出回车符,否则先输出回车符再输出下一条学生数据。

[运行结果]

系统截图如下
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

博主后记:

希望看到此篇博文的小伙伴,如果发现有什么不对的地方,欢迎在下方留言指正!博主一定虚心接受并改正!大家一起共同进步。如果对你有所帮助,可以给博主一个赞👍。

  • 29
    点赞
  • 282
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值