手撕学生管理系统超详解——【c++】

news2024/11/16 11:50:01

题目要求:设计一个学生成绩管理程序,实现按班级完成对学生成绩信息的录入和修改,并用文件保存。 实现按班级输出学生的成绩单;实现按学号和姓名进行查询,按平均成绩进行排序功能。


  • 问题描述

该程序的目标是提供一个简单且易于使用的学生成绩管理工具,以便教育机构能够有效地录入、修改、查询和排序学生的成绩信息。通过将学生信息保存到文件中,确保数据的持久性,即使在程序关闭后,学生成绩数据也能够被保留和恢复。

  • 基本要求

这个程序的基本要求是实现一个学生成绩管理系统,要求满足以下功能:

1. 录入学生成绩:能够接收用户输入学生的姓名、学号、班级和分数,并将这些信息保存在内存中的数据结构中,例如向量或链表。

2. 修改学生成绩:能够根据用户输入的学号查找到对应的学生,并允许用户修改学生的分数。

3. 保存学生成绩到文件:能够将当前内存中的学生数据保存到文件中,以便下次程序运行时可以加载和使用。

4. 按班级输出学生成绩单:能够根据用户输入的班级名称,打印该班级学生的姓名、学号、班级和分数。

5. 按学号和姓名查询学生成绩:能够根据用户选择的查询方式(学号或姓名),接收用户输入的学号或姓名,然后打印匹配的学生信息。

6. 按平均成绩进行排序:能够根据学生的平均成绩进行排序,并打印排序后的学生信息。

程序应该具备良好的用户交互性,即向用户提供清晰的菜单选项和提示信息,以便用户能够轻松地使用各项功能。

此外,程序还应考虑错误处理和异常情况的处理。例如,当用户输入无效的选项或学生信息不存在时,应给出相应的错误提示。

最后,为了确保学生数据的持久性,程序应能够将学生成绩保存到文件,并在每次启动时从文件中加载数据。这样,即使程序关闭后再次打开,学生数据也能够得到保留和恢复。

三.需求分析 

这个程序的需求分析主要包括以下几个方面:

1. 数据录入需求:

   - 用户需要能够输入学生的姓名、学号、班级和分数。

   - 程序应能够将输入的学生信息存储到内存中的数据结构中,以便后续操作使用。

   - 学生的班级信息应该包含在录入的数据中。

2. 数据修改需求:

   - 用户需要能够根据学号选择要修改的学生。

   - 程序应能够找到对应学号的学生,并提供修改分数的选项。

   - 修改后的数据应该能够在内存中更新,以便后续操作使用。

3. 数据保存需求:

   - 用户希望能够将当前内存中的学生数据保存到文件中,以便下次程序启动时可以加载。

   - 程序应提供保存功能,将学生信息写入到文件中。

4. 成绩单输出需求:

   - 用户需要能够按班级输出学生成绩单。

   - 程序应根据用户输入的班级名称,找到对应班级的学生,并输出学生的姓名、学号、班级和分数。

5. 学生信息查询需求:

   - 用户需要能够根据学号或姓名进行学生信息的查询。

   - 程序应根据用户选择的查询方式,输入相应的学号或姓名,然后输出匹配的学生信息。

6. 成绩排序需求:

   - 用户需要能够按平均成绩对学生进行排序。

   - 程序应根据学生的平均成绩对学生信息进行排序,并输出排序后的学生信息。

7. 错误处理需求:

   - 程序应能够处理用户输入错误的情况,例如无效的选项或找不到对应的学生信息。

   - 当发生错误时,程序应给出相应的错误提示信息,以帮助用户进行正确操作。

8. 持久化需求:

   - 程序应能够将学生成绩信息保存到文件中,并在程序启动时能够从文件中加载数据。

   - 通过持久化数据,学生成绩可以在程序关闭后得到保留和恢复。

以上是对程序的需求分析,帮助确定程序应满足的功能和用户需求。在实现程序时,应根据这些需求进行逐步开发和测试,确保程序能够达到预期的目标。

  • 概要设计

这个程序的概要设计包括以下几个组件:

1. `Student` 结构体:表示学生的基本信息,包括姓名、学号、班级和分数。

2. `addStudent` 函数:用于录入学生信息,接收用户输入的学生姓名、学号、班级和分数,并将学生信息添加到学生数据结构中。

3. `modifyScore` 函数:根据学号查找学生,并允许用户修改学生的分数。

4. `saveToFile` 函数:将当前内存中的学生数据保存到文件中。

5. `loadFromFile` 函数:从文件中加载学生数据到内存中。

6. `printClassScores` 函数:根据班级名称,打印该班级学生的成绩单。

7. `searchStudent` 函数:根据选择的查询方式(学号或姓名),接收用户输入的学号或姓名,并打印匹配的学生信息。

8. `sortByAverageScore` 函数:按学生的平均成绩进行排序,并打印排序后的学生信息。

9. 主程序:提供用户界面,接收用户的操作选择,并调用相应的函数来实现功能。

程序的主要流程如下:

1. 主程序启动,加载学生数据文件(如果存在)。

2. 显示主菜单,让用户选择操作。

3. 根据用户选择,调用相应的函数来执行对应的功能。

4. 执行完操作后,回到主菜单,等待用户的下一个选择。

5. 当用户选择退出时,保存学生数据到文件,然后程序结束。

概要设计中的函数和组件是为了实现对学生成绩的管理和操作而设计的。通过合理的函数划分和组织,可以使程序具有良好的结构和可扩展性。实际的实现细节和算法应根据具体的编程语言和需求进行进一步设计和开发。

五.详细设计

这是一个较为复杂的程序,下面是它的详细设计:

1. Student 结构体:

cpp

struct Student {

    std::string name;

    int id;

    std::string className;

    int score;

};

2. addStudent 函数:

cpp

