一、课程设计目的

通过设计一个小型的应用系统,使学生进一步掌握面向对象的程序设计方法,运用C++中的类与对象的概念结合面向对象程序设计的思想,独立完成应用系统的设计,并养成良好的编程习惯。通过这个实践教学平台,培养学生对计算机应用系统的综合设计能力,培养学生正确分析和解决问题的能力,了解系统开发的过程,逐步熟悉程序设计的方法。

二、课程设计题目及内容

题目:学生学籍管理系统

设计一个程序,对学生的学籍信息进行管理。通过该系统实现对学生基本信息的录入、保存、删除、修改、查询等操作。

设计要求及提示如下:

  1. 学生基本信息包括:学号、姓名、性别、年龄、班号、专业名称、系别等。

  2. 使用类和对象的概念实现程序设计。

  3. 以菜单形式显示各功能项。

  4. 各功能项如下:
    (1)学生基本信息的录入。
    (2)学生基本信息的删除。
    (3)学生基本信息的修改。
    (4)学生基本信息的查询。

     	(a)按学号查询单个学生信息;
     	(b)按姓名查询单个学生信息;
     	(c)按性别查询学生信息;
     	(d)按班号查询学生信息;
    

    (5)学生基本信息的统计。

     	(a)按性别统计学生人数;
     	(b)按班号统计学生人数;
     	(c)按年龄统计学生人数;
     	(d)按系别统计学生人数;
    

    (6)退出系统。

  5. 执行某个功能之后,程序将重新显示菜单供用户选择。

  6. 将学生学籍信息保存到文件中。

三、实验内容及原理

1. 程序中使用的数据及主要符号说明

	stu ——用vector容器创建动态数组,将Student类对象的信息存放至此。
	total——该学生学籍管理系统的学生总数
	Number——Student类数据成员(学号)
	Name——Student类数据成员(姓名)
	Gender——Student类数据成员(性别)
	Age——Student类数据成员(年龄)
	Class——Student类数据成员(班号)
	Major——Student类数据成员(专业名称)
	Department——Student类数据成员(系别)
	Student::setStu()——Student类成员函数(设置成员信息)
	Student::showStu()——Student类成员函数(展示成员信息)
	Input()——录入信息函数
	Delete()——删除信息函数
	Recompose()——修改学生信息函数
	Find()——查询学生的信息函数
	Count()——统计学生信息函数
	DeleteFirstLine()——删除文件中的第一行函数
	PutOutFile()——读取文件中的数据函数(out是指数据从文件中出来)
	PutInFlie()——将学生信息存储(写入)到文件中(in是指数据进入文件)

2. 每个功能模块的设计分析及算法描述

(1)信息录入功能模块:

void Input()           //录入信息函数
{
	int n;          //要录入信息的学生人数
	cout << "执行“录入学生信息”操作---------->请输入要录入信息的学生人数:";
	cin >> n;
	cout << "请依次输入学生的学号、姓名、性别、年龄、班号、专业名称、系别:" << endl;
	for (int i = 0; i < n; i++)
	{
		Student S;
		S.setStu();
		stu.push_back(S);    //将输入的学生信息放入vector<Student>容器中
	}
	total += n;
}
/*
创建一个vector容器stu来存放录入的学生信息,根据用户输入的录入人数n,循环n次,
创建Student类对象S,调用其成员函数setStu()输入学生的信息,然后插入容器stu的
尾部,完成录入操作。
*/

(2)信息删除功能模块:

void Delete()          //删除信息函数
{
	cout << "执行“删除学生信息”操作---------->请输入要删除学生的学号:";
	string num;
	cin >> num;
	//用迭代器来遍历容器所有元素,用于查找和删除
	vector<Student>::iterator it = stu.begin();
	for (; it != stu.end(); it++)
	{
		if ((*it).Number == num)
		{
			stu.erase(it);    //删除迭代器it指向的学生信息
			total--;       //删除一名学生的信息后,系统记录学生的人数减一
			cout << "--------->学号为" << num << "的学生的信息已删除!" << endl;
			return;
		}
	}
	cout << "--------->未找到学号为" << num << "的学生,请检查学号是否输入错误!" << endl;
}
/*
用户输入的要删除的学生的学号,用迭代器来遍历容器所有元素(即每一个学生类对
象),如果迭代器指向的学生的学号和用户输入的学号一致,则删除这个对象,并将
用于记录学生总人数的int型变量减一,完成删除操作。
*/

(3)信息修改功能模块:

