C++学生成绩管理系统

#C++学生成绩管理系统


这个我们程序设计课要求写的一个项目,埋头写了一个星期,最后的结果还是令我满意的。

  • 这个项目总共包含5个头文件和5个源文件。
  • 这个项目参考的是C++程序实际教程第十章——物流货仓管理系统。
  • 这个项目的源文件并未添加太多注释,主要是因为语言表达能力不行(都是借口,主要是太懒)。
  • 程序是在VS2017的环境下编写。

首先是头文件

然后是源文件

下面是头文件

control.h

#pragma once

/*
*这是主控制类,一切控制都是从这里开始,
*/

#include "manager.h"
#include "menu.h"
using namespace std;

class Control{
private:
	Manager t_manager;   //定义一个管理类对象                     
	int iChoice;		//用户选择的选项
public:
	Control();		//在这个构造函数中实现了对一级菜单的输出,对文件内容的输入,
					//和主控制函数的调用
	~Control();
	void MainControl(); //主控制函数
};

可以点击这里返回标题哦

manager.h

#pragma once

#include "studentList.h"
#include "menu.h"
using namespace std;
class Manager {
private:
	ifstream stuFile;//定义文件输入流
	string strStuFileName; // 学生信息文件名称
	studentList* stuInfoHead; // 定义学生信息链表
public:
	Manager(string t_strStuFileName, string t_strLogFileName);
	~Manager();
	void ReadRecord();// 从文件中读取数据
	void UpdateRecord(); // 更新数据到文件中
	void InventoryManager(int t_iChoice, int t_attributeChoice, vector<string> attribute);// 选项控制函数
};


可以点击这里返回标题哦

menu.h

#pragma once

#include <iostream>
#include <conio.h>
#include <windows.h>
#include <fstream>
#include <vector>
#include <string>

using namespace std;
//在指定位置输出
#define GOTOXY_PUT(out, x, y, val) 
do 
{ 
	COORD coord = { x, y };
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
	out << val; 
} 
while (0)
//在指定位置输入
#define GOTOXY_IN(cin, x, y, val)
do
{
	COORD coord = { x, y };
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
	cin >> val;
}
while(0)

/*INPUT_STUINFO在studentList类中AddStudent()函数、
manager类中ReadRecord()函数使用,用于输入数据 */
#define INPUT_STUINFO(in, stu) 
in >> stu.iNum 
>> stu.sName >> stu.sSex 
>> stu.iAge >> stu.iClass 
>> stu.iCplus >> stu.iEnglish 
>> stu.iMath>> stu.iProgramming

//用于交换学生链表数据域
#define CHANGE_STUINFO(before, now) 
do 
{ 
	before->iNum = now.iNum; 
	before->sName = now.sName; 
	before->sSex = now.sSex; 
	before->iAge = now.iAge; 
	before->iClass = now.iClass; 
	before->iCplus = now.iCplus; 
	before->iEnglish = now.iEnglish; 
	before->iMath = now.iMath; 
	before->iProgramming = now.iProgramming; 
}while(0)

//输出学生信息头
#define OUTPUT_HEAD(out) 
do 
{ 
	out << "学号	" 
	<< "姓名	" 
    << "性别	" 
	<< "年龄	" 
	<< "班级		" 
	<< "Cplusplus	" << "英语	" << "高等数学	" << "程序设计" << endl; 
	out << "----------------------------------------------
--------------------------------------------------" << endl;
} 
while(0)
// 输出学生信息
#define OUTPUT_STU(out, p) 
out << p->iNum << '	' 
	<< p->sName << '	' 
	<< p->sSex << '	' 
	<< p->iAge << '	' 
	<< p->iClass << '	' << '	' 
	<< p->iCplus << '	' << '	' 
	<< p->iEnglish << '	' 
	<< p->iMath << '	' << '	' 
	<< p->iProgramming << endl

class Menu {
public:
	static bool abnorma;//判断文件打开是否异常
public:
	static void MainMenu();//显示主菜单
	static void SubMenu();//显示分菜单
};