void addStudent(std::vector<Student>& students) {

    std::string name;

    int id;

    std::string className;

    int score;

    std::cout << "请输入学生的姓名:";

    std::cin >> name;

    std::cout << "请输入学生的学号:";

    std::cin >> id;

    std::cout << "请输入学生的班级:";

    std::cin >> className;

    std::cout << "请输入学生的分数:";

    std::cin >> score;

    students.push_back({name, id, className, score});

    std::cout << "学生信息录入成功。" << std::endl;

}

3. modifyScore 函数:

cpp

void modifyScore(std::vector<Student>& students) {

    int id;

    int newScore;

    std::cout << "请输入要修改分数的学生学号:";

    std::cin >> id;

    bool found = false;

    for (auto& student : students) {

        if (student.id == id) {

            std::cout << "请输入新的分数:";

            std::cin >> newScore;

            student.score = newScore;

            found = true;

            std::cout << "学生分数修改成功。" << std::endl;

            break;

        }

    }

    if (!found) {

        std::cout << "未找到对应学号的学生。" << std::endl;

    }

}

4. saveToFile 函数:

cpp

void saveToFile(const std::vector<Student>& students) {

    std::ofstream file("students.txt");

    if (file.is_open()) {

        for (const auto& student : students) {

            file << student.name << " " << student.id << " " << student.className << " " << student.score << std::endl;

        }

        file.close();

        std::cout << "学生信息保存成功。" << std::endl;

    } else {

        std::cout << "无法打开文件进行保存。" << std::endl;

    }

}

5. loadFromFile 函数:

cpp

void loadFromFile(std::vector<Student>& students) {

    std::ifstream file("students.txt");

    if (file.is_open()) {

        std::string line;

        while (std::getline(file, line)) {

            std::istringstream iss(line);

            std::string name;

            int id;

            std::string className;

            int score;

            if (iss >> name >> id >> className >> score) {

                students.push_back({name, id, className, score});

            }

        }

        file.close();

        std::cout << "学生信息加载成功。" << std::endl;

    } else {

        std::cout << "无法打开文件进行加载。" << std::endl;

    }

}

6. printClassScores 函数:

cpp

void printClassScores(const std::vector<Student>& students) {

    std::string className;

    std::cout << "请输入班级名称:";

    std::cin >> className;

    std::cout << "班级 " << className << " 的学生成

绩单:" << std::endl;

    bool found = false;

    for (const auto& student : students) {

        if (student.className == className) {

            std::cout << "姓名:" << student.name << "\t学号:" << student.id << "\t班级:" << student.className << "\t分数:" << student.score << std::endl;

            found = true;

        }

    }

    if (!found) {

        std::cout << "未找到对应班级的学生。" << std::endl;

    }

}

7. searchStudent 函数:

cpp

void searchStudent(const std::vector<Student>& students) {

    int choice;

    std::cout << "请选择查询方式:\n1. 学号\n2. 姓名\n";

    std::cin >> choice;

    if (choice == 1) {

        int id;

        std::cout << "请输入学号:";

        std::cin >> id;

        bool found = false;

        for (const auto& student : students) {

            if (student.id == id) {

                std::cout << "学号:" << student.id << "\t姓名:" << student.name << "\t班级:" << student.className << "\t分数:" << student.score << std::endl;

                found = true;

                break;

            }

        }

        if (!found) {

            std::cout << "未找到对应学号的学生。" << std::endl;

        }

    } else if (choice == 2) {

        std::string name;

        std::cout << "请输入姓名:";

        std::cin >> name;

        bool found = false;

        for (const auto& student : students) {

            if (student.name == name) {

                std::cout << "学号:" << student.id << "\t姓名:" << student.name << "\t班级:" << student.className << "\t分数:" << student.score << std::endl;

                found = true;

            }

        }

        if (!found) {

            std::cout << "未找到对应姓名的学生。" << std::endl;

        }

    } else {

        std::cout << "无效的选择。" << std::endl;

    }

}

8. sortByAverageScore 函数:

cpp

bool compareByAverageScore(const Student& student1, const Student& student2) {

    return (student1.score + student2.score) / 2.0 > (student2.score + student2.score) / 2.0;

}

void sortByAverageScore(std::vector<Student>& students) {

    std::sort(students.begin(), students.end(), compareByAverageScore);

    std::cout << "按平均成绩排序成功。" << std::endl;

}

9. 主程序:

cpp

int main() {

    std::vector<Student> students;

    loadFromFile(students);

    int choice;

    do {

        std::cout << "\n1. 录入学生成绩\n2. 修改学生成绩\n3. 保存学生成绩到文件\n4. 按班级输出学生成绩单\n5. 按学号和姓名查询学生成绩\n6. 按平均成绩排序\n0. 退出\n";

        std::cin >> choice;

        switch (choice) {

            case 1:

                addStudent(students);

                break;

            case 2:

                modifyScore(students

);

                break;

            case 3:

                saveToFile(students);

                break;

            case 4:

                printClassScores(students);

                break;

            case 5:

                searchStudent(students);

                break;

            case 6:

                sortByAverageScore(students);

                break;

            case 0:

                saveToFile(students);

                std::cout << "学生成绩已保存到文件,程序即将退出。" << std::endl;

                break;

            default:

                std::cout << "无效的选择。" << std::endl;

                break;

        }

    } while (choice != 0);

    return 0;

}

这个详细设计提供了每个函数的实现细节,包括参数、返回类型和主要操作步骤。通过这些设计,程序可以实现按要求对学生成绩进行管理和操作。

  • 调试分析

在调试过程中,可能会遇到一些问题,下面是一些遇到的问题及其解决方案,以及对设计与实现的回顾、讨论和分析:

1. 问题:在录入学生信息时,输入的分数超出了有效范围。

   解决方案:在 `addStudent` 函数中添加适当的验证逻辑,确保输入的分数在有效范围内。

2. 问题:加载学生数据文件时,文件不存在或格式错误。

   解决方案:在 `loadFromFile` 函数中添加适当的错误处理,例如检查文件是否存在,以及读取每行数据时的格式验证。

