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++编程。建议你尝试以下练习:

添加删除学生的功能

实现按姓名搜索学生

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

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

添加单元测试

相关推荐
John_ToDebug2 小时前
Chromium WebUI 定制实践:从 C++ 注入到 JS 安全展示全链路解析
javascript·c++·chrome
雪域迷影2 小时前
使用Python库获取网页时报HTTP 403错误(禁止访问)的解决办法
开发语言·python·http·beautifulsoup·urllib
chao1898442 小时前
基于Qt的SSH/FTP远程文件管理与命令执行实现方案
开发语言·qt·ssh
凯子坚持 c2 小时前
Qt常用控件指南(1)
开发语言·数据库·qt
水饺编程2 小时前
开源项目介绍:VirtuaNES 模拟器
c语言·c++·windows·visual studio
Flash.kkl2 小时前
Python基础语法
开发语言·python
mu_guang_2 小时前
算法图解2-选择排序
数据结构·算法·排序算法
十五年专注C++开发2 小时前
CMake进阶:find_package使用总结
开发语言·c++·cmake·跨平台编译
lxw18449125142 小时前
PHP凉了?岗位缩水50%+,开发者该何去何从?
开发语言·php