C++学习:学生成绩管理系统

下面是一个综合性的C++代码示例,涵盖了C++的核心语法和常用特性。这个程序实现了一个简单的学生成绩管理系统。

程序代码

cpp 复制代码
// ============================================
// 文件: student_management.cpp
// 描述: 一个完整的学生成绩管理系统
// 包含了C++常用语法和特性的示例
// ============================================

// ====================
// 1. 预处理指令
// ====================
// #include 用于包含头文件
// <iostream> 标准输入输出流头文件
#include <iostream>
// <string> 字符串操作头文件
#include <string>
// <vector> 动态数组容器
#include <vector>
// <map> 关联容器,键值对存储
#include <map>
// <algorithm> 算法库,包含排序、查找等
#include <algorithm>
// <fstream> 文件流操作
#include <fstream>
// <iomanip> 输入输出格式化
#include <iomanip>
// <stdexcept> 异常处理类
#include <stdexcept>

// 使用命名空间std,避免重复写std::
using namespace std;

// 宏定义:定义常量
// 宏在预处理阶段进行文本替换
#define MAX_STUDENTS 100
#define MIN_SCORE 0
#define MAX_SCORE 100

// 条件编译:调试模式开关
#ifdef DEBUG_MODE
    #define DEBUG_LOG(msg) cout << "[DEBUG] " << msg << endl
#else
    #define DEBUG_LOG(msg)
#endif

// ====================
// 2. 全局函数声明
// ====================
// 函数原型声明:告诉编译器函数的存在
void displayMenu();  // 显示菜单
int getValidInput(int min, int max);  // 获取有效输入

// ====================
// 3. 枚举类型
// ====================
// enum: 定义一组相关的命名常量
enum class GradeLevel {
    FRESHMAN,   // 大一
    SOPHOMORE,  // 大二
    JUNIOR,     // 大三
    SENIOR      // 大四
};

// ====================
// 4. 结构体定义
// ====================
// struct: 定义一组相关数据的复合类型
struct Date {
    int year;
    int month;
    int day;
    
    // 结构体方法
    string toString() const {
        return to_string(year) + "-" + to_string(month) + "-" + to_string(day);
    }
};

// ====================
// 5. 类定义
// ====================
// class: 面向对象的核心,封装数据和操作

// 前向声明
class Student;

// 基类:Person
class Person {
// protected: 保护成员,子类可以访问
protected:
    string name;
    int age;
    
// public: 公有成员,任何代码都可以访问
public:
    // 构造函数:对象创建时自动调用
    Person(const string& n, int a) : name(n), age(a) {
        DEBUG_LOG("Person构造函数被调用: " + n);
    }
    
    // 虚析构函数:确保派生类正确释放资源
    virtual ~Person() {
        DEBUG_LOG("Person析构函数被调用: " + name);
    }
    
    // 虚函数:支持多态
    virtual void displayInfo() const {
        cout << "姓名: " << name << ", 年龄: " << age << endl;
    }
    
    // 纯虚函数:抽象类,不能实例化
    virtual string getType() const = 0;
    
    // 内联函数:小型函数,直接在调用处展开
    inline const string& getName() const { return name; }
    inline int getAge() const { return age; }
    
    // 静态成员函数:属于类而不是对象
    static void showPersonCount() {
        // 静态局部变量:只在第一次调用时初始化
        static int callCount = 0;
        callCount++;
        cout << "showPersonCount被调用了 " << callCount << " 次" << endl;
    }
};

// 派生类:Student
class Student : public Person {
// private: 私有成员,只有类内可以访问
private:
    string studentId;
    GradeLevel gradeLevel;
    vector<int> scores;  // 使用vector存储成绩
    static int studentCount;  // 静态成员变量:所有对象共享
    
public:
    // 构造函数初始化列表
    Student(const string& n, int a, const string& id, GradeLevel grade)
        : Person(n, a), studentId(id), gradeLevel(grade) {
        studentCount++;  // 每创建一个学生,计数器加1
    }
    