3. 问题:修改学生分数时,无法找到对应学号的学生。

   解决方案:在 `modifyScore` 函数中添加对学生是否存在的判断,并给出相应的错误提示。

4. 问题:按班级输出学生成绩单时,班级不存在或无学生数据。

   解决方案:在 `printClassScores` 函数中添加对班级存在性和学生数据是否为空的判断,并给出相应的错误提示。

5. 问题:按学号或姓名查询学生成绩时,找不到匹配的学生。

   解决方案:在 `searchStudent` 函数中添加对学生是否存在的判断,并给出相应的错误提示。

6. 问题:排序学生成绩时,排序逻辑有误。

   解决方案:在 `sortByAverageScore` 函数中检查排序逻辑,确保按平均成绩进行正确的排序。

  • 用户使用说明

以下是使用学生成绩管理程序的详细操作步骤:

1. 打开终端或命令提示符,进入程序所在的目录。

2. 编译程序源代码。

3. 运行程序。

4. 程序开始运行后,会显示一个菜单供你选择操作。

5. 选择菜单中的选项进行相应的操作:

    选项 1:录入学生成绩

      输入学生的姓名、学号、班级和分数,按照程序提示进行输入。

      录入完成后,程序会显示学生信息录入成功。

    选项 2:修改学生成绩

      输入要修改分数的学生学号。

      输入新的分数。

      修改完成后,程序会显示学生分数修改成功。

    选项 3:保存学生成绩到文件

      学生信息会保存到名为 `students.txt` 的文件中。

      程序会显示学生信息保存成功。

    选项 4:按班级输出学生成绩单

      输入要输出成绩单的班级名称。

      程序会按照班级名称查找学生,并输出对应班级的学生成绩单。

    选项 5:按学号和姓名查询学生成绩

      选择查询方式:按学号或按姓名。

      输入对应的学号或姓名进行查询。

      程序会查找并显示匹配的学生信息。

    选项 6:按平均成绩排序

      学生信息会按照平均成绩进行排序。

      程序会显示按平均成绩排序成功。

    选项 0:退出程序

      学生成绩会自动保存到文件 `students.txt` 中。

      程序会显示学生成绩已保存到文件,然后退出。

6. 根据需要选择合适的选项,并按照程序的提示进行操作。

7. 执行完所选择的操作后,可以选择继续进行其他操作或退出程序。

请注意,在程序运行之前,确保已经创建了 `students.txt` 文件,并按照正确的格式保存了学生信息。如需导入已有的学生数据,可以在 `students.txt` 文件中按行输入学生信息,每个字段之间使用空格分隔。

通过按照以上步骤操作,你可以使用我的学生成绩管理程序进行学生信息的录入、修改、查询、排序等操作,并将学生信息保存到文件中。

  • 测试结果

测试数据:

测试结果:

  • 程序设计总结

这次的程序设计旨在实现学生成绩管理系统,通过对程序的需求分析、概要设计和详细设计,我们完成了一个基于 C++ 的学生成绩管理程序。

在需求分析阶段,我们明确了程序的基本要求,包括学生成绩的录入、修改、保存、输出、查询和排序功能。这些要求帮助我们明确了程序的功能边界和用户需求。

在概要设计阶段,我们设计了程序的主要模块和函数,并定义了学生类以及对学生成绩信息进行管理的函数。这些设计帮助我们梳理了程序的结构和逻辑。

在详细设计阶段,我们进一步详细描述了各个函数的实现细节,包括函数的参数、返回类型和操作步骤。这些设计帮助我们更加清晰地理解了程序的执行流程和数据处理。

在实现过程中,我们遵循了设计的指导,逐步实现了各个功能模块,并进行了测试和调试。通过测试数据的使用,我们验证了程序的功能完整性和正确性。

通过这次的程序设计,我们学习到了以下几点经验总结:

1. 需求分析是设计过程中的关键一步,明确需求可以帮助我们确保程序的功能满足用户需求,并避免不必要的功能冗余。

2. 概要设计和详细设计是程序设计的重要阶段,它们帮助我们建立程序的整体结构和详细逻辑,并为编码提供了指导。

3. 模块化设计可以提高程序的可读性和可维护性,将程序划分为不同的模块或函数,有助于降低复杂度和提高代码复用性。

4. 在实现过程中,逐步测试和调试是非常重要的,它可以帮助我们发现并解决潜在的问题,并确保程序的正确性。

5. 在设计和编写代码时,注重代码的可读性和可维护性是很重要的,例如给变量和函数取合适的命名、添加注释、遵循编码规范等。

总的来说,这次的程序设计使我们能够全面理解和应用软件工程的基本原理和方法,包括需求分析、设计、实现、测试和调试。同时,也提醒我们在设计和编码过程中要注重细节和质量,以开发出高效、可靠且易于维护的软件。

  • 参考文献

1. C++ Primer (5th Edition) by Stanley B. Lippman, Josée Lajoie, and Barbara E. Moo

2. 数据结构与算法分析(C++语言描述)by Mark Allen Weiss

3. 数据库系统概论 by Abraham Silberschatz, Henry F. Korth, and S. Sudarshan

4. 代码大全(第2版)by Steve McConnell

5. C++ reference (cppreference.com)

6. Stack Overflow (stackoverflow.com)

  • 问题描述

该程序的目标是提供一个简单且易于使用的学生成绩管理工具,以便教育机构能够有效地录入、修改、查询和排序学生的成绩信息。通过将学生信息保存到文件中,确保数据的持久性,即使在程序关闭后,学生成绩数据也能够被保留和恢复。

  • 基本要求

这个程序的基本要求是实现一个学生成绩管理系统,要求满足以下功能:

1. 录入学生成绩:能够接收用户输入学生的姓名、学号、班级和分数,并将这些信息保存在内存中的数据结构中,例如向量或链表。

2. 修改学生成绩:能够根据用户输入的学号查找到对应的学生,并允许用户修改学生的分数。

