#C++学生成绩管理系统
这个我们程序设计课要求写的一个项目,埋头写了一个星期,最后的结果还是令我满意的。
首先是头文件
然后是源文件
下面是头文件
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 attribute);// 选项控制函数
};
可以点击这里返回标题哦
menu.h
#pragma once
#include
#include
#include
#include
#include
#include
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 << "学号\t" \
<< "姓名\t" \
<< "性别\t" \
<< "年龄\t" \
<< "班级\t\t" \
<< "Cplusplus\t" << "英语\t" << "高等数学\t" << "程序设计" << endl; \
out << "----------------------------------------------\
--------------------------------------------------" << endl;\
} \
while(0)
// 输出学生信息
#define OUTPUT_STU(out, p) \
out << p->iNum << '\t' \
<< p->sName << '\t' \
<< p->sSex << '\t' \
<< p->iAge << '\t' \
<< p->iClass << '\t' << '\t' \
<< p->iCplus << '\t' << '\t' \
<< p->iEnglish << '\t' \
<< p->iMath << '\t' << '\t' \
<< 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
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 SearchStuInfo(vector t_attribute, int t_choice);//寻找学生信息
vector 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 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 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 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 << "\n学生信息显示完成,";
system("pause");
}
else if (t_iChoice == 2) {
system("cls");
cout << "请按照以下格式输入数据:\n\n";
OUTPUT_HEAD(cout);
stuInfoHead->AddStudent();
cout << "\n学生信息输入完成,";
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 << "\n显示完成,";
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 << "显示学生原信息:\n" << endl;
OUTPUT_HEAD(cout);
stuInfoHead->ShowStuInfo(p[0]);
cout << "\n请按以下格式修改数据" << 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 << "\n排序完成,";
system("pause");
}
else if (t_iChoice == 6) {
system("cls");
vector 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 << "显示学生原信息:\n" << endl;
OUTPUT_HEAD(cout);
stuInfoHead->ShowStuInfo(p[0]);
stuInfoHead->DeleteStuInfo(stoi(p[1]->P_Position));
stuInfoHead = studentList::GetListHead();
cout << "\n数据已删除,";
system("pause");
}
}
else if (t_iChoice == 8) {
system("cls");
UpdateRecord();
cout << "\n文件已存储,";
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 << "\n\t\t|--------学生信息管理系统---------|\n";
cout << "\t\t| |\n";
cout << "\t\t| |\n";
cout << "\t\t| 欢 |\n";
cout << "\t\t| |\n";
cout << "\t\t| |\n";
cout << "\t\t| 迎 |\n";
cout << "\t\t| |\n";
cout << "\t\t| |\n";
cout << "\t\t| 使 |\n";
cout << "\t\t| |\n";
cout << "\t\t| |\n";
cout << "\t\t| 用 |\n";
cout << "\t\t| |\n";
cout << "\t\t| |\n";
cout << "\t\t| |\n";
cout << "\t\t| |\n";
cout << "\t\t| |\n";
cout << "\t\t|---------------------------------|\t";
if (abnorma == true)
GOTOXY_PUT(cout, 60, 15, "文件不存在,已重新创建!");
GOTOXY_PUT(cout, 60, 17, "系统运行正常!");
system("pause");
}
void Menu::SubMenu() {
system("cls");
cout << "\n\t\t|--------学生信息管理系统---------|\n";
cout << "\t\t| |\n";
cout << "\t\t| 1. 输出所有信息 |\n";
cout << "\t\t| |\n";
cout << "\t\t| 2. 添加学生信息 |\n";
cout << "\t\t| |\n";
cout << "\t\t| 3. 学生信息查询 |\n";
cout << "\t\t| |\n";
cout << "\t\t| 4. 修改学生信息 |\n";
cout << "\t\t| |\n";
cout << "\t\t| 5. 学生信息排序 |\n";
cout << "\t\t| |\n";
cout << "\t\t| 6. 学生信息统计 |\n";
cout << "\t\t| |\n";
cout << "\t\t| 7. 删除学生信息 |\n";
cout << "\t\t| |\n";
cout << "\t\t| 8. 保存变更 |\n";
cout << "\t\t| |\n";
cout << "\t\t| 0. 退出 |\n";
cout << "\t\t|---------------------------------|\t";
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.取消)\n";
cin >> choice;
if (choice == 1) {
cout << "您输入的产品名称在系统中已存在,现将信息进行合并!" << endl;
cout << "\n原有信息如下:" << 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 << "修改完成!修改后结果如下\n";
ShowStuInfo(t_stuInfoHead);
t_stuInfoHead = p;
}
vector studentList::SearchStuInfo(vector t_attribute, int t_choice) {//返回多个链表指针
vector p;
p = CompareStuInfo(t_attribute[0], t_choice);
return p;
}
vector studentList::CompareStuInfo(string t_attribute, int t_choice) {
vector 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 studentList::StatisticsStuInfo() {
auto p = t_stuInfoHead;
vector 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;
}
可以点击这里返回标题哦