教务管理系统C++实现

本文根据题目要求,通过实现了一个教务管理系统。在由于题目中给出的一些不合理要求,代码存在冗余结构。最终程序能实现基本的用户登录、查看学生列表、修改信息等功能。
教务管理系统完整代码

1. 需求分析

1.1 性能需求

本课程设计以软件工程方法为指导,采用了多文件结构和面向对象的程序设计方法,以C++语言技术为基础,熟练面向对象程序设计(C++)实验指导和c++程序设计语言教科书的内容,使用Visual Stdio 2019为主要开发工具,对职工工资管理系统进行了需求分析,总体设计,详细设计,最终完成系统的实现与测试。

1.2 功能需求

本软件的使用者有三个,首先需要进行登录和密码校验,然后才有资格查看和修改数据。三个用户分别是教务处工作人员、主修系教务员、辅修系教务员,程序需要满足他们对学生基本信息的查看和修改需要。
全部功能列表如下

0:教务处工作人员:
		0:查看学生列表;
		1:查看学生信息;
        2:修改学生信息;
        3:删除学生信息;
        4:重新选择身份;
        5:更改密码;
        6:退出系统。
1:主修系教务员:
		0:查看学生列表;
        1:查看学生信息;
        2:录入主修成绩;
        3:查看成绩优秀的同学;
        4:查看需要补考的同学;
        5:重新选择身份;
        6:更改密码;
        7:退出系统。
2:辅修系教务员:
		0:查看学生列表;
		1:查看学生信息;
		2:设置辅修专业;
		3:录入辅修成绩;
		4:查看需要补考的同学;
		5:重新选择身份;
		6:更改密码;
		7:退出系统。
3:退出系统。

2.概要设计

2.1功能模块设计

文件结构

程序文件
	mian.cpp     //整体流程控制
	base.h		//学生的基本信息、主修科目、辅修科目对应的Base,First,Fbase三个类的声明
	base.cpp	//上述三个类的具体实现 
	index.h		//索引类
	index.cpp	//索引类的实现
	dialog.h	//对话界面的声明
	dialog.cpp	//对话界面的实现
	tool.h		//一些经常被调用的函数的声明
	tool.cpp	//函数的实现
数据文件  
    student.txt  //为自然数,保存学生的基本信息的一系列文件
    major.txt 	//为自然数,保存学生的主修科目信息的一系列文件
    mimor.txt	//为自然数,保存学生的辅修科目信息的一系列文件
    password.txt	//保存用户密码
    index.txt		//索引文件的备份

2.2 类的分析与设计

每个学生的信息分为三个部分,即基本信息、主修科目分数、辅修科目分数,分别用三个类来实现Base、First、Fbase来实现这三个对象的功能。类的声明如下:

#pragma once
#include
#include"tool.h"
#include 

using namespace std;

constexpr auto MDEPT_NUM = 5; //主修科目有5个
constexpr auto FDEP_NUM = 4;//辅修科目有4个

class Base
{
public:
	void InfoInput();        //输入基本信息
	void Info();             //显示基本信息
	void save(string);       //读取信息
	void read(string);       //保存信息
private:
	long num=0;              //学号
	char name[20] ="NULL";   //姓名
	int sex;                 //性别,0表示男,1表示女
	int age;                 //年龄
	char addr[30];           //地址
	char mdept[30];          //主修专业

};


class First: public Base
{
public:
	void MscoreInput();      //录入成绩
	void display();          //显示成绩
	int getscore(int);       //获取单科成绩
	void save(string);       //保存文件
	void read(string );      //读取文件
	bool outstand();         //是否三门课达到85分,并且其他两门分数不低于70
	bool resit();            //有一门不及格则返回值为真
private:
	float Mscore[60] = {0};//主修分数
};

  
class Fbase:public Base
{

public:
	void FdepSet();        //设置辅修专业名称
	void FscoreInput();    //输入辅修专业分数
	bool resit();          //有一门不及格则返回值为真
	int getscore(int);     //获取某一个辅修专业科目的分数
	void display();        //展示辅修专业分数
	void save(string);     //保存数据
	void read(string a);   //读取数据
	char fdep[30] = {'\0'};//辅修专业
private:
	float Fscore[35] = {0};//辅修分数

};