可以点击这里返回标题哦

student.h

#pragma once

/*
*	student.h
*
*定义了一个学生信息结构体,用于储存信息
*其中typedef是定义了一个类型别名
* 类型别名为 stuInfo
*/

#include <string>
typedef struct StuInfo{
	int iNum;
	std::string sName;
	std::string sSex;
	int iAge;
	int iClass;
	float iCplus;
	float iEnglish;
	float iMath;
	float iProgramming;
}stuInfo;


可以点击这里返回标题哦

studentList.h

#pragma once
#include "student.h"
#include "menu.h"
using namespace std;
class studentList {
private:
	StuInfo* t_stuInfo;//这里是链表的创建
	studentList* t_stuInfoNext;
public:
	string P_Position; //用于记录链表指针位置
private:
	static studentList* t_stuInfoHead;//定义一个链表头
	static studentList* t_stuInfoEnd;//链表尾
public:
	studentList();
	~studentList();
	void AddStudent(const stuInfo* p = nullptr);	//添加学生
	static studentList* GetListHead();				//获得链表的头,用于在manager类中使用的接口
	void ShowAllStuInfo(studentList* head = t_stuInfoHead)const; //显示传进链表头之后的所有学生信息
	void ShowStuInfo(studentList* t_p);//显示当前传入链表指针的学生信息
	studentList* IsSameStudent(const stuInfo& stu);//判断学号是否相同
	void EditStuInfo(StuInfo t_stu, int t_position);//编辑学生信息
	vector<studentList* > SearchStuInfo(vector<string> t_attribute, int t_choice);//寻找学生信息
	vector<studentList* > CompareStuInfo(string t_attribute, int t_choice); // 这个成员函数使用在SearchStuInfo成员函数中,用于匹配数据是否符合条件
	studentList* SortStuInfo(int t_choice);//排序
	void SwapStuInfo(studentList* ptr1, studentList* ptr2);//这个交换函数属于排序成员函数中,用于交换数据
	float sort_choice(int t_choice, studentList *p);//这个函数属于交换函数中,用于根据不同选项计较不同值
	vector<float> StatisticsStuInfo();//统计函数
	void DeleteStuInfo(int t_position);//删除学生数据
	void SaveFile(string file);//保存文件
	static float GetStuNumber();//获得学生数据个数
};


可以点击这里返回标题哦

接下来的就是源文件

control.cpp

#include "control.h"

Control::Control() : t_manager("student.txt", "log.txt") {
	Menu::MainMenu();
	t_manager.ReadRecord();
	MainControl();
}
Control::~Control() {}
void Control::MainControl() {
	while (true) {
		int attributeChoice = 0;
		vector<string> attribute;
		string temp;
		Menu::SubMenu();
		GOTOXY_IN(cin, 71, 17, iChoice);
		if (studentList::GetStuNumber() == 0) {}
		else if (iChoice == 3) {
			GOTOXY_PUT(cout, 60, 17,
				"请输入查询条件:");
			GOTOXY_PUT(cout, 60, 18,"(1. 学号, 2.姓名, 3.班级, 4.性别, 5.有一门挂科)");
			GOTOXY_IN(cin, 60, 19, attributeChoice);
			GOTOXY_PUT(cout, 60, 18,"请输入属性:(如选择“有一门挂科”请任意输入)            ");
			GOTOXY_PUT(cout, 60, 19, "  ");
			cin >> temp;
			attribute.push_back(temp);
		}
		else if (iChoice == 4) {
			GOTOXY_PUT(cout, 60, 17,
				"请输入需要修改学生学号:");
			attributeChoice = 1;
			cin >> temp;
			attribute.push_back(temp);
		}
		else if (iChoice == 5) {
			GOTOXY_PUT(cout, 60, 17,
				"请输入排序条件:");
			GOTOXY_PUT(cout, 60, 18, "(1.Cplusplus,2. 英语,3.高等数学,4.程序设计,5.总分):");
			GOTOXY_IN(cin, 60, 19, attributeChoice);
		}
		else if (iChoice == 7) {
			GOTOXY_PUT(cout, 60, 17,
				"请输入需要删除学生的学号:");
			GOTOXY_IN(cin, 60, 18, temp);
			attributeChoice = 1;
			attribute.push_back(temp);
		}
		t_manager.InventoryManager(iChoice, attributeChoice, attribute);
	}
}

