学生信息管理系统(C++实现)

上个月程序设计作业做了一个学生信息管理系统,效果如下图

附上源代码。

//由于不熟悉文件读写,有些地方的代码有点奇怪。但是功能是可以实现的。

//虽然是用C++,但主要还是用了面向过程

/*
·File name:	file.h
·Description:	所有和文件读写相关的操作
*/

#pragma once
#include<iostream>
#include<fstream>
#include<string>
#include"student.h"

/*
函数:read_record()
功能:从record.txt读入记录,得到现有的记录条数
参数:学生信息记录条数&m, 成绩条数&n,
返回值:1
*/
int read_record(int &m, int &n)
{
	std::ifstream fin("record.txt");
	fin >> m;
	fin >> n;
	return 1;
}

/*
函数:write_record()
功能:写入记录到record.txt,更新记录条数
参数:学生信息记录条数m, 成绩条数n,
返回值: 0
*/
int write_record(int m, int n)
{
	std::ofstream fout("record.txt");
	fout << m;
	fout << " ";
	fout << n;
	return 1;
}
/*
函数:save_score()
功能:保存文件到score.dat
参数: 学生成绩指针StudentScore*, 学生成绩条数n
*/
void save_score(StudentScore* stu_score,int n)
{
	using namespace std;
	ofstream fout("score.dat", ios::binary);
	if (!fout)
	{
		cout << "创建文件失败\n";
		return;
	}
	int i = 0;
	for (int i = 0; i < n; i++)
	{
		fout << stu_score[i].ID << "  " << stu_score[i].lesson_number << "  "
			<< stu_score[i].lesson_name << "  " << stu_score[i].credit<< "  "
			<< stu_score[i].daily_score << "  " << stu_score[i].exp_score<< "  " 
			<< stu_score[i].exam_score << "  " << stu_score[i].total_score<< "  "
			<< stu_score[i].actual_score << "\n";
	}
	fout.close();
}
/*
函数:read_to_stu_score()
功能:从文件score.dat读入分数到数组
参数:学生成绩数组StudentScore*, 学生成绩条数&n
*/
int read_to_stu_score(StudentScore* stu_score, int &n)
{
	using namespace std;
	int i = 0;
	ifstream fin("score.dat", ios::binary);
	if (!fin)
	{
		cout << "读取成绩文件score.dat失败" << endl;
		return 0;
	}
	for (int i = 0; i < n; i++)
	{
		fin >> stu_score[i].ID >> stu_score[i].lesson_number
			>> stu_score[i].lesson_name >> stu_score[i].credit
			>> stu_score[i].daily_score >> stu_score[i].exp_score
			>> stu_score[i].exam_score >> stu_score[i].total_score
			>> stu_score[i].actual_score;
	}
	fin.close();
	return i;
}

/*
函数:read_to_stu()
功能:从文件student.txt读入学生信息到数组
参数:学生数组Student*, 学生信息条数m
*/
int read_to_stu(Student* stu, int &m)
{
	using namespace std;
	int i = 0;
	ifstream fin("student.txt");
	if (!fin)
	{
		cout << "读取学生基本文件student.txt失败" << endl;
		return 0;
	}
	string temp;//临时string,读入第一行的5个字符串
	for (int i = 0; i < 5; i++)
	{
		fin >> temp;
	}
	for (int i = 0; i < m; i++)
	{
		fin >> stu[i].ID >> stu[i].name >> stu[i].sex >> stu[i].dor_number
			>> stu[i].phone;
	}
	fin.close();
	return 1;
}
/*
函数:save_stu
功能:写入学生信息到student.txt
参数:学生数组Student*,学生信息条数m
*/
void save_stu(Student* stu, int m)
{
	using namespace std;
	ofstream fout("student.txt");
	if (!fout)
	{
		cout << "创建文件失败\n";
		return;
	}
	fout << "学号 姓名  性别  宿舍号码  电话号码\n";
	for (int i = 0; i < m; i++)
	{
		fout << stu[i].ID << "  " << stu[i].name << "  " << stu[i].sex << "  "
			<< stu[i].dor_number << "     " << stu[i].phone<<"\n";
	}

	fout.close();
}


/*
·File name:	func.h
·Description:	实现学生管理系统的相关函数的声明
*/
#pragma once
#include<string>
#include"student.h"

int read_data_and_calcu(StudentScore* stu_score, int & n);
int find(Student * stu, StudentScore* stu_score,int m, int n);
void find_baseinfo(Student* stu, int n);
void find_baseinfo_by_id_name(Student* stu, int m);
void find_baseinfo_by_dor(Student* stu, int m);
void find_score(Student* stu, StudentScore * stu_score,int m, int n);
int sort_score(StudentScore * stu_score, int n);
int delete_by_ID(Student * stu, StudentScore * stu_score, int &m, int &n);