    // 析构函数
    ~Student() override {
        studentCount--;  // 对象销毁时计数器减1
        DEBUG_LOG("Student析构函数被调用: " + name);
    }
    
    // 成员函数
    void addScore(int score) {
        // 异常处理:检查输入是否有效
        if (score < MIN_SCORE || score > MAX_SCORE) {
            throw out_of_range("成绩必须在0到100之间");
        }
        scores.push_back(score);
    }
    
    double calculateAverage() const {
        if (scores.empty()) return 0.0;
        
        int sum = 0;
        // 范围for循环:C++11特性
        for (int score : scores) {
            sum += score;
        }
        return static_cast<double>(sum) / scores.size();  // 类型转换
    }
    
    // 重写基类虚函数
    void displayInfo() const override {
        Person::displayInfo();  // 调用基类方法
        cout << "学号: " << studentId << ", 年级: ";
        
        // switch语句
        switch (gradeLevel) {
            case GradeLevel::FRESHMAN: cout << "大一"; break;
            case GradeLevel::SOPHOMORE: cout << "大二"; break;
            case GradeLevel::JUNIOR: cout << "大三"; break;
            case GradeLevel::SENIOR: cout << "大四"; break;
        }
        cout << endl;
        
        if (!scores.empty()) {
            cout << "平均成绩: " << fixed << setprecision(2) << calculateAverage() << endl;
        }
    }
    
    string getType() const override {
        return "学生";
    }
    
    // 友元函数声明:可以访问类的私有成员
    friend void printStudentDetails(const Student& s);
    
    // 静态成员函数
    static int getStudentCount() {
        return studentCount;
    }
    
    // 重载运算符:使对象支持比较
    bool operator<(const Student& other) const {
        return calculateAverage() < other.calculateAverage();
    }
};

// 静态成员变量初始化
int Student::studentCount = 0;

// 友元函数定义
void printStudentDetails(const Student& s) {
    cout << "=== 学生详细信息 ===" << endl;
    cout << "姓名: " << s.name << endl;  // 友元可以访问私有成员
    cout << "学号: " << s.studentId << endl;
}

// ====================
// 6. 模板类
// ====================
// template: 泛型编程,支持多种数据类型
template<typename T>
class Container {
private:
    vector<T> items;
    
public:
    void add(const T& item) {
        items.push_back(item);
    }
    
    void displayAll() const {
        for (const auto& item : items) {
            item.displayInfo();
        }
    }
    
    // 模板函数
    template<typename Compare>
    void sortItems(Compare comp) {
        std::sort(items.begin(), items.end(), comp);
    }
    
    size_t size() const {
        return items.size();
    }
};

// ====================
// 7. 函数定义
// ====================
// 显示主菜单
void displayMenu() {
    cout << "\n========== 学生成绩管理系统 ==========" << 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 << "0. 退出" << endl;
    cout << "=====================================" << endl;
    cout << "请选择操作: ";
}

// 获取有效输入
int getValidInput(int min, int max) {
    int choice;
    while (true) {
        cin >> choice;
        if (cin.fail() || choice < min || choice > max) {
            cin.clear();  // 清除错误状态
            cin.ignore(numeric_limits<streamsize>::max(), '\n');  // 忽略错误输入
            cout << "输入无效,请重新输入 (" << min << "-" << max << "): ";
        } else {
            cin.ignore();  // 清除换行符
            break;
        }
    }
    return choice;
}

// 保存数据到文件
void saveToFile(const Container<Student>& container, const string& filename) {
    // ofstream: 输出文件流
    ofstream outFile(filename);
    if (!outFile) {
        cerr << "无法打开文件: " << filename << endl;
        return;
    }
    
    // 这里简化处理,实际项目需要更复杂的序列化
    outFile << "学生总数: " << container.size() << endl;
    outFile << "=== 学生数据结束 ===" << endl;
    
    outFile.close();
    cout << "数据已保存到 " << filename << endl;
}

