程序设计——班级学生成绩管理系统(C/C++实现)

班级学生成绩管理系统——C/C++实现

  • 项目功能基本完成,且有诸多改进,项目未完成的一两个小BUG都标注在文章末尾了,总体没有问题。✅
  • 项目没怎么用C++的东西,就一个string类和c++的输入输出,还有个new和函数传引用。🤦🏻‍♂️
  • 项目只能算是初级初级初级程序设计,数据结构是最简单的顺序表,没有数据库,没有可视化便捷操控界面,没有设计模式。(啥也不是😂)
  • 希望能对入门程序猿们有一些帮助,一起 stronger。💪🏻

一、功能概述

使用 C 语言完成该系统的开发,通过该系统可实现对某班级(例如 B175A5 班)学生成绩信息的添加、查询、修改、删除、统计分析,以及数据保存、读取等功能。



二、功能详细说明

  1. 学生成绩信息录入
    • 添加学生的成绩信息到系统中,主要包括学号、姓名、各科成绩。其中,学号的格式是:“班号+2 位数字”;成绩要求在 0~100 之间。若输入数据违法,则进行相应提
      示。
    • 判断输入的学号是否存在,若不存在,则添加到系统;否则,提示学号已存在,不
      进行添加。
    • 添加完成后,提示是否继续添加。如果不继续添加,则返回主菜单。
  2. 学生成绩信息查询
    • 系统提供三种查询方式,按学号,按姓名,以及显示所有学生成绩信息。
    • 如果查找成功,显示该学生的成绩信息;否则,提示未找到。
  3. 学生成绩信息修改
    • 系统提供两种方式进行修改,可按姓名或学号来进行。
    • 修改时,先按照提供的信息进行查找,若查找成功,则可输入该学生新的成绩信息;否则,提示该学生不存在。
  4. 学生成绩信息删除
    • 系统只提供按照学生的学号进行删除。
    • 删除时,首先输入学生的学号,若查找到该生的信息,则将其从系统中删除;否则,提示提示该学生不存在。
  5. 学生成绩信息统计
    • 系统提供了选择成绩统计和成绩排名两种操作。
    • 选择成绩统计时,先提示对哪门课(英语、数学、计算机)进行统计,然后提示统计方式。可统计最高分、最低分、平均分、排名、不及格的人数、优秀的人数,选择后显示相应的统计结果。
    • 选择成绩排序时,先提示对哪门课(英语、数学、计算机)进行成绩排序,选择后显示相应排序结果。
  6. 文件操作
    • 系统中所有的学生成绩系统都以二进制形式保存在文件中。



三、代码实现

#include <iostream>
using namespace std;
// #include <stdlib.h>

#define MAX 50
#define TEMPSIZE 100	  // 从二进制文件提取数据的中间变量
#define CODE "作者是个大帅比" // 管理员密码

/**
 * 1. 存储结构
 */
typedef struct
{
	// char number[100];  // 学号  char类型数据只能直接输入/用字符串函数,不能赋值
	// char name[100];  // 姓名
	// char sex[10];  // 性别
	// enum sex {男, 女};  // 性别
	string number;	// 学号
	string name;	// 姓名
	int sex;		// 性别: 1--男,2--女
	int age;		// 年龄
	float score[3]; // 成绩 * 3
} StudentInfo;
typedef struct
{
	StudentInfo stu_array[MAX]; // 学生信息表
	int stu_size;				// 当前学生数量
} StudentList;

/**
 * 2. 操作函数
 */
// 显示菜单
void ShowMenu();
// 初始化学生表
bool InitStudentList(StudentList &);
// 判断学生表是否为空
bool IsEmpty(StudentList);
// 添加学生信息
bool AddStudentList(StudentList &);
// 显示学生信息
bool ShowStudentList(StudentList);
// 查询学生信息
int SearchStudentListByNumber(StudentList, string);
int SearchStudentListByName(StudentList, string);
bool FindStudentListByIndex(StudentList, int);
void FindStudentList(StudentList);
// 删除学生信息
bool DeleteStudentListByIndex(StudentList &, int);
bool DeleteStudentList(StudentList &);
// 修改学生信息
bool ModifyStudentListByIndex(StudentList &, int);
bool ModifyStudentList(StudentList &);
// 清空学生信息
bool ClearStudentList(StudentList &);
// 文件读写操作
bool ClearStudentInfoInTxt();
bool ReadStudentInfoFromTxt(StudentList &);
bool WriteStudentListToTxt(StudentList);
// 学生信息统计
// 学生成绩排名
bool SortStudentList(StudentList &);
// 学生成绩统计
bool StudentInfoStatistics(StudentList);
void StudentScoreStatistics(StudentList);
int CountExcellentStudents(StudentList, int);
int CountFlunks(StudentList, int);
float FindAverageScore(StudentList, int);
float FindLowestScore(StudentList, int);
float FindHighestScore(StudentList, int);

/**
 * 2.1 菜单界面
 */
void ShowMenu()
{
	cout << "***** 欢迎来到学生信息管理系统 *****" << endl;
	cout << "****     1. 添加学生信息        ****" << endl;
	cout << "****     2. 显示学生信息        ****" << endl;
	cout << "****     3. 删除学生信息        ****" << endl;
	cout << "****     4. 查询学生信息        ****" << endl;
	cout << "****     5. 修改学生信息        ****" << endl;
	cout << "****     6. 统计学生信息        ****" << endl;
	cout << "****     7. 清空学生信息        ****" << endl;
	cout << "****     8. 保存学生信息到文件   ****" << endl;
	// cout << "****     9. 从文件读取学生信息   ****" << endl;
	cout << "****     0. 退出管理系统        ****" << endl;
	cout << "************************************" << endl;
}

/**
 * 2.2 初始化学生信息
 */
