学生成绩管理系统

系统功能:

  1. 成绩录入
  2. 成绩输出
  3. 成绩查询
  4. 成绩排序
  5. 身份验证

原来c语言代码为:

/*******************************************************************
* 名 称:学生成绩管理系统1.0 *
* 创建日期:2023-4-3 *
* 最后修改:2023-4-3 *
* 版 权:中国农业大学信息与电气工程学院 *
* 版 本 号:1.0 *
*******************************************************************/


#include <iostream>
#include <cstring>
using namespace std;

#define N 20 //数组的长度

/*******************************************************
功能:显示菜单
参数:无
返回值:无
*******************************************************/
void displayMenu()
{

cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
cout << "+ 学生成绩管理系统 +\n";
cout << "+ +\n";
cout << "+ 1. 录入 +\n";
cout << "+ 2. 输出 +\n";
cout << "+ 3. 查询 +\n";
cout << "+ 4. 排序 +\n";
cout << "+ 5. 结束 +\n";
cout << "+ +\n";
cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++\n";

}

/*******************************************************
功能:登陆函数,验证口令
参数:
类型:char []
说明:用户输入口令
返回值:1或0
类型:int
说明:1表示通过验证;0表示没有通过
*******************************************************/
int login()
{
char password[8];/*用户输入的口令*/
static char key[8] = "1234";
int count = 0;
int s = 0;

/*====验证用户的口令,如果三次输入均错误,则不允许进入系统====*/
do
{
count++;
cout << "请输入口令:";
cin>>password;
if (strcmp(password, key) == 0)
s = 1;
else
s = 0;
} while (s == 0 && count < 3);

return s;
}


/*******************************************************
功能:输入学生成绩到数组中
参数:
参数1:score[]
类型:int []
说明:学生成绩数组
参数2:length
类型:int
说明:要输入的学生成绩数组的长度
返回值:i
类型:int
说明:实际成绩数组的有效值个数
*******************************************************/
int inputScore(int score[], int length)
{
int i = 0;
int tmp;

cout << "请输入学生的成绩(以-1结束输入):\n";
do
{
cout << "第" << i + 1 << "个学生:";
cin >> tmp;
if (tmp >= 0 && tmp <= 100)
{
score[i] = tmp;
i++;
}
} while (tmp != -1 && i < length);

return i;
}
/*******************************************************
功能:输出数组中的学生成绩
参数:
参数1:score[]
类型:int []
说明:学生成绩数组
参数2:length
类型:int
说明:要输出的成绩数组的长度
返回值:无
类型:void
说明:
*******************************************************/
void outputScore(int score[], int length)
{
int i = 0;

cout << "学生成绩如下:\n";
for (i = 0; i < length; i++)
cout << i + 1 << "\t" << score[i] << endl;
cout << "\n";
}
/*******************************************************
功能:查找某个学生成绩是否在数组中,如果找到,则输出下标,
否则,显示没有找到。
参数:
参数1:score[]
类型:int []
说明:学生成绩数组
参数2:length
类型:int
说明:要输入的学生成绩数组的长度
参数2:xScore
类型:int
说明:要查找的学生成绩
返回值:k
类型:int
说明:
*******************************************************/
int queryScore(int score[], int length, int xScore)
{
int i;

for (i = 0; i < length; i++)
{
if (xScore == score[i])
{
return i;
}
}

return -1;
}

/*******************************************************
功能:排序学生的成绩,按照从小到大顺序排序。
参数:
参数1:score[]
类型:int []
说明:学生成绩数组
参数2:length
类型:int
说明:要输入的学生成绩数组的长度
返回值:无
类型:void
说明:
*******************************************************/
void sortScore(int score[], int length)
{
int i, j, t;
cout << "成绩排序如下:\n";
for (i = 0; i < length - 1; i++)
{
for (j = 0; j < length - i - 1; j++)
if (score[j] > score[j + 1])
{
t = score[j];
score[j] = score[j + 1];
score[j + 1] = t;
}
}
}

/*******************************************************
功能:主函数
参数:无
返回值:无
*******************************************************/
int main()
{
int choice = 0; /*代表用户选择的操作数字 */
int s = 0, datalen = 0, x, find;
int score[N];

/*====验证用户的口令====*/
if (login() == 0)
{
cout << "口令错误,不允许进入本系统!\n";
exit(0);
}


/*====根据用户的选择,执行相应的操作.====*/
while (1)
{

displayMenu();

cout << "\n 请选择您的操作(1,2,3,4,5):\n";
cin >> choice;

switch (choice)
{
case 1:
datalen = inputScore(score, N);
break;
case 2:
outputScore(score, datalen);
break;
case 3:
cout << "\n 请输入要查找的成绩:";
cin >> x;
find = queryScore(score, datalen, x);
if (find >= 0)
cout << "要查成绩在数组中的下表为:" << find << endl;
else
cout << "没有要查找的成绩:\n";
break;
case 4:
sortScore(score, datalen); outputScore(score, datalen);
break;
case 5:
exit(0);
break;

}
}
}
  • 代码解释:

  • void welcome();

    ​ 欢迎界面

  • int login();

    • 验证身份,成功返回1,否则返回0
    • 支持由数字和字符混合组成的口令
    • 最长为8位
    • 用户有三次录入机会,如果第三次失败,则不允许登录系统
  • void displayMenu();

    ​ 功能显示提示菜单

  • int inputScore(int s[],int len);int inputScore(int *s,int len);

    ​ 输入学生成绩数组中,如果学生的成绩输入-1,就表示输入结束,s为成绩数组,len为数组的最大列数;返回实际输入学生成绩的个数

  • void outputsScore(int s[],int len);void outputsScore(int *s,int len);

    ​ 输出学生成绩, s为成绩数组,len为实际存储的成绩个数

  • int queryScore(int s[],int len,int xScore);int queryScore(int *s,int len,int xScore);

    ​ 查询成绩。s为成绩数组,len为实际存储成绩个数;xScore为要查找的成绩,若找到该成绩,则返回该成绩的下标,否则返回-1

  • void count(int a[],int n,int b[]);void count(int *a,int n,int *b);

    • 统计成绩各个挡次中的人数90 ~ 100,80 ~ 89,70 ~ 79,60 ~ 69,0 ~ 59

    • a为学生成绩数组;n为数组实际长度;b为各挡人数数组

  • void sortScore(int ps[],int len);void sortScore(int *ps,int len);

    • 成绩升序排序
    • ps为成绩数组
    • len数组实际长度