3. 保存学生成绩到文件:能够将当前内存中的学生数据保存到文件中,以便下次程序运行时可以加载和使用。

4. 按班级输出学生成绩单:能够根据用户输入的班级名称,打印该班级学生的姓名、学号、班级和分数。

5. 按学号和姓名查询学生成绩:能够根据用户选择的查询方式(学号或姓名),接收用户输入的学号或姓名,然后打印匹配的学生信息。

6. 按平均成绩进行排序:能够根据学生的平均成绩进行排序,并打印排序后的学生信息。

程序应该具备良好的用户交互性,即向用户提供清晰的菜单选项和提示信息,以便用户能够轻松地使用各项功能。

此外,程序还应考虑错误处理和异常情况的处理。例如,当用户输入无效的选项或学生信息不存在时,应给出相应的错误提示。

最后,为了确保学生数据的持久性,程序应能够将学生成绩保存到文件,并在每次启动时从文件中加载数据。这样,即使程序关闭后再次打开,学生数据也能够得到保留和恢复。

三.需求分析 

这个程序的需求分析主要包括以下几个方面:

1. 数据录入需求:

   - 用户需要能够输入学生的姓名、学号、班级和分数。

   - 程序应能够将输入的学生信息存储到内存中的数据结构中,以便后续操作使用。

   - 学生的班级信息应该包含在录入的数据中。

2. 数据修改需求:

   - 用户需要能够根据学号选择要修改的学生。

   - 程序应能够找到对应学号的学生,并提供修改分数的选项。

   - 修改后的数据应该能够在内存中更新,以便后续操作使用。

3. 数据保存需求:

   - 用户希望能够将当前内存中的学生数据保存到文件中,以便下次程序启动时可以加载。

   - 程序应提供保存功能,将学生信息写入到文件中。

4. 成绩单输出需求:

   - 用户需要能够按班级输出学生成绩单。

   - 程序应根据用户输入的班级名称,找到对应班级的学生,并输出学生的姓名、学号、班级和分数。

5. 学生信息查询需求:

   - 用户需要能够根据学号或姓名进行学生信息的查询。

   - 程序应根据用户选择的查询方式,输入相应的学号或姓名,然后输出匹配的学生信息。

6. 成绩排序需求:

   - 用户需要能够按平均成绩对学生进行排序。

   - 程序应根据学生的平均成绩对学生信息进行排序,并输出排序后的学生信息。

7. 错误处理需求:

   - 程序应能够处理用户输入错误的情况,例如无效的选项或找不到对应的学生信息。

   - 当发生错误时,程序应给出相应的错误提示信息,以帮助用户进行正确操作。

8. 持久化需求:

   - 程序应能够将学生成绩信息保存到文件中,并在程序启动时能够从文件中加载数据。

   - 通过持久化数据,学生成绩可以在程序关闭后得到保留和恢复。

以上是对程序的需求分析,帮助确定程序应满足的功能和用户需求。在实现程序时,应根据这些需求进行逐步开发和测试,确保程序能够达到预期的目标。

  • 概要设计

这个程序的概要设计包括以下几个组件:

1. `Student` 结构体:表示学生的基本信息,包括姓名、学号、班级和分数。

2. `addStudent` 函数:用于录入学生信息,接收用户输入的学生姓名、学号、班级和分数,并将学生信息添加到学生数据结构中。

3. `modifyScore` 函数:根据学号查找学生,并允许用户修改学生的分数。

4. `saveToFile` 函数:将当前内存中的学生数据保存到文件中。

5. `loadFromFile` 函数:从文件中加载学生数据到内存中。

6. `printClassScores` 函数:根据班级名称,打印该班级学生的成绩单。

7. `searchStudent` 函数:根据选择的查询方式(学号或姓名),接收用户输入的学号或姓名,并打印匹配的学生信息。

8. `sortByAverageScore` 函数:按学生的平均成绩进行排序,并打印排序后的学生信息。

9. 主程序:提供用户界面,接收用户的操作选择,并调用相应的函数来实现功能。

程序的主要流程如下:

1. 主程序启动,加载学生数据文件(如果存在)。

2. 显示主菜单,让用户选择操作。

3. 根据用户选择,调用相应的函数来执行对应的功能。

4. 执行完操作后,回到主菜单,等待用户的下一个选择。

5. 当用户选择退出时,保存学生数据到文件,然后程序结束。

概要设计中的函数和组件是为了实现对学生成绩的管理和操作而设计的。通过合理的函数划分和组织,可以使程序具有良好的结构和可扩展性。实际的实现细节和算法应根据具体的编程语言和需求进行进一步设计和开发。

五.详细设计

这是一个较为复杂的程序,下面是它的详细设计:

1. Student 结构体:

cpp

struct Student {

    std::string name;

    int id;

    std::string className;

    int score;

};

2. addStudent 函数:

cpp

void addStudent(std::vector<Student>& students) {

    std::string name;

    int id;

    std::string className;

    int score;

    std::cout << "请输入学生的姓名:";

    std::cin >> name;

    std::cout << "请输入学生的学号:";

    std::cin >> id;

    std::cout << "请输入学生的班级:";

    std::cin >> className;

    std::cout << "请输入学生的分数:";

    std::cin >> score;

    students.push_back({name, id, className, score});

    std::cout << "学生信息录入成功。" << std::endl;

}

3. modifyScore 函数:

cpp

void modifyScore(std::vector<Student>& students) {

    int id;

    int newScore;

    std::cout << "请输入要修改分数的学生学号:";

    std::cin >> id;

    bool found = false;

    for (auto& student : students) {

        if (student.id == id) {

            std::cout << "请输入新的分数:";

            std::cin >> newScore;

            student.score = newScore;

            found = true;

            std::cout << "学生分数修改成功。" << std::endl;

            break;

        }

    }

    if (!found) {

        std::cout << "未找到对应学号的学生。" << std::endl;

    }

}

4. saveToFile 函数:

cpp