bool InitStudentList(StudentList &stu_list)
{
	stu_list.stu_size = 0; // 初始化学生表长度为0

	char option = 'n';
	cout << "开始初始化系统……\n请选择是否需要从指定文件读取历史学生数据(y/n):";
	cin >> option;
	while (true)
	{
		if (option == 'Y' || option == 'y')
		{
			ReadStudentInfoFromTxt(stu_list); // 从文件读取学生信息
			break;
		}
		else if (option == 'N' || option == 'n')
		{
			cout << "欢迎回来!\n";
			system("pause");
			system("cls");
			break;
		}
		else
		{
			cout << "输入错误,请重新输入:";
			cin >> option;
		}
	}
	return true;
}

// 判空
bool IsEmpty(StudentList stu_list)
{
	if (stu_list.stu_size == 0)
		return true;
	else
		return false;
}

/**
 * 2.3 添加学生信息
 */
bool AddStudentList(StudentList &stu_list)
{
	if (stu_list.stu_size == MAX)
	{ // 判满
		cout << "学生列表已满,无法添加!" << endl;
		system("pause");
		system("cls");
		return false;
	}
	else
	{ // 添加具体学生信息
		// 学号
		string number;
		cout << "请输入学号:" << endl;
		while (true)
		{
			cin >> number;
			if (SearchStudentListByNumber(stu_list, number) == -1 || SearchStudentListByNumber(stu_list, number) == -2)
			{
				stu_list.stu_array[stu_list.stu_size].number = number;
				break;
			}
			else
				cout << "学号重复,请输入新学号:";
		}
		// 姓名
		string name;
		cout << "请输入姓名:" << endl;
		cin >> name;
		stu_list.stu_array[stu_list.stu_size].name = name; // 利用stu_size结构体元素,在当前数组尾插入学生信息
		// 性别
		cout << "请输入性别:" << endl;
		cout << "1 -- 男" << endl;
		cout << "2 -- 女" << endl;
		int sex = 0;
		while (true)
		{
			// 简单的输入合法性判断
			cin >> sex;
			if (sex == 1 || sex == 2)
			{
				stu_list.stu_array[stu_list.stu_size].sex = sex;
				break;
			}
			cout << "输入有误,请重新输入:" << endl;
		}
		// 年龄
		cout << "请输入年龄:" << endl;
		int age = 0;
		while (true)
		{
			// 简单的输入合法性判断
			cin >> age;
			if (age > 0 && age < 150)
			{
				stu_list.stu_array[stu_list.stu_size].age = age;
				break;
			}
			cout << "输入有误,请重新输入:" << endl;
		}
		// 成绩
		cout << "请输入成绩:" << endl;
		float score = 0.0;
		for (int i = 0; i < 3; ++i)
		{
			while (true)
			{
				// 简单的输入合法性判断
				cin >> score;
				if (score >= 0.0 && score <= 100.0)
				{
					stu_list.stu_array[stu_list.stu_size].score[i] = score;
					break;
				}
				cout << "输入有误,请重新输入:" << endl;
			}
		}
		stu_list.stu_size++;
		cout << "学生信息添加成功!" << endl;
		system("pause");
		system("cls");
		return true;
	}
}

/**
 * 2.4 显示学生信息
 */
bool ShowStudentList(StudentList stu_list)
{
	// if (stu_list.stu_size == 0)
	if (IsEmpty(stu_list))
	{
		cout << "学生列表目前为空!" << endl;
		system("pause");
		system("cls");
		return false;
	}
	else
	{
		cout << "学号\t\t"
			 << "姓名\t\t"
			 << "性别\t\t"
			 << "年龄\t\t"
			 << "成绩1\t成绩2\t成绩3" << endl;
		for (int i = 0; i < stu_list.stu_size; ++i)
		{
			cout << stu_list.stu_array[i].number << "\t\t";
			cout << stu_list.stu_array[i].name << "\t\t";
			cout << (stu_list.stu_array[i].sex == 1 ? "男" : "女") << "\t\t";
			cout << stu_list.stu_array[i].age << "\t\t";
			for (int j = 0; j < 3; ++j)
				cout << stu_list.stu_array[i].score[j] << "\t";
			cout << endl;
		}
	}
	system("pause");
	system("cls");
	return true;
}

/**
 * 2.5 查询学生信息
 */
int SearchStudentListByNumber(StudentList stu_list, string number)
{
	if (IsEmpty(stu_list))
		return -2; // 列表为空返回 -2 (-2,-1,>0对应 3 种情况,-2最小优先级最高。)
	else
	{
		for (int i = 0; i < stu_list.stu_size; ++i)
			if (stu_list.stu_array[i].number == number)
				return i;
		return -1; // 查询不到学生信息返回 -1
	}
}

int SearchStudentListByName(StudentList stu_list, string name)
{
	if (IsEmpty(stu_list))
		return -2;
	else
	{
		for (int i = 0; i < stu_list.stu_size; ++i)
			if (stu_list.stu_array[i].name == name)
				return i;
		return -1;
	}
}

// 根据查询到的index位序,对学生信息进行查找
bool FindStudentListByIndex(StudentList stu_list, int index)
{
	if (index == -2)
	{
		cout << "当前学生列表为空!" << endl;
		system("pause");
		system("cls");
		return false;
	}
	else if (index == -1)
	{
		cout << "查无此人!" << endl;
		system("pause");
		system("cls");
		return false;
	}
	else
	{
		cout << "查找成功,学生信息如下:" << endl;
		cout << "学号\t\t"
			 << "姓名\t\t"
			 << "性别\t\t"
			 << "年龄\t\t"
			 << "成绩\t\t" << endl;
		cout << stu_list.stu_array[index].number << "\t\t";
		cout << stu_list.stu_array[index].name << "\t\t";
		cout << (stu_list.stu_array[index].sex == 1 ? "男" : "女") << "\t\t";
		cout << stu_list.stu_array[index].age << "\t\t";
		for (int j = 0; j < 3; ++j)
			cout << stu_list.stu_array[index].score[j] << "\t";
		cout << endl;
		system("pause");
		system("cls");
		return true;
	}
}