// 从文件加载数据
void loadFromFile(const string& filename) {
    // ifstream: 输入文件流
    ifstream inFile(filename);
    if (!inFile) {
        cerr << "无法打开文件: " << filename << endl;
        return;
    }
    
    string line;
    while (getline(inFile, line)) {
        cout << line << endl;
    }
    
    inFile.close();
    cout << "数据已从 " << filename << " 加载" << endl;
}

// ====================
// 8. Lambda表达式
// ====================
// C++11特性:匿名函数
auto compareByAverageDesc = [](const Student& a, const Student& b) {
    return a.calculateAverage() > b.calculateAverage();
};

// ====================
// 9. 主函数
// ====================
int main() {
    // 设置控制台输出为UTF-8,支持中文
    system("chcp 65001 > nul");
    
    cout << "欢迎使用学生成绩管理系统!" << endl;
    
    Container<Student> students;
    int choice;
    
    do {
        displayMenu();
        choice = getValidInput(0, 8);
        
        try {
            switch (choice) {
                case 1: {
                    // 添加学生
                    if (students.size() >= MAX_STUDENTS) {
                        cout << "学生数量已达上限!" << endl;
                        break;
                    }
                    
                    string name, id;
                    int age, gradeChoice;
                    
                    cout << "请输入学生姓名: ";
                    getline(cin, name);
                    
                    cout << "请输入学生年龄: ";
                    age = getValidInput(1, 100);
                    
                    cout << "请输入学号: ";
                    getline(cin, id);
                    
                    cout << "请选择年级 (1-大一, 2-大二, 3-大三, 4-大四): ";
                    gradeChoice = getValidInput(1, 4);
                    
                    GradeLevel grade;
                    switch (gradeChoice) {
                        case 1: grade = GradeLevel::FRESHMAN; break;
                        case 2: grade = GradeLevel::SOPHOMORE; break;
                        case 3: grade = GradeLevel::JUNIOR; break;
                        case 4: grade = GradeLevel::SENIOR; break;
                    }
                    
                    Student newStudent(name, age, id, grade);
                    
                    // 添加成绩
                    char addScore;
                    cout << "是否添加成绩? (y/n): ";
                    cin >> addScore;
                    cin.ignore();
                    
                    if (addScore == 'y' || addScore == 'Y') {
                        int scoreCount;
                        cout << "要添加几门成绩? ";
                        scoreCount = getValidInput(1, 10);
                        
                        for (int i = 0; i < scoreCount; i++) {
                            cout << "请输入第 " << (i + 1) << " 门成绩: ";
                            int score = getValidInput(0, 100);
                            newStudent.addScore(score);
                        }
                    }
                    
                    students.add(newStudent);
                    cout << "学生添加成功!" << endl;
                    break;
                }
                
                case 2:
                    // 显示所有学生
                    cout << "\n=== 所有学生信息 ===" << endl;
                    if (students.size() == 0) {
                        cout << "没有学生记录。" << endl;
                    } else {
                        students.displayAll();
                    }
                    break;
                    
                case 3:
                    // 这里简化为提示信息,实际需要实现选择学生并添加成绩
                    cout << "功能待实现: 请先选择学生,然后添加成绩" << endl;
                    break;
                    
                case 4:
                    // 按平均成绩排序
                    if (students.size() > 0) {
                        students.sortItems(compareByAverageDesc);
                        cout << "学生已按平均成绩降序排列!" << endl;
                        students.displayAll();
                    } else {
                        cout << "没有学生记录可排序。" << endl;
                    }
                    break;
                    
                case 5:
                    // 保存到文件
                    saveToFile(students, "students.txt");
                    break;
                    
                case 6:
                    // 从文件加载
                    loadFromFile("students.txt");
                    break;
                    
                case 7:
                    // 显示学生总数
                    cout << "当前学生总数: " << Student::getStudentCount() << endl;
                    Person::showPersonCount();
                    break;
                    
                case 8: {
                    // 模板容器示例
                    cout << "=== 模板容器示例 ===" << endl;
                    
                    // 创建整数容器
                    Container<int> intContainer;
                    intContainer.add(10);
                    intContainer.add(20);
                    intContainer.add(5);
                    
                    // 创建字符串容器
                    Container<string> strContainer;
                    strContainer.add("苹果");
                    strContainer.add("香蕉");
                    strContainer.add("橙子");
                    
                    cout << "整数容器大小: " << intContainer.size() << endl;
                    cout << "字符串容器大小: " << strContainer.size() << endl;
                    break;
                }
                    
                case 0:
                    cout << "感谢使用,再见!" << endl;
                    break;
                    
                default:
                    cout << "无效选择!" << endl;
            }
        } catch (const exception& e) {
            // 异常处理
            cerr << "发生错误: " << e.what() << endl;
        }
        
    } while (choice != 0);
    
    return 0;
}