void saveToFile(const std::vector<Student>& students) {

    std::ofstream file("students.txt");

    if (file.is_open()) {

        for (const auto& student : students) {

            file << student.name << " " << student.id << " " << student.className << " " << student.score << std::endl;

        }

        file.close();

        std::cout << "学生信息保存成功。" << std::endl;

    } else {

        std::cout << "无法打开文件进行保存。" << std::endl;

    }

}

5. loadFromFile 函数:

cpp

void loadFromFile(std::vector<Student>& students) {

    std::ifstream file("students.txt");

    if (file.is_open()) {

        std::string line;

        while (std::getline(file, line)) {

            std::istringstream iss(line);

            std::string name;

            int id;

            std::string className;

            int score;

            if (iss >> name >> id >> className >> score) {

                students.push_back({name, id, className, score});

            }

        }

        file.close();

        std::cout << "学生信息加载成功。" << std::endl;

    } else {

        std::cout << "无法打开文件进行加载。" << std::endl;

    }

}

6. printClassScores 函数:

cpp

void printClassScores(const std::vector<Student>& students) {

    std::string className;

    std::cout << "请输入班级名称:";

    std::cin >> className;

    std::cout << "班级 " << className << " 的学生成

绩单:" << std::endl;

    bool found = false;

    for (const auto& student : students) {

        if (student.className == className) {

            std::cout << "姓名:" << student.name << "\t学号:" << student.id << "\t班级:" << student.className << "\t分数:" << student.score << std::endl;

            found = true;

        }

    }

    if (!found) {

        std::cout << "未找到对应班级的学生。" << std::endl;

    }

}

7. searchStudent 函数:

cpp

void searchStudent(const std::vector<Student>& students) {

    int choice;

    std::cout << "请选择查询方式:\n1. 学号\n2. 姓名\n";

    std::cin >> choice;

    if (choice == 1) {

        int id;

        std::cout << "请输入学号:";

        std::cin >> id;

        bool found = false;

        for (const auto& student : students) {

            if (student.id == id) {

                std::cout << "学号:" << student.id << "\t姓名:" << student.name << "\t班级:" << student.className << "\t分数:" << student.score << std::endl;

                found = true;

                break;

            }

        }

        if (!found) {

            std::cout << "未找到对应学号的学生。" << std::endl;

        }

    } else if (choice == 2) {

        std::string name;

        std::cout << "请输入姓名:";

        std::cin >> name;

        bool found = false;

        for (const auto& student : students) {

            if (student.name == name) {

                std::cout << "学号:" << student.id << "\t姓名:" << student.name << "\t班级:" << student.className << "\t分数:" << student.score << std::endl;

                found = true;

            }

        }

        if (!found) {

            std::cout << "未找到对应姓名的学生。" << std::endl;

        }

    } else {

        std::cout << "无效的选择。" << std::endl;

    }

}

8. sortByAverageScore 函数:

cpp

bool compareByAverageScore(const Student& student1, const Student& student2) {

    return (student1.score + student2.score) / 2.0 > (student2.score + student2.score) / 2.0;

}

void sortByAverageScore(std::vector<Student>& students) {

    std::sort(students.begin(), students.end(), compareByAverageScore);

    std::cout << "按平均成绩排序成功。" << std::endl;

}

9. 主程序:

cpp

int main() {

    std::vector<Student> students;

    loadFromFile(students);

    int choice;

    do {

        std::cout << "\n1. 录入学生成绩\n2. 修改学生成绩\n3. 保存学生成绩到文件\n4. 按班级输出学生成绩单\n5. 按学号和姓名查询学生成绩\n6. 按平均成绩排序\n0. 退出\n";

        std::cin >> choice;

        switch (choice) {

            case 1:

                addStudent(students);

                break;

            case 2:

                modifyScore(students

);

                break;

            case 3:

                saveToFile(students);

                break;

            case 4:

                printClassScores(students);

                break;

            case 5:

                searchStudent(students);

                break;

            case 6:

                sortByAverageScore(students);

                break;

            case 0:

                saveToFile(students);

                std::cout << "学生成绩已保存到文件,程序即将退出。" << std::endl;

                break;

            default:

                std::cout << "无效的选择。" << std::endl;

                break;

        }

    } while (choice != 0);

    return 0;

}

这个详细设计提供了每个函数的实现细节,包括参数、返回类型和主要操作步骤。通过这些设计,程序可以实现按要求对学生成绩进行管理和操作。

  • 调试分析

在调试过程中,可能会遇到一些问题,下面是一些遇到的问题及其解决方案,以及对设计与实现的回顾、讨论和分析:

1. 问题:在录入学生信息时,输入的分数超出了有效范围。

   解决方案:在 `addStudent` 函数中添加适当的验证逻辑,确保输入的分数在有效范围内。

2. 问题:加载学生数据文件时,文件不存在或格式错误。

   解决方案:在 `loadFromFile` 函数中添加适当的错误处理,例如检查文件是否存在,以及读取每行数据时的格式验证。

3. 问题:修改学生分数时,无法找到对应学号的学生。

   解决方案:在 `modifyScore` 函数中添加对学生是否存在的判断,并给出相应的错误提示。

4. 问题:按班级输出学生成绩单时,班级不存在或无学生数据。

   解决方案:在 `printClassScores` 函数中添加对班级存在性和学生数据是否为空的判断,并给出相应的错误提示。

5. 问题:按学号或姓名查询学生成绩时,找不到匹配的学生。

   解决方案:在 `searchStudent` 函数中添加对学生是否存在的判断,并给出相应的错误提示。

6. 问题:排序学生成绩时,排序逻辑有误。

   解决方案:在 `sortByAverageScore` 函数中检查排序逻辑,确保按平均成绩进行正确的排序。

  • 用户使用说明

以下是使用学生成绩管理程序的详细操作步骤:

1. 打开终端或命令提示符,进入程序所在的目录。

2. 编译程序源代码。

3. 运行程序。