/*
·File name:	menu.h
·Description:	菜单相关函数的声明
*/
#pragma once
#include"student.h"
void show_menu();
bool choose_func(char choice, bool & active, StudentScore * stu_score, Student * stu,
	int & m, int& n);

/*
·File name:	student.h
·Description:	学生类和学生成绩类
*/
#pragma once
#include<iostream>
#include<iomanip>
#include<string>
using std::string;


// StudentScore 存储学生成绩
class StudentScore
{
public:
	int ID;  //学号
	string lesson_number; //课程编号
	string lesson_name; //课程名称
	int credit;  //学分
	int daily_score;  //平时成绩
	int exp_score;  //实验成绩
	int exam_score; //卷面成绩
	double total_score;  //综合成绩, 计算得到
	double actual_score; // 实际得分, 计算得到
public:
	StudentScore() ;
	StudentScore(int ID, string lesson_number,string lesson_name,int credit,
int daily_score,int exp_score,int exam_score);
	~StudentScore() ;
	friend std::ostream& operator<<(std::ostream& os, const StudentScore& score);
};

//Student类,存储学生信息
class Student
{
public:
	int ID;  //学号
	string name; //姓名
	string sex; //性别
	int dor_number; //宿舍号码
	int phone; //电话
public:
	Student();
	~Student();
	friend std::ostream & operator<<(std::ostream & os, const Student& stu);
};



/*
·File name:	 func.cpp
·Description:   实现菜单的4项功能:1.读入数据; 2.查找; 3.删除; 4.成绩排序
*/


#include<iostream>
#include<iomanip>
#include<string>
#include<fstream>
#include"student.h"

using std::string;
using std::cin;
using std::cout;

//下面这4个函数被find调用,故先声明。
void find_baseinfo(Student* stu, int m);
void find_baseinfo_by_id_name(Student* stu, int m);
void find_baseinfo_by_dor(Student* stu, int m);
void find_score(Student* stu, StudentScore * stu_score,int m,int n);


/*
函数:read_data_and_calcu()
功能:从键盘读入成绩相关的7项数据,并根据公式计算出综合成绩和实得学分。
参数:StudentScore*(分数数组地址), &n(已有的成绩条数)
返回值:写入的条数
*/
int read_data_and_calcu(StudentScore* stu_score, int & n)
{
	int Max_read = 1;       //每次最多读入的条数
	bool flag_input = true;// 用来判断是否正常输入
	int id = 0;           //学号
	string lesson_number;//课程编号
	string lesson_name; //课程名称
	int credit;        //学分
	int daily_score;  //平时成绩
	int exp_score;   //实验成绩
	int exam_score; //卷面成绩
	int i = 0;
	for( i = n; i< n+Max_read && flag_input; i++)
	{
		cout << "开始输入学生数据:\n";
		cout << "学号,"<< " 课程编号, " << " 课程名称: \n";		
		cin >> id;
		cin >> lesson_number;
		cin >> lesson_name;
		cout << "学分, " << " 平时成绩, " << " 实验成绩," << " 卷面成绩:\n";
		cin >> credit>> daily_score >>exp_score>> exam_score;
		stu_score[i] = StudentScore(id, lesson_number, lesson_name, credit, daily_score,
			exp_score, exam_score);
		cout << "录入该学生数据成功";
	}
	cout << "\n";
	n += i;
	return i;
}


/*
函数:find()
功能:查询(总),通过用户选择查询类型调用find_baseinfo()或find_score(),显示对应的信息。
参数:Student*(学生数组地址), StudentScore*(分数数组地址),int m(学生信息条数), int n(分数条数)
返回值:0
*/
int find(Student * stu,StudentScore* stu_score,int m, int n)
{
	cout << "输入查询类型:1.学生基本情况查询; 2.成绩查询:";
	char find_kind;
	cin >> find_kind;
	switch (find_kind)
	{
	case '1':
		//学生基本情况查询
		find_baseinfo( stu, m);
		break;
	case '2':
		//成绩查询
		find_score(stu, stu_score,m, n);
		break;
	default:
		cout<<"无效选择\n";
		break;
	}
	cout << "\n";
	return 0;
};

/*
函数:find_baseinfo()
功能:查询_学生基本信息,被find()调用,显示对应的学生信息
参数:Student*, m
*/
void find_baseinfo(Student* stu, int m)
{
	cout << "输入查询方式:1.按学号或姓名查询   2.按宿舍查询: ";
	int choice;
	cin >> choice;
	switch (choice)
	{
	case 1:
		find_baseinfo_by_id_name(stu, m);
		break;
	case 2:
		find_baseinfo_by_dor(stu, m);
		break;
	}
}