将c语言代码改写为c++的类:

/*******************************************************************
* 名 称:学生成绩管理系统1.1 *
* 创建日期:2024-4-16 *
* 最后修改:2024-4-16 *
* 版 权:中国农业大学信息与电气工程学院 *
* 版 本 号:2.0 *
*******************************************************************/


#include "iostream"
#include <cstring>
using namespace std;

#define N 20 //数组的长度

/*******************************************************
功能:显示菜单
参数:无
返回值:无
*******************************************************/
void displayMenu()
{

cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
cout << "+ 学生成绩管理系统 +\n";
cout << "+ +\n";
cout << "+ 1. 录入 +\n";
cout << "+ 2. 输出 +\n";
cout << "+ 3. 查询 +\n";
cout << "+ 4. 排序 +\n";
cout << "+ 5. 结束 +\n";
cout << "+ +\n";
cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++\n";

}

/*******************************************************
功能:登陆函数,验证口令
参数:
类型:char []
说明:用户输入口令
返回值:1或0
类型:int
说明:1表示通过验证;0表示没有通过
*******************************************************/
int login()
{
char password[8];/*用户输入的口令*/
static char key[8] = "1234";
int count = 0;
int s = 0;

/*====验证用户的口令,如果三次输入均错误,则不允许进入系统====*/
do
{
count++;
cout << "请输入口令:";
cin >> password;
if (strcmp(password, key) == 0)
s = 1;
else
s = 0;
} while (s == 0 && count < 3);

return s;
}
class Score
{
private:
int* score;
int Mlen;
int length;
public:
Score(int* s, int n)
{
Mlen = n;
score = s;
}
void inputScore()
{
cout << "请输入学生的成绩(以-1结束输入):\n";
int i = 0;
int tmp;
do
{
cout << "第" << i + 1 << "个学生:";
cin >> tmp;
if (tmp >= 0 && tmp <= 100)
{
score[i] = tmp;
i++;
}
} while (tmp != -1 && i < Mlen);

length = i;
}
void outputScore()
{
int i = 0;
cout << "学生成绩如下:\n";
for (i = 0; i < length; i++)
cout << i + 1 << "\t" << score[i] << endl;
cout << "\n";
}
int queryScore(int x)
{
for (int i = 0; i < length; i++)
if (score[i] == x)
return i;
return -1;
}
void sortScore()
{
int i, j, t;
cout << "成绩排序如下:\n";
for (i = 0; i < length - 1; i++)
{
for (j = 0; j < length - i - 1; j++)
if (score[j] > score[j + 1])
{
t = score[j];
score[j] = score[j + 1];
score[j + 1] = t;
}
}
}

};

/*******************************************************
功能:主函数
参数:无
返回值:无
*******************************************************/
int main()
{
int choice = 0; /*代表用户选择的操作数字 */
int s = 0, datalen = 0, x, find;
int as[N];
Score testS(as, N);

/*====验证用户的口令====*/
if (login() == 0)
{
cout << "口令错误,不允许进入本系统!\n";
exit(0);
}

/*====根据用户的选择,执行相应的操作.====*/
while (1)
{

displayMenu();

cout << "\n 请选择您的操作(1,2,3,4,5):\n";
cin >> choice;

switch (choice)
{
case 1:
testS.inputScore();
break;
case 2:
testS.outputScore();
break;
case 3:
cout << "\n 请输入要查找的成绩:";
cin >> x;
find = testS.queryScore(x);
if (find >= 0)
cout << "要查成绩在数组中的下表为:" << find << endl;
else
cout << "没有要查找的成绩:\n";
break;
case 4:
testS.sortScore();
testS.outputScore();
break;
case 5:
exit(0);
break;
}
}
}

缺点及可补充功能:

  1. **数据持久化:**成绩数据只在程序运行期间存储在内存中,没有实现数据持久化。可以选择将数据保存在文件中

  2. 错误处理和用户输入验证:

    • 增加对用户输入的验证,确保输入的数据有效,检查成绩是否在合法范围(0-100分)之内。

    • 在用户输入非法时,给出明确的错误信息,并允许重新输入而不是立即退出。

  3. 增加更多成绩管理功能:

    • **统计功能:**计算全班的平均成绩、最高分、最低分等。

    • **成绩修改和删除:**允许用户修改或删除已录入的成绩。

    • **分组排序显示:**统计成绩各个挡次中的人数90 ~ 100,80 ~ 89,70 ~ 79,60 ~ 69,0 ~ 59

    • **实现多科目动态输入:**可输入多个学科的名称,实现对多个学科的成绩录入