4. 程序开始运行后,会显示一个菜单供你选择操作。

5. 选择菜单中的选项进行相应的操作:

    选项 1:录入学生成绩

      输入学生的姓名、学号、班级和分数,按照程序提示进行输入。

      录入完成后,程序会显示学生信息录入成功。

    选项 2:修改学生成绩

      输入要修改分数的学生学号。

      输入新的分数。

      修改完成后,程序会显示学生分数修改成功。

    选项 3:保存学生成绩到文件

      学生信息会保存到名为 `students.txt` 的文件中。

      程序会显示学生信息保存成功。

    选项 4:按班级输出学生成绩单

      输入要输出成绩单的班级名称。

      程序会按照班级名称查找学生,并输出对应班级的学生成绩单。

    选项 5:按学号和姓名查询学生成绩

      选择查询方式:按学号或按姓名。

      输入对应的学号或姓名进行查询。

      程序会查找并显示匹配的学生信息。

    选项 6:按平均成绩排序

      学生信息会按照平均成绩进行排序。

      程序会显示按平均成绩排序成功。

    选项 0:退出程序

      学生成绩会自动保存到文件 `students.txt` 中。

      程序会显示学生成绩已保存到文件,然后退出。

6. 根据需要选择合适的选项,并按照程序的提示进行操作。

7. 执行完所选择的操作后,可以选择继续进行其他操作或退出程序。

请注意,在程序运行之前,确保已经创建了 `students.txt` 文件,并按照正确的格式保存了学生信息。如需导入已有的学生数据,可以在 `students.txt` 文件中按行输入学生信息,每个字段之间使用空格分隔。

通过按照以上步骤操作,你可以使用我的学生成绩管理程序进行学生信息的录入、修改、查询、排序等操作,并将学生信息保存到文件中。

  • 测试结果

测试数据:

测试结果:

下面我们展示这个项目的所有代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>

struct Student {
    std::string name;
    int id;
    std::string className;
    int score;
};

// 函数声明
void addStudent(std::vector<Student>& students);
void updateStudent(std::vector<Student>& students);
void saveToFile(const std::vector<Student>& students);
void loadFromFile(std::vector<Student>& students);
void printClassScores(const std::vector<Student>& students);
void searchStudent(const std::vector<Student>& students);
void sortByAverageScore(std::vector<Student>& students);

int main() {
    std::vector<Student> students;
    loadFromFile(students);

    int choice;
    do {
        std::cout << "学生成绩管理程序" << std::endl;
        std::cout << "1. 录入学生成绩" << std::endl;
        std::cout << "2. 修改学生成绩" << std::endl;
        std::cout << "3. 保存学生成绩到文件" << std::endl;
        std::cout << "4. 按班级输出学生成绩单" << std::endl;
        std::cout << "5. 按学号和姓名查询学生成绩" << std::endl;
        std::cout << "6. 按平均成绩排序" << std::endl;
        std::cout << "0. 退出程序" << std::endl;
        std::cout << "请选择操作: ";
        std::cin >> choice;

        switch (choice) {
        case 1:
            addStudent(students);
            break;
        case 2:
            updateStudent(students);
            break;
        case 3:
            saveToFile(students);
            break;
        case 4:
            printClassScores(students);
            break;
        case 5:
            searchStudent(students);
            break;
        case 6:
            sortByAverageScore(students);
            break;
        case 0:
            saveToFile(students);
            std::cout << "程序已退出。" << std::endl;
            break;
        default:
            std::cout << "无效的选择,请重新选择操作。" << std::endl;
            break;
        }

        std::cout << std::endl;
    } while (choice != 0);

    return 0;
}

void addStudent(std::vector<Student>& students) {
    Student student;
    std::cout << "请输入学生姓名: ";
    std::cin >> student.name;
    std::cout << "请输入学生学号: ";
    std::cin >> student.id;
    std::cout << "请输入学生班级: ";
    std::cin >> student.className;
    std::cout << "请输入学生分数: ";
    std::cin >> student.score;

    students.push_back(student);
}

void updateStudent(std::vector<Student>& students) {
    int id;
    std::cout << "请输入要修改的学生学号: ";
    std::cin >> id;

    bool found = false;
    for (auto& student : students) {
        if (student.id == id) {
            std::cout << "请输入修改后的学生分数: ";
            std::cin >> student.score;
            found = true;
            break;
        }
    }

    if (!found) {
        std::cout << "未找到学号为 " << id << " 的学生。" << std::endl;
    }
}

void saveToFile(const std::vector<Student>& students) {
    std::ofstream file("students.txt");
    if (file.is_open()) {
        for (const auto& student : students) {
            file << student.name << " " << student.id << " " << student.className << " " << student.score << std::endl;
        }
        file.close();
        std::cout << "学生成绩已保存到文件。" << std::endl;
    }
    else {
        std::cout << "无法打开文件进行保存。" << std::endl;
    }
}

void loadFromFile(std::vector<Student>& students) {
    std::ifstream file("students.txt");
    if (file.is_open()) {
        std::string name, className;
        int id, score;
        while (file >> name >> id >> className >> score) {
            Student student;
            student.name = name;
            student.id = id;
            student.className = className;
            student.score = score;
            students.push_back(student);
        }
        file.close();
        std::cout << "从文件加载了 " << students.size() << " 条学生成绩信息。" << std::endl;
    }
    else {
        std::cout << "无法打开文件进行加载。" << std::endl;
    }
}

void printClassScores(const std::vector<Student>& students) {
    std::cout << "请输入班级名称: ";
    std::string className;
    std::cin >> className;

    std::cout << "班级成绩单:" << std::endl;
    for (const auto& student : students) {
        if (student.className == className) {
            std::cout << "姓名: " << student.name << ", 学号: " << student.id << ", 班级: " << student.className << ", 分数: " << student.score << std::endl;
        }
    }
}