如何编译和运行

在Windows上:

使用MinGW (推荐):

下载并安装MinGW-w64

打开命令提示符或PowerShell

导航到代码所在目录

编译:g++ -std=c++11 student_management.cpp -o student_management.exe

运行:student_management.exe

使用Visual Studio:

创建新的C++控制台项目

将代码复制到main.cpp

按F5编译并运行

在Linux/macOS上:

打开终端

导航到代码所在目录

编译:g++ -std=c++11 student_management.cpp -o student_management

运行:./student_management

C++基础知识概览

  1. 预处理指令

    #include:包含头文件

    #define:定义宏

    #ifdef/#endif:条件编译

  2. 基本数据类型

    int:整数

    double:双精度浮点数

    char:字符

    bool:布尔值

    string:字符串(来自标准库)

  3. 复合数据类型

    struct:结构体

    class:类

    enum:枚举

    union:联合(未在示例中展示)

  4. 变量作用域

    局部变量:函数内定义

    全局变量:文件内定义

    静态变量:static关键字

    成员变量:类的组成部分

  5. 控制结构

    if/else:条件判断

    for:循环

    while:循环

    switch:多分支选择

    break/continue:循环控制

  6. 函数

    函数声明和定义

    参数传递(值传递、引用传递)

    返回值

    函数重载

    递归(未在示例中展示)

  7. 面向对象编程

    类与对象

    构造函数与析构函数

    继承与多态

    封装(public/private/protected)

    虚函数与纯虚函数

  8. 内存管理

    自动存储(栈)

    动态存储(堆,使用new/delete)

    智能指针(未在示例中展示)

  9. 标准库组件

    vector:动态数组

    map:关联数组

    string:字符串

    fstream:文件流

    算法库:sort, find等

  10. 高级特性

    模板(泛型编程)

    异常处理

    命名空间

Lambda表达式(C++11)

类型推导(auto)

学习建议

从简单的程序开始,逐步增加复杂度

多写代码,多调试

理解指针和内存管理

学习STL(标准模板库)

阅读优秀的开源代码

使用现代C++特性(C++11/14/17/20)

这个示例涵盖了C++的大部分核心概念,通过运行和修改这个程序,你可以快速上手C++编程。建议你尝试以下练习:

添加删除学生的功能

实现按姓名搜索学生

添加教师类并实现继承关系

使用智能指针改进内存管理

添加单元测试

相关推荐
lazy H2 小时前
从入门到日常开发,一篇文章掌握 Git 核心操作
git·后端·学习·github
Scott9999HH9 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
2401_8414956410 小时前
【操作系统】进程同步与互斥实验报告
c++·算法·操作系统·进程·并发·同步·互斥
fqbqrr10 小时前
2607C++,soui与安卓
c++·soui
码智社10 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海10 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖11 小时前
JDK 26 新特性详解
java·开发语言
马优晨12 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
a11177613 小时前
2FA 验证码生成器(github登录验证 app)
笔记·学习
我的xiaodoujiao13 小时前
API 接口自动化测试详细图文教程学习系列32--Allure测试报告2
python·学习·测试工具·pytest