// 查找学生信息总函数,设计查找操作的总逻辑以及对内部小函数进行调用
void FindStudentList(StudentList stu_list)
{
	// cout << "通过输入 学生学号 查找请按 1,通过输入 学生姓名 查找请按 2,按其他键取消操作:" << endl;
	cout << "请选择操作选项:\n1. 通过学生学号进行查询\n2. 通过学生姓名进行查询\n3. 按其他键取消操作\n";
	int select;
	cin >> select;
	while (cin.fail())
	{
		// cin输入异常处理
		cin.clear();
		cin.ignore();
		cout << "输入错误,请重新输入:";
		cin >> select;
	}
	switch (select)
	{
	case 1:
	{
		string number;
		cout << "请输入待查找学生的学号:" << endl;
		cin >> number;
		int index = SearchStudentListByNumber(stu_list, number); // 查询
		FindStudentListByIndex(stu_list, index);
		break;
	}
	case 2:
	{
		string name;
		cout << "请输入待查找学生的姓名:" << endl;
		cin >> name;
		int index = SearchStudentListByName(stu_list, name); // 查询
		FindStudentListByIndex(stu_list, index);
		break;
	}
	default:
	{
		cout << "操作取消成功!" << endl;
		system("pause");
		system("cls");
		return;
		break;
	}
	}
}

/**
 * 2.6 删除学生信息
 */
// 根据查询到的index位序,对学生信息进行删除
bool DeleteStudentListByIndex(StudentList &stu_list, int index)
{
	if (index == -2)
	{
		cout << "当前学生列表为空!" << endl;
		system("pause");
		system("cls");
		return false;
	}
	else if (index == -1)
	{
		cout << "查无此人!" << endl;
		system("pause");
		system("cls");
		return false;
	}
	else
	{
		for (int i = index; i < stu_list.stu_size; ++i)
			stu_list.stu_array[i] = stu_list.stu_array[i + 1];
		stu_list.stu_size--;
		cout << "删除成功!" << endl;
		system("pause");
		system("cls");
		return true;
	}
}

// 删除学生信息总函数,设计删除操作的总逻辑以及对内部小函数进行调用
bool DeleteStudentList(StudentList &stu_list)
{
	// cout << "通过输入 学生学号 删除请按 1,通过输入 学生姓名 删除请按 2,按其他键取消操作:" << endl;
	cout << "请选择操作选项:\n1. 通过学生学号进行查询并删除\n2. 通过学生姓名进行查询并删除\n3. 按其他键取消操作\n";
	int select;
	cin >> select;
	while (cin.fail())
	{ // cin输入异常处理
		cin.clear();
		cin.ignore();
		cout << "输入错误,请重新输入:";
		cin >> select;
	}
	switch (select)
	{
	case 1:
	{
		string number;
		cout << "请输入待删除学生的学号:" << endl;
		cin >> number;
		int index = SearchStudentListByNumber(stu_list, number); // 查询
		DeleteStudentListByIndex(stu_list, index);
		break;
	}
	case 2:
	{
		string name;
		cout << "请输入待删除学生的姓名:" << endl;
		cin >> name;
		int index = SearchStudentListByName(stu_list, name);
		DeleteStudentListByIndex(stu_list, index);
		break;
	}
	default:
	{
		cout << "操作取消成功!" << endl;
		system("pause");
		system("cls");
		return false;
		break;
	}
	}
}

/**
 * 2.7 修改学生信息
 */
// 根据查询到的index位序,对学生信息进行修改
bool ModifyStudentListByIndex(StudentList &stu_list, int index)
{
	if (index == -2)
	{
		cout << "当前学生列表为空!" << endl;
		system("pause");
		system("cls");
		return false;
	}
	else if (index == -1)
	{ // ==可不能写成=,那就会为 真 条件,必执行此分支
		cout << "查无此人!" << endl;
		system("pause");
		system("cls");
		return false;
	}
	else
	{
		cout << "查找成功!" << endl;
		cout << "请输入想要修改的信息项:\n1. 学号\n2. 姓名\n3. 性别\n4. 年龄\n5. 成绩\n"
			 << endl;
		int select2;
		cin >> select2;
		switch (select2)
		{
		case 1:
		{
			string number;
			cout << "请输入新学号:" << endl;
			while (true)
			{
				cin >> number;
				if (SearchStudentListByNumber(stu_list, number) == -1)
				{ // 修改则该生必存在,前面的分支已经确定。
					stu_list.stu_array[index].number = number;
					break;
				}
				else
					cout << "学号重复,请输入新学号:";
			}
			break;
		}
		case 2:
		{
			string name;
			cout << "请输入新姓名:" << endl;
			cin >> name;
			stu_list.stu_array[index].name = name;
			break;
		}
		case 3:
		{
			cout << "请输入新性别:" << endl;
			cout << "1 -- 男" << endl;
			cout << "2 -- 女" << endl;
			int sex = 0;
			while (true)
			{ // 简单的输入合法性判断
				cin >> sex;
				if (sex == 1 || sex == 2)
				{
					stu_list.stu_array[index].sex = sex;
					break;
				}
				cout << "输入有误,请重新输入:" << endl;
			}
			break;
		}
		case 4:
		{
			cout << "请输入新年龄:" << endl;
			int age = 0;
			while (true)
			{ // 简单的输入合法性判断
				cin >> age;
				if (age > 0 && age < 150)
				{
					stu_list.stu_array[index].age = age;
					break;
				}
				cout << "输入有误,请重新输入:" << endl;
			}
			break;
		}
		case 5:
		{
			cout << "请输入新成绩:" << endl;
			int score = 0;
			for (int i = 0; i < 3; ++i)
			{
				while (true)
				{ // 简单的输入合法性判断
					cin >> score;
					if (score >= 0 && score <= 100)
					{
						stu_list.stu_array[index].score[i] = score;
						break;
					}
					cout << "输入有误,请重新输入:" << endl;
				}
			}
			break;
		}
		default:
			break;
		}
		cout << "修改成功!" << endl;
		system("pause");
		system("cls");
		return true;
	}
}