可以点击这里返回标题哦

manager.cpp

#include "manager.h"

Manager:: Manager(string t_strStuFileName, string t_strLogFileName) :
	strStuFileName(t_strStuFileName),
	stuInfoHead(new studentList()) {
	stuFile.open(t_strStuFileName, ios::_Nocreate);
	if (!stuFile)
		Menu::abnorma = true;
	stuFile.open(t_strStuFileName, ios_base::out | ios_base::app);
}
Manager::~Manager() {}
void Manager::ReadRecord() {
	stuFile.open(strStuFileName, ios::in);
	stuFile.clear();
	stuFile.seekg(0, ios::beg);
	StuInfo stu;
	while (INPUT_STUINFO(stuFile, stu)) 
		stuInfoHead->AddStudent(&stu);
	stuFile.close();
}
void Manager::UpdateRecord() {
	auto str = strStuFileName + ".bak";
	stuInfoHead->SaveFile(str); 
	remove(strStuFileName.c_str());

	rename(str.c_str(), strStuFileName.c_str());
}
void Manager::InventoryManager(int t_iChoice, int t_attributeChoice, vector<string> attribute) {
	stuInfoHead = studentList::GetListHead();
	if (studentList::GetStuNumber() == 0 &&
		(t_iChoice == 1 || t_iChoice == 3 ||
			t_iChoice == 4 || t_iChoice == 5 ||
			t_iChoice == 6 || t_iChoice == 7 ||
			t_iChoice == 8)) {
		system("cls");
		cout << "当先系统中没有数据,请输入!";
		system("pause");
	}
	else if (t_iChoice == 1) {
		system("cls");
		stuInfoHead->ShowAllStuInfo(stuInfoHead);
		cout << "
学生信息显示完成,";
		system("pause");
	}
	else if (t_iChoice == 2) {
		system("cls");
		cout << "请按照以下格式输入数据:

";
		OUTPUT_HEAD(cout);
		stuInfoHead->AddStudent();
		cout << "
学生信息输入完成,";
		system("pause");
	}
	else if (t_iChoice == 3) {//剩选择5的一个输入问题
		system("cls");
		auto p = stuInfoHead->SearchStuInfo(attribute, t_attributeChoice);
		if (p.size() == 1) {
			cout << "未找到符合条件数据,";
			system("pause");
		}
		else {
			
			OUTPUT_HEAD(cout);
			for (int i = 0; i < p.size() - 1; i++)
				stuInfoHead->ShowStuInfo(p[i]);
			cout << "
显示完成,";
			system("pause");
		}
	} 
	else if (t_iChoice == 4) {//完成
		system("cls");
		auto p = stuInfoHead->SearchStuInfo(attribute, t_attributeChoice);
		if (p.size() == 1) {
			cout << "没有找到" << endl;
			system("pause");
			return;
		}
		else {
			cout << "显示学生原信息:
" << endl;
			OUTPUT_HEAD(cout);
			stuInfoHead->ShowStuInfo(p[0]);
			cout << "
请按以下格式修改数据" << endl;
			OUTPUT_HEAD(cout);
			stuInfo stu;
			INPUT_STUINFO(cin, stu);
			stuInfoHead->EditStuInfo(stu, stoi(p[1]->P_Position));
			cout << "修改完成,";
			system("pause");
		}
	}
	else if (t_iChoice == 5) {
		system("cls");
		auto p = stuInfoHead->SortStuInfo(t_attributeChoice);
		stuInfoHead->ShowAllStuInfo(p);
		cout << "
排序完成,";
		system("pause");
	}
	else if (t_iChoice == 6) {
		system("cls");
		vector<float> statistics;
		statistics = stuInfoHead->StatisticsStuInfo();
		cout << "当前学生总人数为:" << statistics[4] << endl;
		cout << "c++平均分:" << statistics[0] << endl;
		cout << "数学平均分:" << statistics[1] << endl;
		cout << "英语平均分:" << statistics[2] << endl;
		cout << "程序设计平均分:" << statistics[3] << endl;
		system("pause");
	}
	else if (t_iChoice == 7) {
		system("cls");
		auto p = stuInfoHead->SearchStuInfo(attribute, t_attributeChoice);
		if (p.size() == 1) {
			cout << "没有找到" << endl;
			system("pause");
			return;
		}
		else {
			cout << "显示学生原信息:
" << endl;
			OUTPUT_HEAD(cout);
			stuInfoHead->ShowStuInfo(p[0]);
			stuInfoHead->DeleteStuInfo(stoi(p[1]->P_Position));
			stuInfoHead = studentList::GetListHead();
			cout << "
数据已删除,";
			system("pause");
		}
	}
	else if (t_iChoice == 8) {
		system("cls");
		UpdateRecord();
		cout << "
文件已存储,";
		system("pause");
	}
	else if (t_iChoice == 0) {
		system("cls");
		GOTOXY_PUT(cout, 71, 22, "欢迎下次使用!");
		system("pause");
		exit(0);
	}
	else {  
		system("cls");
		GOTOXY_PUT(cout, 71, 17, "请选择对应的选项!");
		system("pause");
	}
}