void Recompose()           //修改学生信息
{
    cout<< "执行“修改学生信息”操作---------->请输入要修改学生的原学号:";
	string num;
	cin >> num;
	//用迭代器来遍历容器所有元素,用于查找和删除
	vector<Student>::iterator it = stu.begin();
	for (; it != stu.end(); it++)
	{
		if ((*it).Number == num)
		{
			cout << "依次输入修改后的学生的学号、姓名、性别、年龄、班号、专业名称、系别:" << endl;
			(*it).setStu();    //调用成员函数重新给该学生的属性赋值
			cout << "--------->原学号为"<<num<<"的学生的信息已修改!" << endl;
			return;
		}
	}
	cout << "--------->未找到学号为" << num << "的学生,请检查学号是否输入错误!" << endl;
}
/*
用户输入要修改的学生的学号,用迭代器来遍历容器所有元素(即每一个学生类对象),
如果迭代器指向的学生的学号和用户输入的学号一致,则提示用户将修改后的学生信息输
入,程序通过调用迭代器指向的类对象的成员函数setStu(),将相应学生的信息进行修
改,完成修改操作。
*/

(4)信息查询功能模块:

void Find()               //查询学生的信息
{
	cout  << "=========(a)按学号查询单个学生信息" << endl;
	cout  << "=========(b)按姓名查询单个学生信息" << endl;
	cout  << "=========(c)按性别查询学生信息" << endl;
	cout  << "=========(d)按班号查询学生信息" << endl;
	cout  << "=========>请根据以上序号选择查询类别:";
	char x;
	cin >> x;
	switch (x)
	{   case 'a':
	   {
		cout << "已选择“按学号查询单个学生信息”---------->请输入该学生的学号:";
		string num;
		cin >> num;
		vector<Student>::iterator it = stu.begin();
		cout << "--------->该学生的基本信息如下:" << endl;
		for (; it != stu.end(); it++)
		{
			if ((*it).Number == num)
			{
				(*it).showStu();
				break;
			}
		}
		if (it == stu.end())
			cout << "--------->未查询到学号为" << num << "的学生" << endl;
	   }break;
	   //代码逻辑一致,篇幅关系这里不展开
	   case 'b':{//……}break;
	   case 'c':{//……}break;
	   case 'd':{//……}break;
	}
}
/*
用户选择执行查询功能,系统提供子菜单供用户选择查询的类别,仍然用迭代器来遍历容
器所有元素(即每一个学生类对象),对于相应的查询类别,如果迭代器指向的学生的信
息和用户输入的一致,则调用其成员函数showStu()向屏幕中输出符合查询类别的学生信
息,完成查询操作。
*/

(5)信息统计功能模块:

void Count()         //统计学生信息
{
	cout  << "=========(a)按性别统计学生人数" << endl;
	cout  << "=========(b)按班号统计学生人数" << endl;
	cout  << "=========(c)按年龄统计学生人数" << endl;
	cout  << "=========(d)按系别统计学生人数" << endl;
	cout  << "========>请根据以上序号选择统计类别:";
	char x;
	cin >> x;
	switch (x)
	{
	case 'a':
	{
		cout << "已选择“按性别统计学生人数”---------->请输入要统计的学生的性别:";
		string gender;
		cin >> gender;
		int totalA = 0;
		vector<Student>::iterator it = stu.begin();
		for (; it != stu.end(); it++)
		{
			if ((*it).Gender == gender)
			{
				totalA++;
			}
		}
		cout << "--------->" << gender << "性学生共有" << totalA << "个" << endl;
	}break;
	//代码逻辑一致,篇幅关系这里不展开
	case 'b':{//……}break;
	case 'c':{//……}break;
	case 'd':{//……}break;
	}
}
/*
用户选择执行查询功能,系统提供子菜单供用户选择查询的类别,对于每个类别创建一个
整型变量totalA(B、C、D),用来统计不同类别的学生人数,用迭代器来遍历容器所有
元素(即每一个学生类对象),对于相应的查询类别,如果迭代器指向的学生的信息和用
户输入的一致,则该类别的total加1,统计完后将统计的结果(学生人数)输出,完成统
计操作。
*/

(6)退出系统功能模块:

将选择功能模块放入while循坏中,当用户选择功能时输入6,执行退出功能,则退出循
坏,完成退出系统功能(然后执行写入文件操作)。具体见main函数

(7)将学生学籍信息保存到文件中,建立本程序与文件的联系:

//删除文件中的第一行(学号	姓名	性别	年龄	班号	专业	系别)
//删除该行后才能正确地把数据写入到Student类的vector容器中
void DeleteFirstLine()
{
	//将文件中的数据逐行写入容器vec中
	vector<string> vec;   
	string strLine;   //记录文件的每一行
	ifstream inFile("学生学籍信息.txt", ios::in);
	while (inFile)
	{
		getline(inFile, strLine);   //逐行读取文件内容到strLine中
		vec.push_back(strLine);     //将读取的一行内容放入容器中
	}
	inFile.close();

	vec.erase(vec.begin());    //删除第一行

	//将剩余的内容重新写回到文件中
	ofstream outFile("学生学籍信息.txt", ios::out);
	vector<string>::const_iterator it = vec.begin();
	for (; it != vec.end(); it++)
	{
		//逐行将vec容器中的内容写入文件中
		outFile.write((*it).c_str(), (*it).size());   
		outFile << endl;
	}
	outFile.close();          //关闭文件
}

void PutOutFile()        //读取文件中的数据,并存入到vector<Student>容器中
{
	ifstream ifs;          //创建流对象
	//打开文件,并判断是否打开成功
	ifs.open("学生学籍信息.txt", ios::in);
	if (!ifs.is_open())
	{
		cout << "文件打开失败" << endl;
		return;
	}
	string number, name, gender;
	int age;
	string class1, major, dep;
	//以上变量用于存放文件每一行对应的学生信息数据,以便用文件中的每一行内容创建一个学生类对象,并存放到stu容器中

	while (ifs >> number >> name >> gender >> age >> class1 >> major >> dep)
	{
		Student s;
		s.Number = number;
		s.Name = name;
		s.Gender = gender;
		s.Age = age;
		s.Class = class1;
		s.Major = major;
		s.Department = dep;
		stu.push_back(s);
		total++;        //每创建一个学生类对象并存入容器stu中,将学生人数加一
	}
	ifs.close();          //关闭文件
}

void PutInFlie()          //将学生信息存储(写入)到文件中
{
	//将Student类中所有成员信息存储(写入)到文件中
	ofstream ofs;       //创建流对象
	//首次默认创建一个"学生学籍信息.txt"文件在与本项目同级文件夹中
	ofs.open("学生学籍信息.txt", ios::out);
	//将学生信息内容写进文件内
	ofs << "学号" << '\t' << "姓名" << '\t' << "性别" << '\t' << "年龄" << '\t'
		<< "班号" << '\t' << '\t' << "专业" << '\t' << '\t' << '\t' << "系别"<<endl;
	for (int i = 0; i < total; i++)
	{
		ofs << stu[i].Number << '\t' << stu[i].Name << '\t' << stu[i].Gender
			<< '\t' << stu[i].Age << '\t' << stu[i].Class
			<< '\t' << '\t' << stu[i].Major << '\t' << '\t' << '\t' << stu[i].Department << endl;
	}
	ofs.close();      //关闭文件
}

/*
将学生信息写入文件时,首先写入一个标题行(学号	姓名	性别	年龄	班号	专业	系别),
然后根据学生人数total,将每个学生信息写入文件中,然后换行,循坏total次。执行完后关闭文件,完成存入文件操作。
由于“将数据写入文件”操作中还多写入了一个标题行,这部分不能存到容器stu中,于是首先执行“删除文件第一行”操作,
删除后将剩余内容重新写回到文件中,然后执行“读取文件中的数据”操作,逐行将文件内对应的学生信息用相应变量记录下来,
用来创建一个Student类对象,并将该对象存进vector<Student> stu容器中,完成读取文件操作。
*/

四、实验结果分析

程序运行效果图:(涉及的人名是随便想到的)

首次运行前(仅录入信息),在与本项目同级文件夹中先创建一个文本文件 “学生学籍信息.txt”,然后运行程序,录入部分学生信息。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

第二次运行,来测试执行各种功能:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

运行结果分析:

首次运行时,文本文件"学生学籍信息.txt"中没有内容,执行“删除第一行”和“读取文件中的数据”时为空操作,文件内容没有改变,用于存放学生信息的容器也是空的。执行录入操作后退出系统,程序将容器vector stu中存放的每个学生信息写入到文件中,于是打开文件能看到已录入的学生的基本信息。
第二次运行时,由于“将数据写入文件”操作中还多写入了一个标题行(学号 姓名 性别 年龄 班号 专业 系别),这部分不能存到容器stu中,于是首先执行“删除文件第一行”操作,删除后将剩余内容重新写回到文件中,然后执行“读取文件中的数据”操作,逐行将文件内对应的学生信息用相应变量记录下来,用来创建一个Student类对象,并将该对象存进vector stu容器中。接着执行各种功能:将另一部分学生信息录入,删除、修改学生信息,查询和统计学生信息等。
这样便可以将程序和文本文件"学生学籍信息.txt"联系起来,用运行程序的方式来对文件中的内容进行添加、删除、修改、查询和统计。

五、源码

github

https://github.com/Git1138954212/StudentSystem

百度网盘

链接:https://pan.baidu.com/s/1e0fso0ygOEC8oKcr3ClKsw
提取码:fkzp
(网页打开可能会乱码,但是下载下来再打开就不会乱码了。)

提示:

要先在与本项目同级文件夹中先创建一个文本文件 “学生学籍信息.txt”,然后再运行程序!

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