// 修改学生信息总函数,设计修改操作的总逻辑以及对内部小函数进行调用
bool ModifyStudentList(StudentList &stu_list)
{
	// cout << "通过输入 学生学号 修改请按 1,通过输入 学生姓名 修改请按 2,按其他键取消操作:" << endl;
	cout << "请选择操作选项:\n1. 通过学生学号进行查询并修改\n2. 通过学生姓名进行查询并修改\n3. 按其他键取消操作\n";
	int select;
	cin >> select;
	switch (select)
	{
	case 1:
	{
		string number;
		cout << "请输入待修改学生的学号:" << endl;
		cin >> number;
		int index = SearchStudentListByNumber(stu_list, number); // 查询
		ModifyStudentListByIndex(stu_list, index);
		break;
	}
	case 2:
	{
		string name;
		cout << "请输入待修改学生的姓名:" << endl;
		cin >> name;
		int index = SearchStudentListByName(stu_list, name); // 查询
		ModifyStudentListByIndex(stu_list, index);
		break;
	}
	default:
	{
		cout << "操作取消成功!" << endl;
		system("pause");
		system("cls");
		return false;
		break;
	}
	}
	return true;
}

/**
 * 2.8 根据学习成绩排序
 */
bool SortStudentList(StudentList &stu_list)
{
	if (stu_list.stu_size == 0)
	{
		cout << "学生列表为空!" << endl;
		system("pause");
		system("cls");
		return false;
	}
	int n;
	cout << "请选择数据项进行排序:\n1. 成绩1——C语言成绩\n2. 成绩2——数学成绩\n3. 成绩3——英语成绩\n";
	cin >> n;		  // 排序依据项,减1后映射到数组
	StudentInfo temp; // 中间变量
	for (int i = 0; i < stu_list.stu_size - 1; ++i)
	{ // 冒泡排序
		bool flag = false;
		for (int j = 0; j < stu_list.stu_size - 1 - i; ++j)
			if (stu_list.stu_array[j].score[n - 1] > stu_list.stu_array[j + 1].score[n - 1])
			{
				temp = stu_list.stu_array[j];
				stu_list.stu_array[j] = stu_list.stu_array[j + 1];
				stu_list.stu_array[j + 1] = temp;
				flag = true;
			}
		if (flag == false) // 本躺遍历后没有进行交换,说明表已经有序,直接退出
			break;
	}
	cout << "排序后的学生信息:" << endl;
	ShowStudentList(stu_list);
	// system("pause");  // ShowStudentList()有系统暂停了
	// system("cls");
	return true;
}

/**
 * 2.9 清空学生信息
 */
bool ClearStudentList(StudentList &stu_list)
{
	if (stu_list.stu_size == 0)
	{
		cout << "学生列表已为空!" << endl;
		system("pause");
		system("cls");
		return false;
	}
	cout << "请再次确认是否清空所有学生信息?(y/n)" << endl;
	char input;
	while (true)
	{
		cin >> input;
		switch (tolower(input))
		{
		case 'y':
		{
			cout << "请输入管理员密码:";
			string code;
			while (true)
			{
				cin >> code;
				if (code == CODE)
				{
					stu_list.stu_size = 0; // 核心语句
					cout << "成功清空所有学生信息!" << endl;
					system("pause");
					system("cls");
					return true;
				}
				else if (code == "Q")
				{
					cout << "取消操作成功!" << endl;
					system("pause");
					system("cls");
					return true;
				}
				else
				{
					cout << "密码输入错误!请重新输入(输入 Q 取消本次操作。):";
				}
			}
			break;
		}
		case 'n':
		{
			cout << "取消清空操作成功!" << endl;
			system("pause");
			system("cls");
			return false;
		}
		default:
		{
			cout << "请输入字母 y 或者 n:";
			break;
		}
		}
	}
	/*if (input == "yes" || input == "YES") {
		cout << "请输入管理员密码:";
		string code;
		while (true) {
			cin >> code;
			if (code == CODE) {
				stu_list.stu_size == 0;
				cout << "成功清空所有学生信息!" << endl;
				system("pause");
				system("cls");
				return true;
			} else {
				cout << "密码输入错误!请重新输入:" << endl;
			}
		}
	} else {
		cout << "取消清空操作成功!" << endl;
		system("pause");
		system("cls");
		return false;
	}*/
}

/**
 * 2.10 文件读写
 */

// 从文件读取学生信息
bool ReadStudentInfoFromTxt(StudentList &stu_list)
{
	char txt_path[50];
	cout << "请输入文件路径:";
	cin >> txt_path; // 输入文件地址
	FILE *fp;
	// StudentInfo *p = (StudentInfo *)malloc(sizeof(StudentInfo) * TEMPSIZE); // c方式,为指针分配空间

	// StudentList stu2;
	// StudentInfo *p = stu2.stu_array;
	StudentInfo *p = new StudentInfo[TEMPSIZE]; // c++方式动态分配内存
	if ((fp = fopen(txt_path, "rt")) == NULL)
	{
		printf("Error on open \"%s\" file!\n", txt_path);
		system("pause");
		system("cls");
		return false;
	}
	while (true)
	{
		// 判满
		if (stu_list.stu_size >= MAX)
		{
			cout << "学生列表已满,无法继续添加!" << endl;
			system("pause");
			system("cls");
			return false;
		}
		// 读出
		fread(p, sizeof(StudentInfo), 1, fp);
		if (!feof(fp))
		{
			// 打印
			cout << "学号\t\t"
				 << "姓名\t\t"
				 << "性别\t\t"
				 << "年龄\t\t"
				 << "成绩1\t成绩2\t成绩3\n";
			cout << p->number << "\t\t";
			cout << p->name << "\t\t";
			cout << (p->sex == 1 ? "男" : "女") << "\t\t";
			cout << p->age << "\t\t";
			for (int j = 0; j < 3; ++j)
				cout << p->score[j] << "\t";
			cout << endl;
			// 保存
			stu_list.stu_array[stu_list.stu_size].number = p->number;
			stu_list.stu_array[stu_list.stu_size].name = p->name;
			stu_list.stu_array[stu_list.stu_size].sex = p->sex;
			stu_list.stu_array[stu_list.stu_size].age = p->age;
			for (int j = 0; j < 3; ++j)
				stu_list.stu_array[stu_list.stu_size].score[j] = p->score[j];
			stu_list.stu_size++; // 学生表长+1
			p++;				 // 中间变量指针后移
		}
		else
		{
			fclose(fp);
			cout << "读取完毕!" << endl;
			system("pause");
			system("cls");
			return true;
		}
	}
}