优化修改后的代码 1.0 :

使用c++14实现(auto关键字)

可以实现:

  1. 读入数据(选项0)

    • 从一个指定的文本文件(scores.txt)中加载学生数据,包括学号、姓名和多个学科的成绩。
    • 每个学生的信息由学号、姓名、科目成绩构成,信息间通过换行分隔,不同学生之间通过空行分隔。
  2. 设置学科(选项1)

    • 允许用户输入一系列学科名称,通过空格分隔,输入-1结束输入。
    • 用户可以选择添加新的学科或重新设置所有学科。
  3. 录入成绩(选项2)

    • 允许用户为每个学科手动录入学生的成绩。
    • 用户需输入学号、姓名,然后为每个已设定的学科输入成绩。
  4. 显示成绩(选项3)

    • 显示当前系统中所有学生的学号、姓名和每个学科的成绩。
    • 如果某个学科的成绩不存在,则显示N/A
  5. 查询成绩(选项4)

    • 允许用户通过学号查询单个学生的所有科目成绩。
  6. 排序显示(选项5)

    • 按总成绩降序排序所有学生,若总成绩相同则按学号升序排序。
    • 显示排序后的学生列表,包括学号、姓名、各科成绩及总成绩。
  7. 统计成绩(选项6)

    • 对每个科目进行统计,包括最高分、最低分和平均分。
  8. 修改/删除成绩(选项7)

    • 允许用户修改指定学生的某科目成绩或删除整个科目的成绩。
    • 用户可以选择删除整个学生记录。
  9. 清除所有数据(选项8)

    • 清空系统中的所有学生记录。
  10. 保存并退出(选项9)

    • 将所有学生的数据保存到文本文件(scores.txt)中,并退出程序。
  11. 用户登录功能

    • 系统启动时要求用户输入密码,密码验证成功后才能访问以上功能。
/*******************************************************************
* 名 称:学生成绩管理系统1.1 *
* 创建日期:2024-4-16 *
* 最后修改:2024-4-18 *
* 版 权:中国农业大学信息与电气工程学院 *
* 版 本 号:3.0 *
*******************************************************************/
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include <string>
#include <iomanip>
#include <algorithm>

using namespace std;

const string dataFile = "scores.txt";

bool login() {
string password;
string correctPassword = "1234";
int attempts = 0;

while (attempts < 3) {
cout << "请输入密码:";
cin >> password;
if (password == correctPassword) {
return true;
}
else {
cout << "密码错误!还有 " << 2 - attempts << " 次机会。\n";
}
attempts++;
}
return false;
}

struct Student {
string id;
string name;
map<string, int> scores;
};