/*
函数:find_baseinfo_by_id_name()
功能:查询_学生基本信息_通过_id或name,被find_baseinfo()调用
参数:Student*, m
*/
void find_baseinfo_by_id_name(Student* stu, int m)
{
	cout << "选择:1.使用学号查询  2.使用姓名: ";
	int choice_2;
	cin >> choice_2;
	switch (choice_2)
	{
	case 1:
	  {	
		//按学号查询,打印结果
		cout << "输入学号: ";
		int id;
		cin >> id;
		bool flag_find_id = false;
		for (int i = 0; i < m; i++)
		{
			if (id == stu[i].ID)
			{
				flag_find_id = true;
				cout << "学号 姓名    性别  宿舍号码  电话号码\n";
				cout << stu[i];
				break;
			}
			if (i == m - 1 && !flag_find_id )
				cout << "  此ID记录不存在\n";
		}
	  }
	  break;
	case 2:
	  {
		//使用姓名查询,打印结果
		cout << "输入姓名: ";
		string name;
		cin >> name;
		bool flag_find_name = false;
		for (int i = 0; i < m; i++)
		{
			if (name == stu[i].name)
			{
				flag_find_name = true;
				cout << "学号  姓名  性别   宿舍号码  电话号码\n";
				cout << stu[i];
				break;
			}
			if (i == m - 1 && !flag_find_name)
				cout << "  此姓名记录不存在\n";
		}
		break;
	  }
	}
}

/*
函数:find_baseinfo_by_dor()
功能:查询_学生基本信息_通过_宿舍,被find_baseinfo()调用
参数:Stuent*, m
*/
void find_baseinfo_by_dor(Student* stu, int m)
{
	//按宿舍查询,打印结果
	cout << "输入宿舍号: ";
	int dor_number;
	cin >> dor_number;
	cout << "学号  姓名  性别   宿舍号码  电话号码\n";
	bool flag_find_dor = false;
	for (int i = 0; i < m; i++)
	{
		if (dor_number == stu[i].dor_number)
		{
			flag_find_dor = true;
			cout << stu[i];
			cout << "\n";
		}
		if (i == m - 1 && !flag_find_dor )
			cout << "    宿舍记录不存在\n";
	}
}

/*
函数:find_score()
功能:查询_分数,被find()调用,显示对应的分数信息
参数:Student*, StudentScore*,m(学生信息条数),n(分数信息条数)
*/
void find_score(Student* stu, StudentScore* stu_score, int m, int n)
{
	cout << "输入该学生的学号:";
	int id;
	cin >> id;
	bool flag_find_id = false;
	for (int i = 0; i < m; i++)
	{
		if (id == stu[i].ID)
		{
			flag_find_id = true;
			cout << "\t\t\t\t学号: "<<std::setiosflags(std::ios::left) 
				<<std::setw(10)<< stu[i].ID << "姓名: "
				<<std::setw(10)<< stu[i].name;
			break;
		}
		if (i == m - 1 && !flag_find_id)
		{
			cout << "\n\t\t此ID学生信息记录不存在\n";
		}
	}
	bool flag_find_score = false;
	int lesson_n = 0;
	double all_credit = 0;
	for (int i = 0; i < n; i++)
	{
		if (id == stu_score[i].ID)
		{
			flag_find_score = true;
			cout << "\n" << stu_score[i];
			lesson_n++;
			all_credit += stu_score[i].actual_score;
		}
		if (i == n - 1 && !flag_find_score)
		{
			cout << "\n\t\t此ID成绩记录不存在\n";
		}
	}
	cout << "\n\t\t共修: " << lesson_n << "科,实得总学分为: " << all_credit;
}

/*
函数:delete_by_ID()
功能:删除和ID相关的信息
返回值:0
*/
int delete_by_ID(Student * stu, StudentScore * stu_score, int &m, int &n)
{
	cout << "删除该学号的所有相关信息:\n输入学号:";
	int ID;
	cin >> ID;
	//删除ID相关的学生基本信息
	for (int i = 0; i < m; i++)
	{
		if (stu[i].ID == ID)
		{
			int k = i;
			if (k == m - 1)
			{
				stu[i] = Student(); //使其为空
				m--;
			}
			else
			{
				for (int j = k+1; j < m; j++)
				{
					stu[j-1] = stu[j];
				}
				m--;
			}
		}
	}
	//删除ID相关的成绩信息
	for (int i = n-1; i >= 0; i--)
	{
		if (stu_score[i].ID == ID)
		{
			int k = i;
			if (k == n - 1)
			{
				stu_score[i] = StudentScore(); //使其为空
				n--;
			}
			else
			{
				for (int j = k + 1; j < n; j++)
				{
					stu_score[j - 1] = stu_score[j];
				}
				n--;
			}
		}
	}
	cout << "该学生所有相关信息删除成功\n";
	return 0;
};