要处理大量数据,需要建立索引,来实现对信息的查找,所以建立Index类来实现索引的建立和查找。

#pragma once
#include
#include"tool.h"
constexpr auto MAX_INDEX = 100;

class Index
{
public:
	Index();                     //建立索引,供初始化时使用
	void create();               //建立索引,供已经实例化之后重建索引使用
	int search(int);             //按学号检索,并返回索引位置
	int search(string);          //按姓名检索,并返回索引位置
    int select();                //引导用户输入并按输入类型查找
	void show();                 //显示全部索引列表
	void show(int n);            //显示单个学生的学号和姓名
private:
	int num[MAX_INDEX]{};
	string name[MAX_INDEX]{};
};

由于在函数编写过程中,经常有一些重复的程序片段,把这些片段整合在tool.h文件中,以便调用。

bool interval(int a, int min, int max); //判断变量是否在区间内
int inputnumber(int a= 2147483647);     //输入一个数字,并确保不发生错误,a为数值上限
float inputfloat(int a);                //参数为数字上限
void clear(string);                     //清除一个学生的数据

此外,为了进行用户与系统的交互,编写了一系列对话函数,并整合到类Dialog中。

#pragma once
#include"tool.h"
#include"index.h"

class Dialog
{
public:
	int select(Index m);            //选择学生序号
	bool KeyCheck(int n);           //检查密码,n为不同用户的代号
	void KeyReset(int n);           //更改密码,n为不同用户的代号
	int logon();                    //登录界面
	int AdmissionOpt();             //教务处工作人员的对话框
	int M_teacherOpt();             //主修专业教务员的对话框
	int F_teacherOpt();             //辅修专业教务员的对话框
};

2.3 数据文件的命名和存储规则

学生的基本信息采用“student+序号+.txt”的格式命名,每名学生的信息存储在相应的文件中,例如序号为0的学生信息文件名为“student0.txt”;主修科目信息和辅修科目信息同样采用类似的方式命名。“student.txt”记录的变量有六个,对应Base类中的num、name、sex、 age、addr、mdept六个变量。

3.详细设计

3.1程序运行流程控制

程序的流程控制由main()函数实现,程序的简要流程如下。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NMD3J4XR-1611562775956)(E:\Documents\MD文稿\流程控制.png)]

程序开始所声明的对象如下:

Base student;              //处理学生基本信息的对象
First major;               //处理主修专业的对象
Fbase minor;               //处理辅修专业的对象
int n;                     //由于传递索引的变量                
bool logoned = false;      //用户登录状态变量
Index index;               //建立索引
Dialog dialog;             //供调用的对话框系列函数

程序的流程控制通过while()循环和 switch()的嵌套来实现,并将变量logoned作为循环判断依据。简化后的代码如下:

while (!logoned)//如未登录则开始登录会话
{
    switch (dialog.logon())//调用登录对话框,选择登录身份
    {
    case 0://以下是招生处的功能
        logoned = true;  //已登录
        while (logoned)  //如已登录则开始会话,在后面的程序运行中,如果用户选择登出,则跳出循环
            {
                switch (dialog.AdmissionOpt())//根据用户输入,选择相应功能
                {
                case 0://展示学生列表
                case 1://检索并查看信息
                case 2://修改信息
                case 3://删除信息
                case 4://重新选择登录身份
                    logoned = false;     //用户登出,跳出循环
                    break;
                case 5:    //更改密码
                    dialog.KeyReset(0);
                    break;
                case 6:
                    return 0;   //程序结束
                default:
                    break;
                }
            }
    
            break;//招生处功能模块结束


        case 1://以下是主修教务员的功能
            logoned = true;
            while (logoned)
            {
                switch (dialog.M_teacherOpt())
                {
                case 0://查看学生列表
                case 1://查看学生信息,选择学生序号,显示基本信息和主修科目分数
                case 2://修改成绩信息并保存
                case 3://筛选出成绩优秀的学生
                case 4://筛选出需要补考的学生
                case 5://重新选择身份
                    logoned = false;
                    break;
                case 6://更改密码
                case 7://退出程序
                    return 0;
                default:
                    break;
                }
            }
    
            break;//主修教务员模块结束
    
        case 2://以下是辅修教务员的功能
            logoned = true;
            while (logoned)
            {
                switch (dialog.F_teacherOpt())
                {
                case 0:
                case 1://查看学生信息
                case 2://设置辅修科目
                case 3://录入辅修成绩
                case 4://查看需要补考人员
                case 5://重新选择身份
                    logoned = false;
                    break;
                case 6://更改密码
                    dialog.KeyReset(2);
                    break;
                case 7://退出程序
                    return 0;
                default:
                    break;
                }
            }
            break;//辅修教务员功能模块结束


        case 3://用户选择退出系统
            return 0;
    
        case -1://密码校验失败,重新选择身份
            logoned = false;
            break;
        default:
            break;
        }
    }

}

3.2 索引的建立与查找

3.2.1 索引的建立

索引的建立是的进行数据管理的关键,具体的建立方法如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kBoWcPW1-1611562775962)(E:\Documents\MD文稿\建立索引.png)]

Index::Index()
{
	create();  //在对象声明时即建立索引
}

void Index::create()  //程序运行过程中需要更新索引,即可使用此函数
{
	ifstream file;
	ofstream outfile;

	outfile.open("data\\index.txt");

	for (int i = 0; i < MAX_INDEX; i++)
	{
		file.open("data\\student"+to_string(i)+".txt",ios::in);//按命名规则依次打开数据文件
		if (file.is_open())
		{
			file >> num[i]>>name[i] ;//如果成功打开则读取数据保存至数组中相应的位置上
		}
		else
		{
			num[i] = 0;           //未成功打开则相应的位置设置为默认值
			name[i] ="NULL";
		}
		file.close();
		outfile << "[id]\t" << i << "\n[num]\t" << num[i] << "\n[name]\t" <
3.3.2 索引查找

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hpLF0jT3-1611562775966)(E:\Documents\MD文稿\查找索引.png)]

索引建立之后,最基本的功能是查找数值在数组中的位置。Index类提供了两种查找方式,可以查找姓名或学号所在的位置,通过对这两个函数的调用,还形成int Index::select()方法,直接供用户查找,下面是程序代码。

int Index::search(int n) 
{
	for (int i = 0; i < MAX_INDEX; i++)
	{
		if (num[i] == n) return i;
	}
	return -1;
}

int Index::search(string n)
{
	for (int i = 0; i < MAX_INDEX; i++)
	{
		if (name[i]==n) return i;
	}
	return -1;
}

int Index::select()
{
	int n,i;
	string str;
	cout << "请输入要查看学生学号或姓名:" ;
	if (!(cin>>n))//尝试按int型读取用户的输入
	{
		cin.clear(); //清除错误警告
		cin >> str;  //按字符串读取输入的内容
		i = search(str);//调用姓名查找方法
	}
	else
	{
		i = search(n);//调用学号查找方法
	}
	return i;
}

此外,Index类还提供展示索引列表的功能