class ScoreManager {
private:
map<string, Student> students;
vector<string> subjects; // 存储学科名称列表

public:
void displayMenu() {
cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
cout << "+ 学生成绩管理系统 +\n";
cout << "+ 0. 读入数据 +\n";
cout << "+ 1. 设置学科 +\n";
cout << "+ 2. 录入成绩 +\n";
cout << "+ 3. 显示成绩 +\n";
cout << "+ 4. 查询成绩 +\n";
cout << "+ 5. 排序显示 +\n";
cout << "+ 6. 统计成绩 +\n";
cout << "+ 7. 修改/删除成绩 +\n";
cout << "+ 8. 清除所有数据 +\n";
cout << "+ 9. 保存并退出 +\n";
cout << "++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
}

void setSubjects() {
cout << "请选择您的操作(1或2):\n";
cout<<"1.添加学科\n";
cout<<"2.重新设置学科\n";
char choicee;
cin >> choicee;
switch (choicee) {
cout << "请输入学科名称,以空格分隔,输入-1结束:";

case '1': setSubjects1(); break;
case '2': setSubjects1(); break;
default: cout << "无效的输入。\n"; break;
}

cout << "已设置的学科有:";
for (const auto& sub : subjects) {
cout << sub << " ";
}
cout << endl;
}

void setSubjects1() {
string subject;
while (cin >> subject && subject != "-1") {
if (find(subjects.begin(), subjects.end(), subject) == subjects.end()) {
subjects.push_back(subject);
}
else {
cout << "科目 '" << subject << "' 已存在,跳过添加。\n";
}
}
}

void setSubjects2() {
subjects.clear();
string subject;
while (cin >> subject && subject != "-1") {
if (find(subjects.begin(), subjects.end(), subject) == subjects.end()) {
subjects.push_back(subject);
}
else {
cout << "科目 '" << subject << "' 已存在,跳过添加。\n";
}
}
}

void loadScores() {
ifstream file(dataFile);
if (!file.is_open()) {
cerr << "无法打开文件 " << dataFile << " 进行读取。\n";
return;
}

string line, id, name, ssubject;
int score;
Student student;
bool isNewStudent = true; // 标志是否读取新学生的学号

while (getline(file, line)) {
if (line.empty()) {
// 当遇到空行时,假设完成了一个学生的所有输入
if (!student.id.empty()) {
students[student.id] = student; // 保存当前学生的数据
student = Student(); // 重置学生对象
isNewStudent = true; // 准备读取下一个学生的数据
}
continue;
}

if (isNewStudent) {
// 读取学号
student.id = line;
isNewStudent = false; // 标记已经读取了学号
continue;
}

if (student.name.empty()) {
// 读取姓名
student.name = line;
continue;
}

// 读取科目和成绩
istringstream iss(line);
iss >> ssubject >> score;
if (find(subjects.begin(), subjects.end(), ssubject) == subjects.end()) {
subjects.push_back(ssubject);
}
student.scores[ssubject] = score;
}

// 确保文件结束时最后一个学生也被添加
if (!student.id.empty() && !student.name.empty()) {
students[student.id] = student;
}

file.close();
cout<<"数据已读取。读取数据如下:\n";
outputScores();
}

void inputScores() {
cout << "开始输入成绩。请输入学号和姓名,对于每个学科输入成绩:\n";
while (true) {
Student student;
cout << "请输入学号(输入-1结束输入):";
cin >> student.id;
if (student.id == "-1") break;
cout << "请输入姓名:";
cin >> student.name;
for (const auto& subject : subjects) {
while (true) {
int score;
cout << "请输入 " << subject << " 的成绩:";
cin >> score;
if (score >= 0 && score <= 100) {
student.scores[subject] = score;
break; // 成绩有效,跳出内部循环
}
else {
cout << "无效成绩,请输入0-100之间的数值。\n";
}
}
}
students[student.id] = student;
}
}

void outputScores() {
if (students.empty()) {
cout << "没有数据显示。\n";
return;
}
cout << left << setw(10) << "学号" << setw(15) << "姓名";
for (const auto& subject : subjects) {
cout << setw(10) << subject;
}
cout << endl;

for (const auto& pair : students) {
cout << setw(10) << pair.second.id << setw(15) << pair.second.name;
for (const auto& subject : subjects) {
auto it = pair.second.scores.find(subject);
if (it != pair.second.scores.end()) {
cout << setw(10) << it->second;
}
else {
cout << setw(10) << "N/A";
}
}
cout << endl;
}
}

void queryScore() {
string id;
cout << "请输入学号:";
cin >> id;
if (students.find(id) == students.end()) {
cout << "学号不存在!\n";
return;
}
Student& student = students[id];
cout << "学号 " << student.id << " 的成绩如下:\n";
for (const auto& score : student.scores) {
cout << score.first << ": " << score.second << endl;
}
}

void sortScores() {
// 将学生数据从map转移到vector,并计算每个学生的总分
vector<pair<Student, int>> sortedStudents;
for (const auto& pair : students) {
int totalScore = 0;
for (const auto& score : pair.second.scores) {
totalScore += score.second;
}
sortedStudents.push_back(make_pair(pair.second, totalScore));
}

// 对学生进行排序,首先按总分降序,若总分相同,则按学号升序
sort(sortedStudents.begin(), sortedStudents.end(),
[](const pair<Student, int>& a, const pair<Student, int>& b) {
if (a.second != b.second) {
return a.second > b.second; // 总分高的在前
}
return a.first.id < b.first.id; // 学号小的在前
});

// 输出排序后的学生信息
cout << left << setw(10) << "学号" << setw(15) << "姓名";
for (const auto& subject : subjects) {
cout << setw(15) << subject;
}
cout << setw(10) << "总成绩" << endl;

for (const auto& item : sortedStudents) {
const auto& student = item.first;
int totalScore = item.second;

cout << setw(10) << student.id << setw(15) << student.name;
for (const auto& subject : subjects) {
cout << setw(15) << student.scores.at(subject); // 显示每门科目的成绩
}
cout << setw(10) << totalScore; // 显示总成绩
cout << endl;
}
}

void statsScores() {
map<string, int> maxScores, minScores;
map<string, double> averageScores;
map<string, int> countScores;

// 初始化最大和最小分数
for (const auto& sub : subjects) {
maxScores[sub] = numeric_limits<int>::min(); // 设置最大分数为最小可能值
minScores[sub] = numeric_limits<int>::max(); // 设置最小分数为最大可能值
}

// 遍历所有学生的成绩
for (const auto& pair : students) {
for (const auto& score : pair.second.scores) {
const string& subject = score.first;
int value = score.second;
if (maxScores.find(subject) != maxScores.end()) {
maxScores[subject] = max(maxScores[subject], value);
}
if (minScores.find(subject) != minScores.end()) {
minScores[subject] = min(minScores[subject], value);
}
averageScores[subject] += value;
countScores[subject]++;
}
}

// 输出统计结果
for (const auto& subject : subjects) {
cout << subject << " - 最高分: " << maxScores[subject];
cout << ", 最低分: " << minScores[subject];
if (countScores[subject] > 0) { // 确保有成绩被录入
cout << ", 平均分: " << (averageScores[subject] / countScores[subject]);
}
else {
cout << ", 平均分: 无数据"; // 如果没有成绩数据,输出无数据
}
cout << "\n";
}
}

void modifyOrDeleteScores() {
string id;
cout << "请输入学号:";
cin >> id;
if (students.find(id) == students.end()) {
cout << "学号不存在!\n";
return;
}

cout << "当前成绩:";
for (const auto& score : students[id].scores) {
cout << score.first << ": " << score.second << " ";
}
cout << "\n请输入要修改的科目名称(输入\"delete\"删除学生记录):";
string subject;
cin >> subject;

if (subject == "delete") {
students.erase(id);
cout << "学生记录已删除。\n";
return;
}

if (students[id].scores.find(subject) == students[id].scores.end()) {
cout << "科目不存在!\n";
return;
}

int newScore;
cout << "输入新成绩(输入-1删除该科目成绩):";
cin >> newScore;
if (newScore == -1) {
students[id].scores.erase(subject);
cout << "该科目成绩已删除。\n";
}
else {
students[id].scores[subject] = newScore;
cout << "成绩已更新。\n";
}
}

void saveScores() {
ofstream file(dataFile);
if (!file.is_open()) {
cerr << "无法打开文件 '" << dataFile << "' 进行写入。\n";
return;
}

for (const auto& pair : students) {
file << pair.second.id << "\n" << pair.second.name << "\n";
for (const auto& score : pair.second.scores) {
file << score.first << " " << score.second << "\n";
}
file << "\n";
}

file.close();
}

void clearAllData() {
students.clear();
ofstream file(dataFile, ios::trunc);
if (!file.is_open()) {
cerr << "无法打开文件以清空内容。\n";
return;
}
file.close();
cout << "所有数据已被清除。\n";
}

};