/*
函数:sort_score()
功能:按分数排序,(降序)。
参数:StudentScore*, n(成绩条数)
返回值:n(成绩条数)
*/
int sort_score(StudentScore * stu_score, int n)
{
	int choice;
	cout << "选择:1.按综合成绩排序   2.按实得学分排序";
	cin >> choice;
	switch (choice)
	{
	 case 1:
	 { 
	 StudentScore temp;
	 for (int i = 0; i < n - 1; i++)
	 {
		 for (int j = 0; j < n - i - 1; j++)
		 {
			 if (stu_score[j].total_score < stu_score[j + 1].total_score)
			 {
				 temp = stu_score[j];
				 stu_score[j] = stu_score[j+1];
				 stu_score[j + 1] = temp;
			 }
		 }
	 }
	 break;
	 }
	 case 2:
	 {
		 StudentScore temp;
		 for (int i = 0; i < n - 1; i++)
		 {
			 for (int j = 0; j < n - i - 1; j++)
			 {
				 if (stu_score[j].actual_score < stu_score[j + 1].actual_score)
				 {
					 temp = stu_score[j];
					 stu_score[j] = stu_score[j + 1];
					 stu_score[j + 1] = temp;
				 }
			 }
		 }
		 break;
	 }
	}

	for (int i = 0; i < n; i++)
	{
	cout<<"学号: "<<std::setiosflags(std::ios::left)<<std::setw(4)
		<<stu_score[i].ID<<stu_score[i] << "\n";
	}
	return n;
};

/*
·File name:	menu.cpp
·Description:	所有和菜单相关的操作。
*/
#include<iostream>
#include"student.h"
#include"func.h"

using std::cout;
using std::cin;

/*
函数:show_menu()
功能:显示主菜单
*/
void show_menu()
{
	cout<<"############################\n";
	cout<<"   学生信息管理系统\n"
		<<"      选择功能\n"
		<<"1.数据的录入和计算\n"
		<<"2.查询功能\n"
		<<"3.删除功能\n"
		<<"4.排序功能\n"
		<<"q.退出程序。\n";

}

/*
函数:choose_func
功能:读入选择,执行功能
返回:程序状态(运行ture,结束false)
*/

bool choose_func(char choice, bool & active,StudentScore * stu_score,Student * stu,
	int & m, int& n )
{
	switch(choice)
	{
	case '1' : 
		n = read_data_and_calcu(stu_score,n);
		break;
	case '2':
	    find( stu, stu_score,m, n);
		break;
	case '3':
		delete_by_ID(stu, stu_score, m, n);
		break;
	case '4':
		sort_score(stu_score, n);
		break;
	case 'q':
		cout<<"quit~\n";
		active = false;
		break;
	default:
		cout << "无效输入\n";
	}
 return active;
}

/*
·File name:	student.cpp
·Description:	学生类和成绩类的相关函数。
*/
#include"student.h"

/*
计算综合成绩,返回综合成绩。 
传入参数: exp_score,  exam_score, daily_score
返回值:   total_score
*/
double calcu_total_score(int exp_score, int exam_score, int daily_score);
/* 
计算实得学分,返回实得学分
传入参数: total_score, credit
返回值:   actual_score
*/
double calcu_actual_score(double total_score, int credit);

//分数的默认构造函数,初始化ID = 0,分数为负数,表示无效成绩;
StudentScore::StudentScore() : ID(0),lesson_number("None"),lesson_name("None"),credit(-1),
	daily_score(-1),exp_score(-1),exam_score(-1)
{

}
//分数的构造函数2,传入参数进行初始化,自动调用calcu_total_score,calcu_actual_score计算 综合成绩和实得学分
StudentScore::StudentScore(int m_ID, string m_lesson_number, string m_lesson_name, int m_credit,
  int m_daily_score, int m_exp_score, int m_exam_score) :  ID(m_ID),lesson_number(m_lesson_number),
  lesson_name(m_lesson_name),credit(m_credit),daily_score(m_daily_score),
	exp_score(m_exp_score),exam_score(m_exam_score)
{
	total_score = calcu_total_score( m_exp_score, m_exam_score, m_daily_score);
	actual_score = calcu_actual_score( total_score,  m_credit);
}
//分数的析构函数,暂无工作要做
StudentScore::~StudentScore()
{

}
//分数的友元函数<<,用于显示
std::ostream& operator<<(std::ostream& os, const StudentScore& stu_score)
{
	os  << std::setiosflags(std::ios::left)
		<<"课程编号: " <<std::setw(8)<< stu_score.lesson_number 
		<< "课程名称: "<<std::setw(12) << stu_score.lesson_name 
		<< "综合成绩: "<<std::setw(8) << stu_score.total_score 
		<< "实得学分: " << stu_score.actual_score;

	return os;
}