void Index::show()
{
	for (int i = 0; i < MAX_INDEX; i++)
	{
		if (num[i] == 0)  continue;
		cout << "序号:" <

3.3 学生基本信息的处理

Base类提供了对学生基本信息的读取、保存、展示、录入的方法。

具体实现如下:

void Base::InfoInput()  //引导用户输入信息
{
	cout << "请输入该生的学号:" << endl;
	num = inputnumber();
	cout << "请输入该生的姓名:" << endl;
	cin >> name;
	cout << "请输入该生的性别(0表示男,1表示女):" << endl;
	sex = inputnumber(1);
	cout << "请输入该生的年龄:" << endl;
	age = inputnumber(200);
	cout << "请输入该生的地址:" << endl;
	cin >> addr;
	cout << "请输入该生的主修专业:" << endl;
	cin >> mdept;
	cout << "学生" << name << "的基本信息录入完成\n";
}

void Base::Info()  //展示相关信息
{
	if (num == 0)
	{
		cout << "信息尚未录入!" << endl;
	}
	else
	{
		cout << "学号:" << num << "\n姓名:" << name << "\n性别:";
		if (sex)  	cout << "女";
		else cout << "男";
		cout << "\n年龄:" << age << "\n地址:" << addr << "\n主修专业:" << mdept << endl;
	}
}

void Base::save(string a)
{
	ofstream outfile;
	outfile.open("data\\student" + a + ".txt", ios::out | ios::trunc);
	outfile << num << endl << name << endl << sex << endl << age << endl << addr << endl << mdept << endl;
	outfile.close();
}

void Base::read(string a)
{
	ifstream infile;
	infile.open("data\\student" + a + ".txt", ios::in);
	if (infile.good())
	{
	infile >> num >> name >> sex >> age >> addr >> mdept;
	}
	infile.close();
}

3.4 学生主修科目分数的处理

First类除了对主修分数的读取、保存、展示和录入功能,还提供了对学生是否成绩优秀、是否需要补考的判断方法bool First::outstand()bool First::resit()。具体实现方法如下:

bool First::outstand()
{
	int t;
	int m = 0;
	int n = 0;
	for (int i = 0; i < MDEPT_NUM; i++)
	{
		t = getscore(i);
		if (t >= 85) m++;
		if (t < 70) n++;
	}
	if (m >= 3 && n <= 0)		return true;
	else return false;
}

bool First::resit()
{
	bool record = false;//检查是否已经被记录
	bool fail = false;//检查是否不及格
	for (int i = 0; i < MDEPT_NUM; i++)
	{
		if (getscore(i) < 60) fail = true;
		if (getscore(i) > 0) record = true;
	}
	return fail&&record;
}

学生辅修科目的处理由Fbase类实现,实现方法与前两个类相似,这里不再赘述。

3.5 人机交互用户界面的实现

3.5.1 登录和密码校验界面

登录界面是用户打开程序之后的主界面,int Dialog::logon()根据提示用户输入不同选项,并产生相应的返回值,决定主函数的跳转。当用户输入012时,将以进行密码检查,密码正确即可进入相应功能界面,否则要重新登录。

int Dialog::logon()//登录系统
{
	int a;
	cout << "欢迎登录教务管理!" << endl;
	cout << "请选择您的身份\n0:招生办工作人员\n1:主修系教务员\n2:辅修系教务员\n3:退出系统" << endl;
	a = inputnumber(3);
	if (a == 3)	return 3;//3对应退出系统选项
	else if (KeyCheck(a))
	{
		cout << "登录成功!" << endl;
		return a;
	}
	else
	{
		cout << "密码错误请重新登录" << endl;
		return -1;
	}
}

用户密码是一个整数,进行密码检查时,会从文件读取已保存的密码,然后提示用户输入密码,当用户选择的身份与密码相对于时,则通过校验。

bool Dialog::KeyCheck(int n)//n为不同用户的代号
{
	int password[3]{};
	int key;
	ifstream infile;
	infile.open("data\\password.txt", ios::in);
	if (infile.good())
	{
		infile >> password[0] >> password[1] >> password[2];
	}
	infile.close();
	cout << "请输入密码:";
	key = inputnumber();
	if (password[n] == key) return true;
	else  return false;
}
3.5.2 功能选择界面

当用户以某一身份登录成功后,将会进行引导用户进行功能选择,返回值将用于控制主程序的跳转。下面是主修系教务员的功能选择界面的代码。

int Dialog::M_teacherOpt()
{
	int a;
	cout << "请输入要进行的操作\n0:查看学生列表\n1:查看学生信息\n2:录入主修成绩\n3:查看成绩优秀的同学\n4:查看需要补考的同学\n5:重新选择身份\n6:更改密码\n7:退出系统" << endl;
	a = inputnumber(7);
	return a;
}

4 具体功能的实现

4.1 查看学生列表

当用户选择查看学生列表时,直接调用Indexvoid Index::show()功能,这里不再赘述。

4.2 查看单个学生信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WcOwFKRG-1611562775969)(E:\Documents\MD文稿\查看单个学生信息.png)]

