班级学生成绩管理系统——C/C++实现
- 项目功能基本完成,且有诸多改进,项目未完成的一两个小BUG都标注在文章末尾了,总体没有问题。✅
- 项目没怎么用C++的东西,就一个string类和c++的输入输出,还有个new和函数传引用。🤦🏻♂️
- 项目只能算是初级初级初级程序设计,数据结构是最简单的顺序表,没有数据库,没有可视化便捷操控界面,没有设计模式。(啥也不是😂)
- 希望能对入门程序猿们有一些帮助,一起 stronger。💪🏻
一、功能概述
使用 C 语言完成该系统的开发,通过该系统可实现对某班级(例如 B175A5 班)学生成绩信息的添加、查询、修改、删除、统计分析,以及数据保存、读取等功能。
二、功能详细说明
- 学生成绩信息录入
- 添加学生的成绩信息到系统中,主要包括学号、姓名、各科成绩。其中,学号的格式是:“班号+2 位数字”;成绩要求在 0~100 之间。若输入数据违法,则进行相应提
示。 - 判断输入的学号是否存在,若不存在,则添加到系统;否则,提示学号已存在,不
进行添加。 - 添加完成后,提示是否继续添加。如果不继续添加,则返回主菜单。
- 添加学生的成绩信息到系统中,主要包括学号、姓名、各科成绩。其中,学号的格式是:“班号+2 位数字”;成绩要求在 0~100 之间。若输入数据违法,则进行相应提
- 学生成绩信息查询
- 系统提供三种查询方式,按学号,按姓名,以及显示所有学生成绩信息。
- 如果查找成功,显示该学生的成绩信息;否则,提示未找到。
- 学生成绩信息修改
- 系统提供两种方式进行修改,可按姓名或学号来进行。
- 修改时,先按照提供的信息进行查找,若查找成功,则可输入该学生新的成绩信息;否则,提示该学生不存在。
- 学生成绩信息删除
- 系统只提供按照学生的学号进行删除。
- 删除时,首先输入学生的学号,若查找到该生的信息,则将其从系统中删除;否则,提示提示该学生不存在。
- 学生成绩信息统计
- 系统提供了选择成绩统计和成绩排名两种操作。
- 选择成绩统计时,先提示对哪门课(英语、数学、计算机)进行统计,然后提示统计方式。可统计最高分、最低分、平均分、排名、不及格的人数、优秀的人数,选择后显示相应的统计结果。
- 选择成绩排序时,先提示对哪门课(英语、数学、计算机)进行成绩排序,选择后显示相应排序结果。
- 文件操作
- 系统中所有的学生成绩系统都以二进制形式保存在文件中。
三、代码实现
#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
- 设置不能输入重复学号number?
if (SearchStudentListByNumber(stu_list, number) == -1) {...}
- int型数据输入其他值报错?
try catch
if(cin.fail())
- 排序?
- 把冒泡排序、快速排序等排序算法的
ElemType
换一下就行。
- 把冒泡排序、快速排序等排序算法的
- 怎么输出格式整齐?(
\t
的话,某数据超过其数据类型长度,\t
就不整齐了。)- 用
printf
进行格式化输出。
- 用
- 修改操作出错,总改不了?
stu_list.stu_array[stu_list.stu_size].name = name;
改为stu_list.stu_array[index]...
- 查询、删除、修改时,名字重复的学生只能查出来第一个被查到的。
- ???
- 输入浮点数成绩直接报错?
- 中间变量初始化
score
的时候类型定义错了。定义为int
了。
- 中间变量初始化
- 从文件读取信息保存,找不到合适的解决方案?
- 用
fwrite
、fread+feof
- 用 指针变量 存储信息,需要提前分配好空间!!!
struct StudentInfo *p = (struct StudentInfo *)malloc(sizeof(struct StudentInfo) * TEMPSIZE);
- 明明正常运行,学生表却没有改变! ==> 函数参数要加引用!!!
- 总是多读取一行?解决
feof()
判断文件末尾多读一次的方法先 if(!feof(fp)) 再 fread()
改为先fread()再if
- 从文件读取学生信息可能与新输入过的信息学号冲突
因为只有通过了 添加学生 函数的限制条件,才能保存,所以文件内的数据都是正常合法的,只有 学号信息的唯一性 无法保证。
- 法1:进入系统强制从文件读取信息刷新学生表,然后再利用添加学生信息函数的判重去限制 ✅
- 法2:从文件读取增加学号重复判断。
- 读取的数据,其他信息都正常,学号、姓名是空的?而且同一次程序中读取学生数据就没问题,保存后退出程序,下次运行就读不到 学号和名字。
- (是string的问题,还是编码问题?)???
- 用
- 该系统主要用c语言,但是输入输出用了c++的cin\cout,数据类型也用了c++的string,以及函数的传引用。对C语言学者不太好。
- 但是,cin/cout 是真的好用!!不需要自己填写类型。
- string也是,比字符数组好用多了。
- 函数传引用,这样修改形参实现对实参变量的修改,不用
传引用
的话,只能用指针
。
- 你能在开关中使用 OR关系 吗?——
case 'Y'||'y': ...
- 不能!!!最好是用
tolower()
转变为小写,再进行case
。
- 不能!!!最好是用
2. SUMMARY
while(true)+if&break
即可实现简单的循环合法性判断,用while+switch
也可。
该系统中我用了多种结构进行尝试。不仅是 语法关键字选择,还有输入语句cin
位置的区别(循环内/循环外)- 通过形参改变变量值 方法:
- (1) 指针
AddStudentList (StudentList* stu_list)+传地址&
- (2) 传引用
AddStudentList (StudentList &stu_list)
- (1) 指针
- 学生存储结构,对于名字学号这一类的信息,可以用
- (1)
char数组
+strcmp等字符串函数
+%s
(char类型数据只能直接输入/用字符串函数,不能直接赋值) - (2)
string
+可直接用字符串赋值
+cin直接输入
等便捷操作
- (1)
- 存储结构只是结构体数组也可以,但是多一个表示当前长度的
length
属性,会方便很多。比如清空的时候,直接让length=0
即可。 - 经常重复用的代码块可以封装为函数。如
xxxByIndex()
函数 - 设置合适的提示和暂停、清屏
cout
、system("pause")
、system("cls")
- 赋值语句
=
千万不要写成==
- 想设置输入判断,错误重新输入,就往外套
while(true)
,里面添个return
;无限套都可 - 往任何地方(变量/文件)保存,就必须检测是否已经存在。
- break,return,exit
- break只能中断switch/循环,return能中断一个函数,exit中断一个程序。
- 总结逻辑
-
(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)
-
该系统也没用到什么复杂的数据结构,就是最简单的顺序表。
希望对大家有所帮助和启发~
一键三连!!!😎😎😎