void searchStudent(const std::vector<Student>& students) {
    std::cout << "请选择查询方式:" << std::endl;
    std::cout << "1. 按学号查询" << std::endl;
    std::cout << "2. 按姓名查询" << std::endl;
    std::cout << "请选择操作: ";
    int choice;
    std::cin >> choice;

    if (choice == 1) {
        int id;
        std::cout << "请输入学生学号: ";
        std::cin >> id;

        bool found = false;
        for (const auto& student : students) {
            if (student.id == id) {
                std::cout << "姓名: " << student.name << ", 学号: " << student.id << ", 班级: " << student.className << ", 分数: " << student.score << std::endl;
                found = true;
                break;
            }
        }

        if (!found) {
            std::cout << "未找到学号为 " << id << " 的学生。" << std::endl;
        }
    }
    else if (choice == 2) {
        std::string name;
        std::cout << "请输入学生姓名: ";
        std::cin >> name;

        bool found = false;
        for (const auto& student : students) {
            if (student.name == name) {
                std::cout << "姓名: " << student.name << ", 学号: " << student.id << ", 班级: " << student.className << ", 分数: " << student.score << std::endl;
                found = true;
            }
        }

        if (!found) {
            std::cout << "未找到姓名为 " << name << " 的学生。" << std::endl;
        }
    }
    else {
        std::cout << "无效的选择,请重新选择操作。" << std::endl;
    }
}

void sortByAverageScore(std::vector<Student>& students) {
    std::sort(students.begin(), students.end(), [](const Student& a, const Student& b) {
        return a.score < b.score;
        });

    std::cout << "按平均成绩排序:" << std::endl;
    for (const auto& student : students) {
        std::cout << "姓名: " << student.name << ", 学号: " << student.id << ", 班级: " << student.className << ", 分数: " << student.score << std::endl;
    }
}

  • 程序设计总结

这次的程序设计旨在实现学生成绩管理系统,通过对程序的需求分析、概要设计和详细设计,我们完成了一个基于 C++ 的学生成绩管理程序。

在需求分析阶段,我们明确了程序的基本要求,包括学生成绩的录入、修改、保存、输出、查询和排序功能。这些要求帮助我们明确了程序的功能边界和用户需求。

在概要设计阶段,我们设计了程序的主要模块和函数,并定义了学生类以及对学生成绩信息进行管理的函数。这些设计帮助我们梳理了程序的结构和逻辑。

在详细设计阶段,我们进一步详细描述了各个函数的实现细节,包括函数的参数、返回类型和操作步骤。这些设计帮助我们更加清晰地理解了程序的执行流程和数据处理。

在实现过程中,我们遵循了设计的指导,逐步实现了各个功能模块,并进行了测试和调试。通过测试数据的使用,我们验证了程序的功能完整性和正确性。

通过这次的程序设计,我们学习到了以下几点经验总结:

1. 需求分析是设计过程中的关键一步,明确需求可以帮助我们确保程序的功能满足用户需求,并避免不必要的功能冗余。

2. 概要设计和详细设计是程序设计的重要阶段,它们帮助我们建立程序的整体结构和详细逻辑,并为编码提供了指导。

3. 模块化设计可以提高程序的可读性和可维护性,将程序划分为不同的模块或函数,有助于降低复杂度和提高代码复用性。

4. 在实现过程中,逐步测试和调试是非常重要的,它可以帮助我们发现并解决潜在的问题,并确保程序的正确性。

5. 在设计和编写代码时,注重代码的可读性和可维护性是很重要的,例如给变量和函数取合适的命名、添加注释、遵循编码规范等。

总的来说,这次的程序设计使我们能够全面理解和应用软件工程的基本原理和方法,包括需求分析、设计、实现、测试和调试。同时,也提醒我们在设计和编码过程中要注重细节和质量,以开发出高效、可靠且易于维护的软件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/656943.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

scratch lenet(2): C语言实现图像直方图的计算

scratch lenet(2): C语言实现图像直方图的计算 1. 目的 用 C 语言实现 uint8 类型图像&#xff08;单通道&#xff09;的直方图计算。不涉及直方图均衡化。 2. 什么是图像直方图 2.1 统计得到图像直方图 通常是对于单通道的灰度图而言的。像素范围是 [0, 255], 统计每个像…

提高错误日志处理效率!使用Python和钉钉机器人实现自动告警聚合

1、背景 日志是非常重要的信息资源。它们记录了应用程序的运行状态、错误和异常情况&#xff0c;帮助我们了解系统的健康状况以及发现潜在的问题。为了高效地管理和分析日志数据&#xff0c;许多组织采用了Elasticsearch、Logstash和Kibana&#xff08;ELK&#xff09;堆栈作为…

Eclipse Krazo(Jakarta MVC)的使用

文章目录 背景Jakarta MVC规范Eclipse Krazo使用前的思考全局配置Controller示例返回View的三种写法View中用到的Model如何设值&#xff1f;View中如何获取Model中的值&#xff1f; 参数校验防止CSRFKrazo是如何实现的呢&#xff1f;如何生成csrf的token&#xff1f;如何校验cs…

开源赋能,决胜未来 — 参加原子全球开源峰会有感

目录 文章目录 目录前言开源决胜未来&#xff1a;闭源摧毁 UNIX&#xff0c;开源成就 Linux开源创新&#xff1a;软硬件协同&#xff0c;共建开源生态 前言 开源原子基金会作为国内首家开源基金会组织&#xff0c;由其主办的首届 “开放原子全球开源峰会” 也是第一次被冠以 “…

干货文:Mac 中 .bash_profile 和 .zshrc 的区别

如果你想在 Mac OS 中配置 MySQL 的环境变量&#xff0c;在 .zshrc 文件中添加如下内容&#xff1a; # 设置 mysql 的路径 export MYSQL_HOME/usr/local/mysql/bin# 将 MYSQL_HOME 添加到 PATH 中 export PATH$HOME/bin:/usr/local/bin:$MYSQL_HOME:$PATH# 解决需要 source 才…

硬件【9】详解二极管钳位电路