case 1:                                    //检索并查看信息
	n = index.select();                    //让用户通过输入学号或姓名来检索要展示的数据
    if (n == -1)                           //返回值为“-1”代表未检索到相关信息
    {
        cout << "此信息不存在!" << endl;
        break;
    }
	student.read(to_string(n));            //读取磁盘信息到对象
	student.Info();                        //展示读取到的信息
	break;

4.3 修改学生信息

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SZoxgn3Y-1611562775971)(E:\Documents\MD文稿\修改信息.png)]

case 2:                                    //修改信息
	n = index.select();
	if (n==-1)                                    
	{
		cout << "信息不存在,请录入" << endl;
		n=index.search(0);                 //如果学号不存在,则选择一个空位置。
	}
	else
	{
		cout << "信息已存在,是否修改?\n不修改请输入0,修改请输入1" << endl;    
		if(inputnumber(1)==0) break;
	}
	student.InfoInput();                     //输入对象信息
	student.save(to_string(n));              //保存相应信息
	index.create();                          //重新建立索引
	break;

4.4 删除学生信息

case 3:           //删除信息
	n = index.select();;
	if (n==-1)
	{
		cout << "此人信息不存在!" << endl;
    	break;
	}
	else
	{
		clear(to_string(n));    //调用函数清空相应信息
		index.create();         //重建索引
		cout << "删除成功" << endl;
	}
	break;

4.5 录入学生成绩

case 2://修改成绩信息并保存 
	n = index.select();                //查找学生序号
	if (n==-1)                         //如果基本信息尚未录入,则不能修改成绩
	{
		cout << "此人不存在!" << endl;  
		break;
	}
	major.MscoreInput();                //输入成绩
    major.save(to_string(n));           //按命名规则保存
	break;

4.6 筛选出成绩优秀的学生

case 3://筛选出成绩优秀的学生
	for (int i = 0; i < MAX_INDEX; i++) 
	{
		major.read(to_string(i));      //遍历文件
		if (major.outstand())          //调用判断方法
		{
			index.show(i);             //展示姓名和学号
			major.display();           //展示分数
		}
	}
	cout << "以上是成绩优秀的学生。\n" << endl;
	break;

4.7 筛选出需要补考的学生

case 4://筛选出需要补考的学生
	for (int i = 0; i < MAX_INDEX; i++)
	{
		major.read(to_string(i));
		if (major.resit())
        {
            index.show(i);
            major.display();
        }
    }
	cout << "以上是需要补考的学生。\n" << endl;
	break;
case 2://设置辅修科目
	n = index.select();
	if (n == -1)
    {
        cout << "此人不存在!" << endl;//如果基本信息尚未录入,则不能修改成绩
 		break;
	}
	minor.FdepSet();
	minor.save(to_string(n));
	break;

4.系统分析与测试

5.使用说明

本软件可在windows X86/64平台上运行;

运行需保证同目录下存在名为“data”的文件夹,以保证数据文件的正常存储和读取;

用户密码是默认是“0”;

参考文献

附录:源程序清单

你可能感兴趣的:(c++,面向对象编程)