可以点击这里返回标题哦

menu.cpp

#include "menu.h"

bool Menu::abnorma = false;

void Menu::MainMenu() {
	system("color 2F");
	system("title Student achievement management");
	system("cls");
	cout << "
		|--------学生信息管理系统---------|
";
	cout << "		|                                 |
";
	cout << "		|                                 |
";
	cout << "		|               欢                |
";
	cout << "		|                                 |
";
	cout << "		|                                 |
";
	cout << "		|               迎                |
";
	cout << "		|                                 |
";
	cout << "		|                                 |
";
	cout << "		|               使                |
";
	cout << "		|                                 |
";
	cout << "		|                                 |
";
	cout << "		|               用                |
";
	cout << "		|                                 |
";
	cout << "		|                                 |
";
	cout << "		|                                 |
";
	cout << "		|                                 |
";
	cout << "		|                                 |
";
	cout << "		|---------------------------------|	";
	if (abnorma == true)
		GOTOXY_PUT(cout, 60, 15, "文件不存在,已重新创建!");
	GOTOXY_PUT(cout, 60, 17, "系统运行正常!");
	system("pause");

}
void Menu::SubMenu() {
	system("cls");
	cout << "
		|--------学生信息管理系统---------|
";
	cout << "		|                                 |
";
	cout << "		|         1. 输出所有信息         |
";
	cout << "		|                                 |
";
	cout << "		|         2. 添加学生信息         |
";
	cout << "		|                                 |
";
	cout << "		|         3. 学生信息查询         |
";
	cout << "		|                                 |
";
	cout << "		|         4. 修改学生信息         |
";
	cout << "		|                                 |
";
	cout << "		|         5. 学生信息排序         |
";
	cout << "		|                                 |
";
	cout << "		|         6. 学生信息统计         |
";
	cout << "		|                                 |
";
	cout << "		|         7. 删除学生信息         |
";
	cout << "		|                                 |
";
	cout << "		|         8.   保存变更           |
";
	cout << "		|                                 |
";
	cout << "		|         0.    退出              |
";
	cout << "		|---------------------------------|	";
	GOTOXY_PUT(cout, 60, 17, "请选择功能:");
}

可以点击这里返回标题哦

main.cpp


#include "control.h"
int main(	) {
	Control a;
	system("pause");
}