//学生的默认构造函数,初始化0
Student::Student(): ID(0), name("None"), sex("None"), dor_number(0), phone(0)
{

}

//学生的析构函数,暂无工作要做
Student::~Student()
{

}

//学生的友元函数<< 用于打印输出.
std::ostream & operator<<(std::ostream & os, const Student& stu)
{
	os <<std::setiosflags(std::ios::left)
		<<std::setw(5)<< stu.ID 
		<<std::setw(8)<< stu.name 
		<< stu.sex << "      " << stu.dor_number << "     "
		<< stu.phone;
	return os;
}




// 计算实得学分
double calcu_actual_score(double total_score, int credit)
{
	double actual_score;
	int flag_total =total_score/10;
	switch (flag_total)
	{
	case 10: case 9: actual_score = credit;
		break;
	case 8: actual_score = credit * 0.8;
		break;
	case 7: actual_score = credit * 0.75;
		break;
	case 6: actual_score = credit * 0.6;
		break;
	default: actual_score = 0;
		break;
	}
	return actual_score ;
}
//计算综合成绩
double calcu_total_score(int exp_score, int exam_score, int daily_score)
{
	double total_score;
	if(exp_score == -1)
		total_score = daily_score * 0.3 + exam_score * 0.7;
	else
		total_score = daily_score * 0.15 + exp_score * 0.15 + exam_score * 0.7;
	return total_score;
}

/*
# File name:    main.cpp
# Author:       一只大鸽子
# Date:         2018/9/10
# Description:  学生信息管理系统的主函数
*/

#include<iostream>
#include"menu.h"
#include"student.h"
#include"file.h"

//主函数main,程序入口
int main()
{		
	char choice = 0;	//choice,让用户输入选择
	bool active = true;	//active,用来判断程序运行状态,true代表运行中,false代表结束	
	int	m = 0; //学生基本信息 数量
	int n = 0; //成绩信息 数量
	read_record(m, n);//得到学生基本信息、成绩信息条数
	Student * stu =  new Student[m+10];	//学生数组stu,存储学生信息
	StudentScore * stu_score = new StudentScore[n+400];//分数数组stu_score,存储成绩信息

	read_to_stu(stu, m); //从student.txt读入数据到数组中
	read_to_stu_score(stu_score, n); //从score.dat读入数据到数组中

	//显示主菜单
	show_menu();
	//进入循环,用户选择菜单上的功能。直到active为false,程序即将结束时,退出循环
	while(active)
	{ 
		std::cin>>choice;
		choose_func(choice,active,stu_score,stu,m,n);
		if(active)
		  show_menu();
	}
	/*
	程序即将结束,将学生信息写入student.txt;将分数信息写入score.dat;
	写入信息数量到record.txt中;
	*/
	save_stu(stu, m);
	save_score(stu_score, n);
	write_record(m, n);
	//归还使用的内存
	delete[] stu;
	delete[] stu_score;
	system("pause"); //暂停
	return 0;
}

小结:

这是我的第一个C++实践程序,写了大概有两三天。

中间遇到一些问题,比如文件读写,格式输出。。。。。。第一次运行时还有一些奇奇怪怪的问题。比如stackoverflow...

最后还是通过看书和百度解决了。

总结一点经验:

1.变量和函数的命名很重要,一定要清晰易懂,一看到这个名字就知道它是干什么的,不要随便起 a,b,c或者fun1,fun2之类的名字。

2.注释很重要

3.代码格式很重要(对齐缩进)

4.不要自己钻到一个问题里就不出来了,很浪费时间。 比如排序功能可能你一下子想不出来,就可以上网搜搜(c++排序),

借鉴一下。如果找不到,也不要一直纠结,先空着,过一会可能就想到了。

5.代码重构。当你代码写着写着感觉某个函数太长了,或者感觉一些功能可以提取出来,就可以把某个功能做成函数。

6..注意身体,注意休息,喝水。最好能定时休息。

猜你喜欢

转载自blog.csdn.net/qq_41068877/article/details/83036099