int main() {
if (!login()) {
cout << "口令错误,不允许进入本系统!\n";
return 0;
}
ScoreManager manager;
while (true) {
manager.displayMenu();
cout << "请选择您的操作(0-9):";
char choice;
cin >> choice;
switch (choice) {
case '0': manager.loadScores(); break;
case '1': manager.setSubjects(); break;
case '2': manager.inputScores(); break;
case '3': manager.outputScores(); break;
case '4': manager.queryScore(); break;
case '5': manager.sortScores(); break;
case '6': manager.statsScores(); break;
case '7': manager.modifyOrDeleteScores(); break;
case '8': manager.clearAllData(); break;
case '9': manager.saveScores(); cout << "数据已保存,退出系统。\n"; return 0;
default: cout << "无效的输入,请重新输入。\n"; break;
}
}
return 0;
}

可以看到,对科目成绩的管理基本完善。在此的基础上,还可以添加对于综测成绩的管理。

加入:

  • 单科GPA计算与评级
  • 总GPA计算
  • 课外活动分数
  • 想品德成绩(该项默认为95分)
  • 参考信电学院综测计算公式:

综合测评成绩=GPA×70+思想品德成绩×10+课外活动表现×20+附加分100综合测评成绩=\frac{GPA×70 + 思想品德成绩 ×10 +课外活动表现×20+附加分}{100}

完整代码如下:

使用c++14:

/*******************************************************************
* 名 称:学生成绩管理系统1.1 *
* 创建日期:2024-4-21 *
* 最后修改:2024-4-22 *
* 版 权:中国农业大学信息与电气工程学院 *
* 版 本 号:4.0 *
*******************************************************************/
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <map>
#include <string>
#include <iomanip>
#include <algorithm>
#include <limits>
#include <numeric>
#include <utility>

using namespace std;

const string dataFile = "scores.txt";
// 登录函数
bool login() {
string password;
string correctPassword = "1234";
int attempts = 0;

while (attempts < 3) {
cout << "请输入密码:";
cin >> password;
if (password == correctPassword) {
return true;
}
else {
cout << "密码错误!还有 " << 2 - attempts << " 次机会。\n";
}
attempts++;
}
return false;
}

//单学科的信息
struct SubjectInfo {
int score; // 成绩
string grade; // 等级
double gpa; // 绩点
};

struct Student {

string id; // 学号
string name; // 姓名
string classId; // 班级
map<string, SubjectInfo> scores;// 学科信息
double gpa; // 绩点
double extracurricularActivitiesScore; // 课外活动分数
double comprehensiveScore; // 综测分数
// 更新综合测评成绩
void calculateComprehensiveScore() {
double academicScore = gpa * 25 * 1.0; // 获取基于 GPA 的学习成绩
double moralEducationScore = 95; // 思想品德成绩固定为95分
comprehensiveScore = (academicScore * 0.7) + (moralEducationScore * 0.1) + (extracurricularActivitiesScore * 0.2);
}
int gparank;//绩点排名
int comprehensiveRank;//综测排名
};