可以点击这里返回标题哦

studentList.cpp

#include "studentList.h"

studentList* studentList::t_stuInfoHead = nullptr;
studentList* studentList::t_stuInfoEnd = nullptr;
studentList::studentList() :t_stuInfo(nullptr), t_stuInfoNext(nullptr) {
	//链表刚创建时,只存在一个节点,内容无效,头尾指针均指向该节点
	if (!(t_stuInfoHead || t_stuInfoEnd)) {
		t_stuInfoHead = this;
		t_stuInfoEnd = this;
	}
	P_Position = "";
}
studentList::~studentList() {}
void studentList::AddStudent(const stuInfo* p) {
	stuInfo stu;
	int choice = 0;
	if (!p)
		INPUT_STUINFO(cin, stu);
	else
		stu = *p;
	auto p1 = IsSameStudent(stu);
	if (p1) {
		cout << "您输入的学生信息在系统中已经存在,是否覆盖(1.覆盖, 2.取消)
";
		cin >> choice;
		if (choice == 1) {
			cout << "您输入的产品名称在系统中已存在,现将信息进行合并!" << endl;
			cout << "
原有信息如下:" << endl;
			OUTPUT_HEAD(cout);
			ShowStuInfo(p1);
			EditStuInfo(stu, stoi(p1->P_Position));
		}
	}
	if (t_stuInfoEnd && choice != 2 && choice != 1) {
		t_stuInfoEnd->t_stuInfo = new stuInfo(stu);
		t_stuInfoEnd->t_stuInfoNext = new studentList();
		t_stuInfoEnd = t_stuInfoEnd->t_stuInfoNext;
	}
}
studentList* studentList::GetListHead() {
	return t_stuInfoHead;
}
void studentList::ShowAllStuInfo(studentList* head)const {
	if (head == nullptr)
		return;
	auto p = head;
	OUTPUT_HEAD(cout);
	while (p->t_stuInfo) {
		OUTPUT_STU(cout, p->t_stuInfo);
		p = p->t_stuInfoNext;
	}
}
void studentList::ShowStuInfo(studentList* t_p) {
	auto p = t_p;
	OUTPUT_STU(cout, p->t_stuInfo);
}
studentList* studentList::IsSameStudent(const stuInfo& stu) {
	auto p = t_stuInfoHead;
	int i = 0;
	while (p->t_stuInfo) {
		if (p->t_stuInfo->iNum == stu.iNum) {
			p->P_Position = to_string(i);
			return p;
		}
		i++;
		p = p->t_stuInfoNext;
	}
	return nullptr;
}
void studentList::EditStuInfo(StuInfo t_stu, int t_position) {
	studentList *p = t_stuInfoHead; //注意这是指针,p记录了t_stuInfoHead的地址,只是地址
	for (int i = 0; i < t_position; i++)
		t_stuInfoHead = t_stuInfoHead->t_stuInfoNext;
	CHANGE_STUINFO(t_stuInfoHead->t_stuInfo, t_stu);
	cout << "修改完成!修改后结果如下
";
	ShowStuInfo(t_stuInfoHead);
	t_stuInfoHead = p;
}
vector<studentList* > studentList::SearchStuInfo(vector<string> t_attribute, int t_choice) {//返回多个链表指针
	vector<studentList*> p;
	p = CompareStuInfo(t_attribute[0], t_choice);
	return p;
}
vector<studentList* > studentList::CompareStuInfo(string t_attribute, int t_choice) {
	vector<studentList*> p_out;
	auto p = t_stuInfoHead;
	int i = 0;
	while (p->t_stuInfo) {
		if (t_choice == 1) {
			if (t_attribute == to_string(p->t_stuInfo->iNum)) {
				p_out.push_back(p);
				break;
			}
			i++;
		}
		else if (t_choice == 2) {
			if (t_attribute == p->t_stuInfo->sName)
				p_out.push_back(p);
		}

		else if (t_choice == 3) {
			if (t_attribute == to_string(p->t_stuInfo->iClass))
				p_out.push_back(p);
		}

		else if (t_choice == 4) {
			if (t_attribute == p->t_stuInfo->sSex)
				p_out.push_back(p);
		}
		else if (t_choice == 5) {
			if (p->t_stuInfo->iCplus < 60 ||
				p->t_stuInfo->iEnglish < 60 ||
				p->t_stuInfo->iMath < 60 ||
				p->t_stuInfo->iProgramming < 60)
				p_out.push_back(p);
		}
		p = p->t_stuInfoNext;
	}
	studentList* temp = new studentList;
	temp->P_Position = to_string(i);
	p_out.push_back(temp);
	return p_out;
}
studentList* studentList::SortStuInfo(int t_choice) {
	auto p = t_stuInfoHead;
	auto p1 = p;
	for (; p != t_stuInfoEnd; p = p->t_stuInfoNext)
		for (p1 = p->t_stuInfoNext; p1 != t_stuInfoEnd; p1 = p1->t_stuInfoNext)
			if (sort_choice(t_choice, p) < sort_choice(t_choice, p1))
				SwapStuInfo(p, p1);
	return t_stuInfoHead;
}
void studentList::SwapStuInfo(studentList* ptr1, studentList* ptr2) {
	stuInfo *temp;
	temp = ptr1->t_stuInfo;
	ptr1->t_stuInfo = ptr2->t_stuInfo;
	ptr2->t_stuInfo = temp;
}
float studentList::sort_choice(int t_choice, studentList *p) {
	return (t_choice == 1 ? p->t_stuInfo->iCplus :
		(t_choice == 2 ? p->t_stuInfo->iEnglish :
		(t_choice == 3 ? p->t_stuInfo->iMath :
			(t_choice == 4 ? p->t_stuInfo->iProgramming :
			(t_choice == 5 ? (p->t_stuInfo->iCplus +
				p->t_stuInfo->iEnglish +
				p->t_stuInfo->iMath +
				p->t_stuInfo->iProgramming) : -1)))));
}
vector<float> studentList::StatisticsStuInfo() {
	auto p = t_stuInfoHead;
	vector<float> out;
	float C = 0, math = 0, eng = 0, programming = 0;
	while (p->t_stuInfo) {
		C += p->t_stuInfo->iCplus;
		math += p->t_stuInfo->iMath;
		eng += p->t_stuInfo->iEnglish;
		programming += p->t_stuInfo->iProgramming;
		p = p->t_stuInfoNext;
	}
	out.push_back(C / GetStuNumber());
	out.push_back(math / GetStuNumber());
	out.push_back(eng / GetStuNumber());
	out.push_back(programming / GetStuNumber());
	out.push_back(GetStuNumber());
	return out;
}
void studentList::DeleteStuInfo(int t_position) {
	studentList *p = t_stuInfoHead;
	if (t_position == 0)
		t_stuInfoHead = t_stuInfoHead->t_stuInfoNext;
	else {
		for (int i = 0; i < t_position - 1; i++)
			t_stuInfoHead = t_stuInfoHead->t_stuInfoNext;
		t_stuInfoHead->t_stuInfoNext = t_stuInfoHead->t_stuInfoNext->t_stuInfoNext;
		t_stuInfoHead = p;
	}
}
void studentList::SaveFile(string file) {
	ofstream os(file, ios::out);
	auto p = t_stuInfoHead;
	while (p->t_stuInfo) {
		OUTPUT_STU(os, p->t_stuInfo);
		p = p->t_stuInfoNext;
	}
	os.close();
}
float studentList::GetStuNumber() {
	float i = 0;
	for (auto p = t_stuInfoHead; p != t_stuInfoEnd; p = p->t_stuInfoNext)
		i++;
	return i;
}

可以点击这里返回标题哦

下面是运行出来的效果
演示

原文地址:https://www.cnblogs.com/neverth/p/11760941.html