// 保存学生信息到文件
bool WriteStudentListToTxt(StudentList stu_list)
{
	if (IsEmpty(stu_list))
	{
		cout << "学生列表目前为空!无需保存。" << endl;
		system("pause");
		system("cls");
		return false;
	}
	else
	{
		char txt_path[50];
		cout << "请输入文件路径:";
		cin >> txt_path; // 输入文件地址
		FILE *fp;
		StudentInfo *p;
		p = stu_list.stu_array; // 令指针指向学生表
		if ((fp = fopen(txt_path, "wt")) == NULL)
		{ // 以 写模式、二进制类型 打开文件
			printf("Error on open \"%s\" file!", txt_path);
			system("pause");
			system("cls");
			return false;
		}
		// for (int i = 0; i < stu_list.stu_size; ++i)
		// 	fwrite(p, sizeof(StudentInfo), 1, fp);
		fwrite(p, sizeof(StudentInfo), stu_list.stu_size, fp); // 写入学生信息
		fclose(fp);											   // 关闭文件
		cout << "保存成功!" << endl;
		system("pause");
		system("cls");
		return true;
	}
}

// 清空文件所有学生信息
bool ClearStudentInfoInTxt()
{
	char txt_path[50];
	cout << "请确认是否继续清空文件中所有学生信息?(y/n)" << endl;
	char input;
	while (true)
	{
		cin >> input;
		switch (tolower(input))
		{
		case 'y':
		{
			cout << "请输入管理员密码:";
			string code;
			while (true)
			{
				cin >> code;
				if (code == CODE)
				{
					cout << "请输入文件路径:";
					cin >> txt_path; // 输入文件地址
					FILE *fp;
					if ((fp = fopen(txt_path, "wb")) == NULL)
					{ // 以 wb模式 打开文件,已存在则删除新建,不存在则建立。
						printf("Error on open \"%s\" file!", txt_path);
						system("pause");
						system("cls");
						return false;
					}
					fclose(fp);
					cout << "成功清空文件所有学生信息!" << endl;
					system("pause");
					system("cls");
					return true;
				}
				else if (code == "Q")
				{
					cout << "取消操作成功!" << endl;
					system("pause");
					system("cls");
					return true;
				}
				else
				{
					cout << "密码输入错误!请重新输入(输入 Q 取消本次操作。):";
				}
			}
			break;
		}
		case 'n':
		{
			cout << "取消清空操作成功!" << endl;
			system("pause");
			system("cls");
			return false;
		}
		default:
		{
			cout << "请输入字母 y 或者 n:";
			break;
		}
		}
	}
}

/**
 * 2.11 学生成绩统计
 */
// 求第 i 门成绩最高分
float FindHighestScore(StudentList stu_list, int i)
{
	float max = stu_list.stu_array[0].score[i - 1];
	for (int j = 1; j < stu_list.stu_size; ++j)
		if (stu_list.stu_array[j].score[i - 1] > max)
			max = stu_list.stu_array[j].score[i - 1];
	return max;
}

// 求第 i 门成绩最低分
float FindLowestScore(StudentList stu_list, int i)
{
	float min = stu_list.stu_array[0].score[i - 1];
	for (int j = 1; j < stu_list.stu_size; ++j)
		if (stu_list.stu_array[j].score[i - 1] < min)
			min = stu_list.stu_array[j].score[i - 1];
	return min;
}

// 求第 i 门成绩平均分
float FindAverageScore(StudentList stu_list, int i)
{
	float avg = 0.0;
	for (int j = 0; j < stu_list.stu_size; ++j)
		avg += stu_list.stu_array[j].score[i - 1];
	return avg / stu_list.stu_size;
}

// 求不及格人数
int CountFlunks(StudentList stu_list, int i)
{
	int count = 0;
	for (int j = 0; j < stu_list.stu_size; ++j)
		if (stu_list.stu_array[j].score[i - 1] < 60)
			count++;
	return count;
}

// 求优秀人数
int CountExcellentStudents(StudentList stu_list, int i)
{
	int count = 0;
	for (int j = 0; j < stu_list.stu_size; ++j)
		if (stu_list.stu_array[j].score[i - 1] > 80)
			count++;
	return count;
}