class ScoreManager {
private:
map<string, Student> students; // 学生数据
map<string, double> subjects; // 存储学科名称和学分
public:
void displayMenu() {
cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
cout << "+ 学生成绩管理系统 +\n";
cout << "+ 1. 添加或重置学科 +\n";
cout << "+ 2. 录入学生成绩 +\n";
cout << "+ 3. 显示学生成绩 +\n";
cout << "+ 4. 查询学生详细成绩 +\n";
cout << "+ 5. 按GPA或综测成绩排序学生 +\n";
cout << "+ 6. 统计和分析学科成绩 +\n";
cout << "+ 7. 修改或删除学生数据 +\n";
cout << "+ 8. 保存当前数据到文件 +\n";
cout << "+ 9. 从文件加载学生数据 +\n";
cout << "+ 0. 退出系统 +\n";
cout << "+ d. 清除数据 +\n";
cout << "+++++++++++++++++++++++++++++++++++++++++++++++++++++++\n";
}


void setSubjects() {
cout << "请选择您的操作(1或2):\n";
cout << "1.添加学科\n";
cout << "2.重新设置学科\n";
char choicee;
cin >> choicee;
if (choicee == '1' || choicee == '2') {
if (choicee == '2') {
subjects.clear();
cout << "原有学科已清空,请重新输入学科名称和学分:\n";
}
while (true) {
string name;
double credit;
cout << "请输入学科名称 (输入-1结束) : ";
getline(cin, name); // 读取一行作为科目名称


if (name == "-1") {
break;
}

if (subjects.find(name) != subjects.end()) {
cout << "“" << name << "”已存在!\n";
continue; // 跳过后续的学分输入,请求用户重新输入科目名称
}

cout << "请输入“ " << name << " ”所占学分: ";
cin >> credit; // 输入对应科目的学分
cin.ignore(numeric_limits<streamsize>::max(), '\n');

// 存储科目名称和学分
subjects[name] = credit;
}
}
else {
cout << "无效的输入。\n";
return;
}


cout << "已设置的学科有:" << endl;
for (const auto& subject : subjects) {
cout << subject.first << ": " << subject.second << " 学分\n";
}
}


void inputScores() {
cout << "开始录入成绩。\n";
cout << "------------------------------------\n";
while (true) {
Student student;
cout << "请输入学号(输入-1结束输入):";
cin >> student.id;
if (student.id == "-1") break;
cout << "请输入姓名:";
cin >> student.name;
cout << "请输入班级:";
cin >> student.classId;
for (auto& subject : subjects) {
while (1) {
int sco;
cout << "请输入学科: " << subject.first << " 的成绩:";
cin >> sco;
if (sco >= 0 && sco <= 100) {
student.scores[subject.first].score = sco;
break; // 成绩有效,跳出内部循环
}
else {
cout << "无效成绩,请输入0-100之间的数值。\n";
}
}
}
cout << "请输入课外活动分数:";
while (1) {
int tmp;
cin >> tmp;
if (tmp <= 0 || tmp > 50)
cout << "课外活动分数应在0-50之间,请重新输入:";
else {
student.extracurricularActivitiesScore = tmp;
break;
}
}
students[student.id] = student; // 将学生添加到映射中
cout << "------------------------------------\n";
}
updateStudentRecords();
}
//flag 1 各科成绩 2 综测成绩
void outputScores(int flag) {
flag--;
cout << fixed << setprecision(2);
if (students.empty()) {
cout << "没有数据显示。\n";
return;
}
if (!flag)
{
cout << left << setw(17) << "学号" << setw(10) << "姓名" << setw(10) << "班级";
for (const auto& subject : subjects) {
cout << setw(10) << subject.first;
}
cout << setw(10) << "GPA" << setw(5) << "GPA排名";
cout << endl;

for (const auto& pair : students) {
cout << setw(17) << pair.second.id << setw(10) << pair.second.name << setw(10) << pair.second.classId;
for (const auto& subject : subjects) {
auto it = pair.second.scores.find(subject.first);
cout << setw(10) << it->second.score;
}
cout << setw(10) << pair.second.gpa << pair.second.gparank << "/" << students.size();

cout << endl;
}
}
else {
cout << setw(17) << "学号" << setw(10) << "姓名" << setw(10) << "班级" << setw(10) << "绩点" << setw(10) << "绩点排名" << setw(15) << "课外活动分数" << setw(10) << "综测分数" << setw(10) << "综测排名" << endl;
for (const auto& pair : students) {
cout << setw(17) << pair.second.id << setw(10) << pair.second.name << setw(10) << pair.second.classId << setw(10) << pair.second.gpa << setw(10) << pair.second.gparank << setw(15) << pair.second.extracurricularActivitiesScore << setw(10) << pair.second.comprehensiveScore << setw(10) << pair.second.comprehensiveRank << endl;
}
}
}

void queryScore() {
cout << fixed << setprecision(2);
string id;
cout << "请输入学号:";
cin >> id;
queryScore(id);
}

void queryScore(string id) {
cout << fixed << setprecision(2);
if (students.find(id) == students.end()) {
cout << "学号不存在!\n";
return;
}
Student& student = students[id];
cout << "学号: " << student.id << " 姓名: " << student.name << " 班级: " << student.classId << endl;
cout << "成绩如下:\n";
cout << setw(10) << "学科名称" << setw(7) << "成绩" << setw(7) << "等级" << setw(7) << "绩点" << endl;
for (const auto& score : student.scores) {
cout << setw(10) << score.first << setw(7) << score.second.score << setw(7) << score.second.grade << setw(7) << score.second.gpa << endl;
}
cout << "课外活动分数" << student.extracurricularActivitiesScore << endl;
cout << "绩点" << student.gpa << endl;
cout << "综测分数" << student.comprehensiveScore << endl;
cout << "总绩点排名" << student.gparank << "/" << students.size() << endl;
cout << "总综测排名" << student.comprehensiveRank << "/" << students.size() << endl;
}

void sortAndOutput() {
cout << fixed << setprecision(2);
string option;
cout << "请选择排序选项:1.按 GPA 排序 2.按综测成绩排序\n";
cin >> option;
vector<pair<string, Student>> sortedStudents(students.begin(), students.end());

// GPA
if (option == "1") {
sort(sortedStudents.begin(), sortedStudents.end(),
[](const pair<string, Student>& a, const pair<string, Student>& b) {return a.second.gpa > b.second.gpa;
});
cout << "按 GPA 排序的学生信息:\n";
}
else if (option == "2") {
sort(sortedStudents.begin(), sortedStudents.end(),
[](const pair<string, Student>& a, const pair<string, Student>& b) {
return a.second.comprehensiveScore > b.second.comprehensiveScore;
});
cout << "按综测成绩排序的学生信息:\n";
}
else {
cout << "无效的排序选项。\n";
return;
}
cout << setw(17) << "学号" << setw(10) << "姓名" << setw(10) << "班级" << setw(10) << "GPA" << setw(10) << "综测成绩" << setw(10) << "绩点排名" << setw(10) << "综测排名" << endl;
// 输出排序后的学生信息
for (const auto& pair : sortedStudents) {
cout << setw(17) << pair.second.id << setw(10) << pair.second.name << setw(10) << pair.second.classId << setw(10) << pair.second.gpa << setw(10) << pair.second.comprehensiveScore << setw(3) << pair.second.gparank << "/" << setw(10) << students.size() << setw(3) << pair.second.comprehensiveRank << "/" << students.size() << endl;

}
}


void statsScores() {
cout << fixed << setprecision(2);
if (students.empty()) {
cout << "没有学生数据可以分析。\n";
return;
}

// 存储每个科目的成绩数据
map<string, vector<int> > subjectScores;
for (const auto& pair : students) {
for (const auto& score : pair.second.scores) {
subjectScores[score.first].push_back(score.second.score);
}
}

// 输出每个科目的成绩分析
cout << "学科成绩分析:\n";
cout << setw(10) << "科目" << setw(10) << "最低分" << setw(10) << "最高分" << setw(10) << "平均分" << setw(10) << "及格率" << endl;
for (const auto& subject : subjectScores) {
int minScore = INT_MAX;
int maxScore = INT_MIN;
double totalScore = 0;
int passCount = 0;

for (int score : subject.second) {
if (score < minScore) minScore = score;
if (score > maxScore) maxScore = score;
totalScore += score;
if (score >= 60) passCount++; // 60 分及格
}

double averageScore = totalScore / subject.second.size();
double passRate = 100.0 * passCount / subject.second.size();

cout << setw(10) << subject.first << setw(10) << minScore << setw(10) << maxScore << setw(10) << averageScore << setw(10) << passRate << endl;
}
}

// 计算单个科目的 GPA 和等级
void calculateSubjectGPAAndGrade() {
for (auto& pair : students) {
calculateGPAAndGrade(pair.second);
}
}
void calculateGPAAndGrade(Student& student) {
for (auto& pair : student.scores) {
int score = pair.second.score;
auto& info = pair.second;
if (score >= 95) {
info.gpa = 4.0; info.grade = "A+";
}
else if (score >= 90) {
info.gpa = 4.0; info.grade = "A";
}
else if (score >= 85) {
info.gpa = 3.7; info.grade = "A-";
}
else if (score >= 82) {
info.gpa = 3.3; info.grade = "B+";
}
else if (score >= 78) {
info.gpa = 3.0; info.grade = "B";
}
else if (score >= 75) {
info.gpa = 2.7; info.grade = "B-";
}
else if (score >= 72) {
info.gpa = 2.3; info.grade = "C+";
}
else if (score >= 68) {
info.gpa = 2.0; info.grade = "C";
}
else if (score >= 64) {
info.gpa = 1.5; info.grade = "D+";
}
else if (score >= 60) {
info.gpa = 1.0; info.grade = "D";
}
else {
info.gpa = 0.0; info.grade = "F";
}
}
}

// 计算每个学生的总绩点
void calculateTotalGPA() {
for (auto& pair : students) {
double totalGPA = 0;
double totalCredits = 0;
calculateGPAAndGrade(pair.second);

for (const auto& spair : pair.second.scores) {
double credits = subjects[spair.first]; // 获取科目对应的学分
totalGPA += spair.second.gpa * credits;
totalCredits += credits;
}

if (totalCredits != 0) { // 防止除以零
pair.second.gpa = totalGPA / totalCredits;
}
else {
pair.second.gpa = 0;
}
}
}

// 计算绩点排名
void calculateGPARank() {
vector< pair<string, double> > gpas;
for (const auto& pair : students) {
gpas.emplace_back(pair.first, pair.second.gpa);
}
sort(gpas.begin(), gpas.end(), [](const auto& a, const auto& b) {return a.second > b.second; });
int rank = 1;
for (auto& pair : gpas) {
students[pair.first].gparank = rank++;
}
}

// 计算综测排名
void calculateComprehensiveRank() {
vector< pair<string, double> > comprehensiveScores;
for (auto& pair : students) {
pair.second.calculateComprehensiveScore(); // 确保最新的综测分数被计算
comprehensiveScores.emplace_back(pair.first, pair.second.comprehensiveScore);
}
sort(comprehensiveScores.begin(), comprehensiveScores.end(), [](const auto& a, const auto& b) {return a.second > b.second; });
int rank = 1;
for (auto& pair : comprehensiveScores) {
students[pair.first].comprehensiveRank = rank++;
}
}

// 调用函数更新所有学生信息和排名
void updateStudentRecords() {
calculateTotalGPA();
calculateGPARank();
calculateComprehensiveRank();
}



void modifyOrDeleteScores() {
string id;
cout << "请输入学号:";
cin >> id;
if (students.find(id) == students.end()) {
cout << "学号不存在!\n";
return;
}

Student& student = students[id];

cout << "当前学生数据:\n";
queryScore(id);

cout << "选择操作:\n1. 修改学科成绩\n2. 修改课外活动分数\n输入 'delete' 删除学生记录:";
string choice;
cin >> choice;

if (choice == "delete") {
students.erase(id);
cout << "学生记录已删除。\n";
return;
}

if (choice == "1") {
cout << "请输入要修改的科目名称:";
string subject;
cin >> subject;

if (student.scores.find(subject) == student.scores.end()) {
cout << "科目不存在!\n";
return;
}

int newScore;
cout << "输入新成绩:";
cin >> newScore;

student.scores[subject].score = newScore;

cout << "成绩已更新。\n";

}
else if (choice == "2") {
double newActivitiesScore;
cout << "输入新的课外活动分数:";
cin >> newActivitiesScore;
student.extracurricularActivitiesScore = newActivitiesScore;
cout << "课外活动分数已更新。\n";
}
else {
cout << "无效输入。\n";
}

updateStudentRecords();
}

void loadScores() {
ifstream file(dataFile);
if (!file.is_open()) {
cerr << "无法打开文件 " << dataFile << " 进行读取。\n";
return;
}

string line;
getline(file, line); // 读取表头
istringstream header(line);
string token;
vector< pair<string, double> > Tmp;

// 跳过前三个标题
header >> token >> token >> token;
// 读取学科和学分信息
while (header >> token) {
if (token == "课外活动分数") break;
string tmp = token;// 保留学科
header >> token; // 读取学分
subjects[tmp] = stod(token);
Tmp.push_back(make_pair(tmp, stod(token)));
}

Student student;

while (getline(file, line)) {
if (line.empty()) {
// 当遇到空行时完成了一个学生的所有输入
if (!student.id.empty()) {
students[student.id] = student; // 保存当前学生的数据
student = Student(); // 重置学生对象
}
continue;
}

istringstream iss(line);
iss >> student.id >> student.name >> student.classId;
string subject;
SubjectInfo info;
int i = subjects.size();
while (i--) {
iss >> info.score >> info.gpa;
subject = Tmp[subjects.size() - i - 1].first;
student.scores[subject] = info;
}
iss >> student.extracurricularActivitiesScore;

}

// 确保文件结束时最后一个学生也被添加
if (!student.id.empty() && !student.name.empty() && !student.classId.empty()) {
students[student.id] = student;
}

file.close();
cout << "数据已读取。读取数据如下:\n";
updateStudentRecords();
outputScores(1); // 显示读入的数据
}

void saveScores() {
cout << "是否保存数据? 1.保存 2.不保存\n";
char choice;
cin >> choice;
if (choice == '1') {
ofstream file(dataFile);
if (!file.is_open()) {
cerr << "无法打开文件 '" << dataFile << "' 进行写入。\n";
return;
}

// 写入表头
file << left << setw(17) << "学号" << "\t\t\t" << setw(10) << "姓名" << "\t\t" << setw(10) << "班级" << "\t";
for (const auto& subject : subjects) {
file << "\t\t" << subject.first << "\t\t" << subject.second;
}
file << "\t\t" << "课外活动分数" << endl;

// 写入学生数据
for (const auto& pair : students) {
const Student& student = pair.second;
file << left << setw(17) << student.id << "\t\t" << setw(10) << student.name << "\t\t" << setw(10) << student.classId << "\t";
for (const auto& subject : subjects) {
auto it = student.scores.find(subject.first);
file << "\t\t" << it->second.score; // 写入学科成绩
file << "\t\t" << it->second.gpa; // 写入gpa
}
file << "\t\t" << student.extracurricularActivitiesScore << endl;
file << endl;
}

file.close();
cout << "--------------数据已保存。---------------\n";
}
else if (choice == '2') {
cout << "数据未保存,退出系统。\n";
}
else {
cout << "无效的输入。\n";
}
}


void clearAllData() {
students.clear();
subjects.clear();
ofstream file(dataFile, ios::trunc);
if (!file.is_open()) {
cerr << "无法打开文件以清空内容。\n";
return;
}
file.close();
cout << "所有数据已被清除。\n";
}

};

int main() {
if (!login()) {
cout << "口令错误,不允许进入本系统!\n";
return 0;
}
ScoreManager manager;
while (true) {
manager.displayMenu();
cout << "请选择您的操作(0-9):";
char choice;
cin >> choice;
switch (choice) {
case '1':
manager.setSubjects();
cout << '\n';
break;
case '2':
manager.inputScores();
cout << '\n';
break;
case '3':
cout << "选择输出格式(1:各科成绩,2:综测成绩):";
cin >> choice;
manager.outputScores(choice - '0');
cout << '\n';
break;
case '4':
manager.queryScore();
cout << '\n';
break;
case '5':
manager.sortAndOutput();
cout << '\n';
break;
case '6':
manager.statsScores();
cout << '\n';
break;
case '7':
manager.modifyOrDeleteScores();
cout << '\n';
break;
case '8':
manager.saveScores();
cout << '\n';
break;
case '9':
manager.loadScores();
cout << '\n';
break;
case '0':
cout << "已退出系统。\n";
return 0;
case 'd':
manager.clearAllData();
break;
default:
cout << "无效的选择,请重新输入。\n";
}
}
return 0;
}

最终版测试数据可以使用附件score.txt

dev c++下载地址 密码:foex