文章目录 1 概述1.1 正向钳位电路1.2 偏置正向钳位电路 1 概述 在之前的 二极管限幅电路 一文中&#xff0c;我们学习了二极管限幅电路&#xff0c;该电路可以削掉一部分信号&#xff0c;但不会影响剩余信号。今天&#xff0c;我们将学习另一种基于二极管的电路&#xff0c;该…

搭建环境【2】windows主机和ubuntu互传文件的4种方法

我的ubuntu系统是安装在 VMware 虚拟机中的&#xff0c;两者之间经常要互传文件&#xff0c;下面介绍4种常用的互传文件方法。 1. 共享文件夹方式互传 在虚拟机中需要开启共享文件夹的功能。首先虚拟机中的ubuntu要求是已经开机了的状态&#xff0c;然后进行设置&#xff1a;…

Vue2封装一个全局通知组件并发布到NPM

✍&#x1f3fc;作者&#xff1a;周棋洛&#xff0c;计算机学生 ♉星座&#xff1a;金牛座 &#x1f3e0;主页&#xff1a;点击查看更多 &#x1f310;关键&#xff1a;vue2 组件封装 npm发包 文章目录 1. 前言 &#x1f343;2. 我为什么要封装通知插件 ❓3. 初始化vue空项目 &…

B047-cms02-高级查询 删除 添加 修改

目录 高级查询页面准备下拉框显示文章类型ArticleController用jstl和el表达式取值展示 高级查询参数ArticleQuery 高级查询页面发送请求导入jquery.jdirk.js在jquery下引用绑定按钮发送请求高级查询sql 绑定删除事件绑定事件拿到标签id值准备模态框来自xmind弹出删除模态框绑定…

matlab不显示子图刻度并调整子图间距

matlab中在使用subplot函数画图时&#xff0c;尤其是做emd分解查看IMF时&#xff0c; 正常画图的代码及结果如下&#xff1a; figure for i 1:size(imf_norm,1)subplot(7,1,i)plot(imf_norm(i,:))ylabel(IMFstring(i)) end其中imf_norm为分解得到的imfs 效果图&#xff1a; …

python里apply用法_Python apply函数的用法

Python编程语言Python 是一种面向对象、解释型计算机程序设计语言&#xff0c;由Guido van Rossum于1989年底发明&#xff0c;第一个公开发行版发行于1991年。Python语法简洁而清晰&#xff0c;具有丰富和强大的类库。它常被昵称为胶水语言&#xff0c;它能够把用其他语言制作的…

HDL抽象等级 仿真模型 网表 delay speicfy与sdf

1.HDL 硬件描述语言 抽象分级 HDL这里主要说verilog 在描述硬件电路时分为三个抽象级别 行为级模型&#xff1a;主要用于test bench&#xff0c;着重系统行为和算法&#xff0c;不在于电路实现&#xff0c;不可综合&#xff08;常用描述有initial&#xff0c;fork/join&#…

【MYSQL】MYSQL应用环境,系统特征,储存引擎,应用框架和索引功能的详细讲解

作者简介&#xff1a; 辭七七&#xff0c;目前大一&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a; 七七的闲谈 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01;&#x1f496;&#x1f…

DINO-DETR匈牙利匹配与加噪过程学习记录

今天再来回顾一下DINO中匈牙利匹配与损失函数部分&#xff0c;该部分大致与DETR相似&#xff0c;却又略有不同。 为了查看数据方便&#xff0c;博主将num_query改为20&#xff0c;max_select值也为20。 匈牙利匹配过程 首先是数据送入匈牙利匹配中进行标签匹配过程了。 获取…

qt.qpa.plugin: Could not load the Qt platform plugin “xcb“ in

兄弟们看看是不是这个错&#xff1a; QObject::moveToThread: Current thread (0xe5205f0) is not the objects thread (0xa14d0f0). Cannot move to target thread (0xe5205f0)qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "/xxx/python3.…

Esp32+Blynk实现云端控制LED开灭

目录 环境配置依赖库安装blynk 基础设置 GPIO 点灯实验 环境配置 依赖库安装 参考 blynk 官方快速上手文档 如果要使用 blynk 提供的环境&#xff0c;我们就必须安装对应的库 选择基于 blynk 且适用于 ESP32 的库并安装到 arduino 上&#xff1a; blynk 基础设置 进入官网并且…

Question1:harbor登录成功,推送镜像失败

denied: requested access to the resource is denied 解决方案 查看用户的权限 Harbor 用户角色权限速查 系统级角色&#xff1a; Harbor 系统管理员&#xff1a;“Harbor 系统管理员”拥有最多的权限。除了上述权限外&#xff0c;“Harbor 系统管理员”还可以列出所有项目、…

一种令人拍案叫绝的 ChatGPT 攻击手段!

公众号关注 “GitHubDaily” 设为 “星标”&#xff0c;每天带你逛 GitHub&#xff01; 最近看到一个非常巧妙的 ChatGPT 攻击手段&#xff0c;跟大家分享一下&#xff0c;也算是做个提醒。 不论你是否懂技术&#xff0c;我都建议你了解一下这种攻击手段&#xff0c;有备无患。…

Golang的trace性能分析

文章目录 一、trace概述二、trace的使用方式代码中trace采集通过pprof采集 三、trace分析细节trace的web界面trace中需要关注的关注GC的频率关注goroutine调度情况关注goroutine的数量理想情况 四、GC分析当前服务GC情况设置GOGC设置GOMEMLIMITGC阈值的讨论GC的特点 五、gorout…

【每日挠头算法题(8)】最后一个单词的长度|重新排列字符串

文章目录 一、最后一个单词的长度思路1&#xff1a;从后往前遍历具体代码如下&#xff1a; 思路2&#xff1a;具体代码如下&#xff1a; 二、重新排列字符串思路具体代码如下&#xff1a; 一、最后一个单词的长度 点我直达~ 思路1&#xff1a;从后往前遍历 从后往前遍历&…