// 成绩统计
void StudentScoreStatistics(StudentList stu_list)
{
	int select = 0, index = 0;
	cout << "成绩统计开始……\n请选择统计依据项:\n1. C语言成绩\n2. 数学成绩\n3. 英语成绩\n";
	cin >> index;
	while (1)
	{
		cout << "请选择统计内容:\n1. 最高分\n2. 最低分\n3. 平均分\n4. 不及格人数\n5. 优秀人数\n0. 取消操作返回上级菜单\n";
		cin >> select;
		switch (select)
		{
		case 1:
			cout << "该科目成绩的最高分: " << FindHighestScore(stu_list, index) << endl;
			system("pause");
			system("cls");
			break;
		case 2:
			cout << "该科目成绩的最低分: " << FindLowestScore(stu_list, index) << endl;
			system("pause");
			system("cls");
			break;
		case 3:
			cout << "该科目成绩的平均分: " << FindAverageScore(stu_list, index) << endl;
			system("pause");
			system("cls");
			break;
		case 4:
			cout << "该科目成绩不合格人数: " << CountFlunks(stu_list, index) << endl;
			system("pause");
			system("cls");
			break;
		case 5:
			cout << "该科目成绩优秀人数: " << CountExcellentStudents(stu_list, index) << endl;
			system("pause");
			system("cls");
			CountExcellentStudents(stu_list, index);
			break;
		case 0:
			cout << "取消成功!!!" << endl;
			system("pause");
			system("cls");
			return;
		default:
		{
			cout << "输入错误!请重新输入!\n";
			break;
		}
		}
	}
}

// 学生信息统计总函数
bool StudentInfoStatistics(StudentList stu_list)
{
	int select = 0;
	// cout << "学生信息统计开始……\n请选择统计选项:\n1. 成绩统计\n2. 成绩排名\n";
	while (1)
	{
		cout << "学生信息统计开始……\n请选择统计选项:\n1. 成绩统计\n2. 成绩排名\n0. 取消操作返回主菜单\n";
		cin >> select;
		switch (select)
		{
		case 1:
			StudentScoreStatistics(stu_list);
			break;
		case 2:
			SortStudentList(stu_list);
			break;
		case 0:
			cout << "取消成功!!!" << endl;
			system("pause");
			system("cls");
			return false;
		default:
			cout << "输入错误!请重新输入:";
			break;
		}
	}
	return true;
}

/**
 * 3. 主函数
 */
int main()
{
	StudentList stus_list;		// 定义全局结构体变量
	InitStudentList(stus_list); // 初始化
	int select = 0;
	while (true)
	{ // 死循环,只要里面设置return就行。
		ShowMenu();
		cout << "请输入操作选项:";
		cin >> select;
		while (cin.fail())
		{ // cin输入异常处理
			cin.clear();
			cin.ignore();
			cout << "输入错误,请重新输入:";
			cin >> select;
		}
		switch (select)
		{
		case 1: // 1. 添加学生信息
			AddStudentList(stus_list);
			break;
		case 2: // 2. 显示学生信息
			ShowStudentList(stus_list);
			break;
		case 3: // 3. 删除学生信息
			DeleteStudentList(stus_list);
			break;
		case 4: // 4. 查询学生信息
			FindStudentList(stus_list);
			break;
		case 5: // 5. 修改学生信息
			ModifyStudentList(stus_list);
			break;
		case 6: // 6. 统计学生信息
			StudentInfoStatistics(stus_list);
			break;
		case 7: // 7. 清空学生信息
			ClearStudentList(stus_list);
			ClearStudentInfoInTxt();
			break;
		case 8: // 8. 保存学生信息到文件
			WriteStudentListToTxt(stus_list);
			break;
		case 9: // 9. 从文件读取学生信息
			ReadStudentInfoFromTxt(stus_list);
			break;
		case 0:
		{
			// 0. 退出管理系统
			cout << "欢迎下次使用!" << endl;
			exit(0);
			// return 0;
		}
		default:
			cout << "输入错误,请重新输入!" << endl;
			break;
		}
	}
	return 0;
}

/*
 * 文件名后缀为 .cpp
 * 用 VSCode 编辑代码的话,需要把文件改为以 GBK 模式保存打开,(下载个 Code Runner 插件会很舒服)
 */



四、总结

1. BUGS & QUESTIONS & ANSWERS

  1. 设置不能输入重复学号number?
    • if (SearchStudentListByNumber(stu_list, number) == -1) {...}
  2. int型数据输入其他值报错?
    • try catch
    • if(cin.fail())
  3. 排序?
    • 把冒泡排序、快速排序等排序算法的ElemType换一下就行。
  4. 怎么输出格式整齐?(\t的话,某数据超过其数据类型长度,\t就不整齐了。)
    • printf 进行格式化输出。
  5. 修改操作出错,总改不了?
    • stu_list.stu_array[stu_list.stu_size].name = name; 改为 stu_list.stu_array[index]...
  6. 查询、删除、修改时,名字重复的学生只能查出来第一个被查到的。
    • ???
  7. 输入浮点数成绩直接报错?
    • 中间变量初始化 score 的时候类型定义错了。定义为 int 了。
  8. 从文件读取信息保存,找不到合适的解决方案?
    • fwritefread+feof
    • 用 指针变量 存储信息,需要提前分配好空间!!!
      struct StudentInfo *p = (struct StudentInfo *)malloc(sizeof(struct StudentInfo) * TEMPSIZE);
    • 明明正常运行,学生表却没有改变! ==> 函数参数要加引用!!!
    • 总是多读取一行?解决 feof() 判断文件末尾多读一次的方法
      • 先 if(!feof(fp)) 再 fread() 改为 先fread()再if
    • 从文件读取学生信息可能与新输入过的信息学号冲突

      因为只有通过了 添加学生 函数的限制条件,才能保存,所以文件内的数据都是正常合法的,只有 学号信息的唯一性 无法保证。

      • 法1:进入系统强制从文件读取信息刷新学生表,然后再利用添加学生信息函数的判重去限制 ✅
      • 法2:从文件读取增加学号重复判断。
    • 读取的数据,其他信息都正常,学号、姓名是空的?而且同一次程序中读取学生数据就没问题,保存后退出程序,下次运行就读不到 学号和名字。
      • (是string的问题,还是编码问题?)???
  9. 该系统主要用c语言,但是输入输出用了c++的cin\cout,数据类型也用了c++的string,以及函数的传引用。对C语言学者不太好。
    • 但是,cin/cout 是真的好用!!不需要自己填写类型。
    • string也是,比字符数组好用多了。
    • 函数传引用,这样修改形参实现对实参变量的修改,不用传引用的话,只能用 指针
  10. 你能在开关中使用 OR关系 吗?——case 'Y'||'y': ...
    • 不能!!!最好是用 tolower() 转变为小写,再进行 case

2. SUMMARY

  1. while(true)+if&break 即可实现简单的循环合法性判断,用 while+switch 也可。
    该系统中我用了多种结构进行尝试。不仅是 语法关键字选择,还有输入语句 cin 位置的区别(循环内/循环外)
  2. 通过形参改变变量值 方法:
    • (1) 指针
      AddStudentList (StudentList* stu_list)+传地址&
    • (2) 传引用
      AddStudentList (StudentList &stu_list)
  3. 学生存储结构,对于名字学号这一类的信息,可以用
    • (1) char数组 + strcmp等字符串函数 + %s (char类型数据只能直接输入/用字符串函数,不能直接赋值)
    • (2) string + 可直接用字符串赋值 + cin直接输入 等便捷操作
  4. 存储结构只是结构体数组也可以,但是多一个表示当前长度的 length 属性,会方便很多。比如清空的时候,直接让 length=0 即可。
  5. 经常重复用的代码块可以封装为函数。如 xxxByIndex() 函数
  6. 设置合适的提示和暂停、清屏 coutsystem("pause")system("cls")
  7. 赋值语句 = 千万不要写成 ==
  8. 想设置输入判断,错误重新输入,就往外套 while(true),里面添个 return;无限套都可
  9. 往任何地方(变量/文件)保存,就必须检测是否已经存在。
  10. break,return,exit
    • break只能中断switch/循环,return能中断一个函数,exit中断一个程序。
  11. 总结逻辑
    • (1) 添加学生信息

      • 判满
      • 在表尾插入新元素
      • 当前表大小+1
      • while(true)+if,break+SearchStudentListByNumber 实现学号查重,输入合法性判断等
      • 输出注意:cout << (stu_list.stu_array[i].sex == 1 ? "男" : "女");
    • (2) 显示学生信息

      • 判空
      • 显示学生性别信息需要用三目运算符进行简单转换显示
    • (3) 删除学生信息

      • 查询到学生信息 SearchStudentListByNumber/SearchStudentListByName
      • 判空
      • 将 待删学生信息 后的信息往前移一位,覆盖 待删学生信息
      • 表长度-1
    • (4) 查询学生信息

      • 顺序查找到学生位序 SearchStudentListByNumber/SearchStudentListByName
      • 根据返回位序信息进行相关信息显示
    • (5) 修改学生信息

      • 查询到学生信息,返回 index
      • stu_array[index] 进行修改。直接赋值新值即可。
    • (6) 清空学生信息

      • 直接令 stu_size = 0 即可
    • (7) 排序学生信息

      • 用 冒泡排序/快速排序等排序算法 的逻辑,对学生表进行排序。

        以 学生表元素的成绩元素 为大小判断依据,以 学生表元素 为中间变量进行位置交换。

    • (0) 退出管理系统

      • exit(0)

该系统也没用到什么复杂的数据结构,就是最简单的顺序表。



希望对大家有所帮助和启发~
一键三连!!!😎😎😎

相当不错的一个成绩管理系统 #include #include #include #include using namespace std; enum {SUBJECT=5};//一共五门 typedef struct { char subject[10];//科目名称 int score;//科目成绩 }markinfo; typedef struct studentnode { markinfo mark[SUBJECT]; int totalmark; char name[10];//学生姓名 studentnode * next; }studentnode; class student { studentnode * head; public: student(); int addstudent(); ~student(); int countmark(); int sortbymark(); int save(); int show(); int display(); int readfiletolist(); int searchbyname(); }; student::student() //用构造函数来初始化。 { head=new studentnode; head->next=NULL; } //1.输入学生姓名、成绩等数据,并保存在链表中。 int student::addstudent() { studentnode * p; int i; char check; system("cls"); cout<<"**********************"<<endl; cout<<"请输入学生信息:"<<endl; do { p=new studentnode; cin.ignore(); cout<name); i=0; p->totalmark=0; do { cout<mark[i].subject); cout<>p->mark[i].score; } while(p->mark[i].score>100||p->mark[i].scoretotalmark=p->totalmark+p->mark[i].score; getchar(); } while(++i!=SUBJECT); if(head->next==NULL) { head->next=p;p->next=NULL; } else { p->next=head->next; head->next=p; } cout<next; if(p==NULL) { cout<<"没有学生,请重新输入"<<endl;system("pause");return 0; } else { cout<<"***************"<<endl; cout<<"学生成绩汇总:"<<endl; while(p) { cout<<"姓名:"<name<<" 总成绩:"<totalmark<next; } } system("pause"); return 0; } //4.输出所有学生成绩到一个文件中。 int student::save() { char address[35]; int i; studentnode * p=head->next; cout<<"请输入保存的地址"<<endl; cin.ignore(); gets(address); ofstream fout; fout.open(address,ios::app|ios::out); while(p) { fout<<"*"; fout<name<<"*"; i=0; while(i!=SUBJECT) { fout<mark[i].subject<<"*"; fout<mark[i].score; i++; } //fout<next; } fout.flush(); fout.close(); cout<next; while(p) { s=p->next; delete p; p=s; } delete head; } //3.按照总成绩大小对记录进行排序 int student::sortbymark() { studentnode *move1=head->next; studentnode *move2,*max,*pre1,*pre2,*maxpre,*s=move1; if(head->next==NULL) { cout<<"没有记录,请添加"<next!=NULL;pre1=move1,maxpre=pre1,move1=move1->next,max=move1) { for(pre2=move1,move2=move1->next;move2!=NULL;pre2=move2,move2=move2->next) if(move2->totalmark>max->totalmark) { maxpre=pre2; max=move2; } if(move1->next==max) //交换max和move1。 { pre1->next=max; move1->next=max->next; max->next=move1; move1=max; } else { s=move1->next; move1->next=max->next; max->next=s; maxpre->next=move1; pre1->next=max; move1=max; } } cout<<"已经按照从大到小排序"<next; int i; if(head->next==NULL){cout<<"没有学生记录,请添加"<<endl;system("pause"); return 0;} else { while(p) { cout<<"姓名:"<name; i=1; while(i!=SUBJECT+1) { cout<<"科目:"<mark[i-1].subject; cout<<" 成绩:"<mark[i-1].score; i++; } cout<next; } } system("pause"); return 0; } //6:从文件按读取记录 int student::display() { ifstream fin; char buf[100]; char str[25]; cout<<"请输入路径及文件名:"<<endl; cin.ignore(); gets(str); fin.open(str); if(!fin) { cout<<"没有此文件"<<endl; system("pause"); return 0; } while(fin) { fin.getline(buf,sizeof(buf)); cout<<buf<<endl; } system("pause"); return 0; } //8从文件中读取数据,并将数据保存在链表中 int student::readfiletolist() { ifstream fin; int i; char str[25]; cout<<"请输入路径及文件名:"<<endl; cin.ignore(); gets(str); fin.open(str); if(!fin) { cout<<"没有此文件"<totalmark=0; fin.getline(p->name,100,'*'); i=0; while(i!=SUBJECT) { fin.getline(p->mark[i].subject,100,'*'); fin>>p->mark[i].score; p->totalmark+=p->mark[i].score; i++; } if(head->next==NULL) { head->next=p; p->next=NULL; } else { p=head->next; head->next=p; } } cout<<"信息已经保存在链表中"<next==NULL) { cout<<"没有学生,请添加或者从文件中读取"<next; char findname[10]; int i; cout<name,findname)) { cout<<"经查找,找到该生信息如下:"<<endl<<endl; cout<<"姓名:"<name; i=1; while(i!=SUBJECT+1) { cout<<"科目:"<mark[i-1].subject; cout<<" 成绩:"<mark[i-1].score; i++; } cout<next; } cout<<"没有此学生,请添加或者从文件中读取"<<endl; system("pause"); return 0; } int showmenu() { int choice; char * menu[9]={ "1:输入学生成绩保存到链表\n", "2:计算每位学生总成绩\n", "3:按照总成绩大小对记录进行排序\n", "4:输出所有学生成绩到一个文件中\n", "5:显示新输入的学生信息\n", "6:从文件中读取信息\n", "7:将文件信息保存在链表中\n", "8:根据姓名查找学生记录\n", "9:结束程序\n" }; cout<<" "<<"*****************************************************"<<endl; cout<<" *"<<" "<<"学生成绩管理系统"<<" *"<<endl; cout<<" "<<"*****************************************************"<<endl; for(choice=0;choice<9;choice++) cout<<" "<<menu[choice]; cout<<" "<<"*****************************************************"<<endl; cout<<"please choose to continue"<>choice; } while(choice>9||choice<1); return choice; } int main() { int menuitem,flag=1; student stu; while(flag) { system("cls"); menuitem=showmenu(); switch(menuitem) { case 1:{stu.addstudent();break;} case 2:{stu.countmark();break;} case 3:{stu.sortbymark();break;} case 4:{stu.save();break;} case 5:{stu.show();break;} case 6:{stu.display();break;} case 7:{stu.readfiletolist();break;} case 8:{stu.searchbyname();break;} case 9:{flag=0;break;} } } return 0; }
好的,学生成绩管理系统C++,主要包括以下功能: 1. 学生信息的录入和修改 2. 成绩的录入和修改 3. 成绩的查询和统计 4. 成绩的排名和分析 下面是一份简单的代码实现,供你参考: ```c++ #include<iostream> #include<string> #include<iomanip> using namespace std; struct Student { string name; // 学生姓名 int num; // 学生学号 float score[3]; // 三门课的成绩 float sum; // 总分 float aver; // 平均分 int rank; // 排名 }; int main() { int n; // 学生人数 cout << "请输入学生人数:"; cin >> n; Student *stu = new Student[n]; // 动态分配内存 // 录入学生信息 for (int i = 0; i < n; i++) { cout << "请输入第" << i + 1 << "个学生的信息:" << endl; cout << "姓名:"; cin >> stu[i].name; cout << "学号:"; cin >> stu[i].num; cout << "数学成绩:"; cin >> stu[i].score[0]; cout << "英语成绩:"; cin >> stu[i].score[1]; cout << "计算机成绩:"; cin >> stu[i].score[2]; stu[i].sum = stu[i].score[0] + stu[i].score[1] + stu[i].score[2]; // 计算总分 stu[i].aver = stu[i].sum / 3; // 计算平均分 } // 计算排名 for (int i = 0; i < n; i++) { stu[i].rank = 1; for (int j = 0; j < n; j++) { if (stu[j].sum > stu[i].sum) { stu[i].rank++; } } } // 输出表头 cout << setw(10) << "姓名" << setw(10) << "学号" << setw(10) << "数学" << setw(10) << "英语" << setw(10) << "计算机" << setw(10) << "总分" << setw(10) << "平均分" << setw(10) << "排名" << endl; // 输出学生信息 for (int i = 0; i < n; i++) { cout << setw(10) << stu[i].name << setw(10) << stu[i].num << setw(10) << stu[i].score[0] << setw(10) << stu[i].score[1] << setw(10) << stu[i].score[2] << setw(10) << stu[i].sum << setw(10) << stu[i].aver << setw(10) << stu[i].rank << endl; } delete[] stu; // 释放内存 return 0; } ``` 这份代码实现了学生信息的录入和修改、成绩的录入和修改、成绩的查询和统计、成绩的排名和分析等功能。当然,你可以根据自己的需求进行修改和完善。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LiYikou

您的支持是我最大的动力~♥

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值