学生选课系统设计文档
一、系统概述
1.1 设计目标
开发一个基于C++的学生选课管理系统,实现课程信息管理、学生信息管理和选课管理等功能。系统采用面向对象方法设计,具有良好的可扩展性和维护性。
1.2 系统功能
- 用户认证管理
- 课程信息管理
- 学生信息管理
- 选课管理
- 系统维护功能
二、系统设计
2.1 系统架构图
2.2 功能模块图
三、数据流程
3.1 系统总体流程图
3.2 选课流程图
四、类设计
4.1 类关系图
五、技术实现要点
5.1 核心技术
-
面向对象设计
- 继承关系设计
- 多态性应用
- 封装性实现
-
数据结构应用
- STL容器使用
- 智能指针管理
- 异常处理机制
-
用户界面设计
- 菜单驱动设计
- 输入验证
- 错误处理
5.2 关键算法
- 选课冲突检测
- 学分统计计算
- 数据查询优化
六、系统测试
6.1 测试项目
-
功能测试
- 用户登录
- 课程管理
- 学生管理
- 选课功能
- 密码修改
-
性能测试
- 数据处理效率
- 内存占用
- 响应时间
6.2 测试用例
测试项 | 输入数据 | 预期结果 | 测试结果 |
---|---|---|---|
登录 | 正确密码 | 登录成功 | 通过 |
登录 | 错误密码 | 登录失败 | 通过 |
选课 | 有效数据 | 选课成功 | 通过 |
退课 | 有效数据 | 退课成功 | 通过 |
七、后续优化建议
7.1 功能扩展
- 数据持久化存储
- 用户权限管理
- 成绩管理功能
- 课程时间管理
7.2 技术优化
- 数据库集成
- 图形用户界面
- 网络功能支持
- 日志记录功能
八、总结
本系统采用面向对象的设计方法,实现了基本的选课管理功能。系统结构清晰,具有良好的可扩展性和可维护性。通过合理的类设计和模块划分,较好地满足了项目需求。虽然还存在优化空间,但作为基础的管理系统,已经实现了核心功能并保持了良好的代码质量。
效果图
项目目录
StudentCourseSystem/
│
├── StudentCourseSystem/ # 主项目目录
│ ├── include/ # 头文件目录
│ │ ├── Base.h # 基类头文件
│ │ ├── Course.h # 课程类头文件
│ │ ├── Student.h # 学生类头文件
│ │ ├── System.h # 系统类头文件
│ │ └── UserInterface.h # 用户界面类头文件
│ │
│ ├── src/ # 源文件目录
│ │ └── main.cpp # 主程序入口
源码
#ifndef BASE_H
#define BASE_H
#include <string>
class Base {
protected:
long id;
std::string name;
public:
Base() : id(0) {}
Base(long id, std::string name) : id(id), name(std::move(name)) {}
virtual ~Base() = default;
long getId() const { return id; }
const std::string& getName() const { return name; }
void setId(long newId) { id = newId; }
void setName(const std::string& newName) { name = newName; }
};
#endif // BASE_H
#ifndef COURSE_H
#define COURSE_H
#include "Base.h"
#include <vector>
#include <memory>
#include <iostream>
class Course : public Base {
private:
int credit;
std::string teacherName;
public:
Course() : credit(0) {}
Course(long id, std::string name, int credit, std::string teacher)
: Base(id, std::move(name)), credit(credit), teacherName(std::move(teacher)) {}
// Getters
int getCredit() const { return credit; }
const std::string& getTeacherName() const { return teacherName; }
// Setters
void setCredit(int newCredit) { credit = newCredit; }
void setTeacherName(const std::string& newTeacher) { teacherName = newTeacher; }
// Display course info
void display() const {
std::cout << "课程编号: " << id << "\t课程名称: " << name
<< "\t学分: " << credit << "\t授课教师: " << teacherName << std::endl;
}
};
#endif // COURSE_H
// Student.h
#ifndef STUDENT_H
#define STUDENT_H
#include "Base.h"
#include "Course.h"
#include <vector>
#include <memory>
#include <algorithm>
class Student : public Base {
private:
std::string gender;
std::string grade;
int maxCredit;
std::vector<std::shared_ptr<Course>> selectedCourses;
public:
Student() : maxCredit(0) {}
Student(long id, std::string name, std::string gender, std::string grade, int maxCredit)
: Base(id, std::move(name)), gender(std::move(gender)),
grade(std::move(grade)), maxCredit(maxCredit) {}
// Getters
const std::string& getGender() const { return gender; }
const std::string& getGrade() const { return grade; }
int getMaxCredit() const { return maxCredit; }
const std::vector<std::shared_ptr<Course>>& getSelectedCourses() const { return selectedCourses; }
// Course management
bool addCourse(const std::shared_ptr<Course>& course) {
// Check if course already exists
auto it = std::find_if(selectedCourses.begin(), selectedCourses.end(),
[&course](const std::shared_ptr<Course>& c) { return c->getId() == course->getId(); });
if (it != selectedCourses.end()) {
return false; // Course already selected
}
// Check credit limit
int currentCredit = getCurrentCredit();
if (currentCredit + course->getCredit() > maxCredit) {
return false; // Exceeds credit limit
}
selectedCourses.push_back(course);
return true;
}
bool removeCourse(long courseId) {
auto it = std::find_if(selectedCourses.begin(), selectedCourses.end(),
[courseId](const std::shared_ptr<Course>& c) { return c->getId() == courseId; });
if (it != selectedCourses.end()) {
selectedCourses.erase(it);
return true;
}
return false;
}
int getCurrentCredit() const {
int total = 0;
for (const auto& course : selectedCourses) {
total += course->getCredit();
}
return total;
}
void display() const {
std::cout << "学号: " << id << "\t姓名: " << name
<< "\t性别: " << gender << "\t年级: " << grade
<< "\t最大学分: " << maxCredit << std::endl;
std::cout << "已选课程:" << std::endl;
if (selectedCourses.empty()) {
std::cout << "暂无选课" << std::endl;
}
else {
for (const auto& course : selectedCourses) {
course->display();
}
std::cout << "当前已选学分: " << getCurrentCredit() << "/" << maxCredit << std::endl;
}
}
};
#endif // STUDENT_H
// System.h
#ifndef SYSTEM_H
#define SYSTEM_H
#include "Student.h"
#include "Course.h"
#include <map>
#include <memory>
#include <string>
class System {
private:
static std::string password;
static bool isLoggedIn;
static std::map<long, std::shared_ptr<Course>> courses;
static std::map<long, std::shared_ptr<Student>> students;
public:
static void setInitialPassword(const std::string& pwd) {
password = pwd;
}
static bool login(const std::string& pwd) {
isLoggedIn = (pwd == password);
return isLoggedIn;
}
static bool isAuthenticated() { return isLoggedIn; }
static void logout() { isLoggedIn = false; }
static bool changePassword(const std::string& oldPwd, const std::string& newPwd) {
if (oldPwd == password) {
password = newPwd;
return true;
}
return false;
}
// Course management
static bool addCourse(const std::shared_ptr<Course>& course) {
if (!course || courses.find(course->getId()) != courses.end()) {
return false;
}
courses[course->getId()] = course;
return true;
}
static bool removeCourse(long courseId) {
return courses.erase(courseId) > 0;
}
static std::shared_ptr<Course> findCourse(long courseId) {
auto it = courses.find(courseId);
return (it != courses.end()) ? it->second : nullptr;
}
static const std::map<long, std::shared_ptr<Course>>& getAllCourses() {
return courses;
}
// Student management
static bool addStudent(const std::shared_ptr<Student>& student) {
if (!student || students.find(student->getId()) != students.end()) {
return false;
}
students[student->getId()] = student;
return true;
}
static bool removeStudent(long studentId) {
return students.erase(studentId) > 0;
}
static std::shared_ptr<Student> findStudent(long studentId) {
auto it = students.find(studentId);
return (it != students.end()) ? it->second : nullptr;
}
static const std::map<long, std::shared_ptr<Student>>& getAllStudents() {
return students;
}
};
// Initialize static members
std::string System::password;
bool System::isLoggedIn = false;
std::map<long, std::shared_ptr<Course>> System::courses;
std::map<long, std::shared_ptr<Student>> System::students;
#endif // SYSTEM_H
// UserInterface.h
#ifndef USER_INTERFACE_H
#define USER_INTERFACE_H
#include "System.h"
#include <iostream>
#include <limits>
#include <cstdlib>
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
class UserInterface {
private:
static void clearScreen() {
#ifdef _WIN32
system("cls");
#else
system("clear");
#endif
}
static void pauseScreen() {
std::cout << "\n按回车键继续...";
std::cin.ignore((std::numeric_limits<std::streamsize>::max)(), '\n');
std::cin.get();
}
public:
static void showLoginMenu() {
std::string pwd;
do {
clearScreen();
std::cout << "=== 学生选课系统登录 ===" << std::endl;
std::cout << "请输入密码(默认: 1234): ";
std::cin >> pwd;
if (!System::login(pwd)) {
std::cout << "密码错误!请重试。" << std::endl;
Sleep(1000);
}
} while (!System::isAuthenticated());
}
static void handleCourseManagement() {
while (true) {
clearScreen();
std::cout << "=== 课程管理 ===" << std::endl;
std::cout << "1. 查看所有课程" << std::endl;
std::cout << "2. 添加课程" << std::endl;
std::cout << "3. 删除课程" << std::endl;
std::cout << "4. 返回主菜单" << std::endl;
int choice;
std::cout << "请选择(1-4):";
std::cin >> choice;
switch (choice) {
case 1: {
clearScreen();
std::cout << "=== 所有课程 ===" << std::endl;
for (const auto& pair : System::getAllCourses()) {
pair.second->display();
}
pauseScreen();
break;
}
case 2: {
clearScreen();
long id;
std::string name, teacher;
int credit;
std::cout << "请输入课程编号:";
std::cin >> id;
std::cout << "请输入课程名称:";
std::cin >> name;
std::cout << "请输入学分:";
std::cin >> credit;
std::cout << "请输入教师姓名:";
std::cin >> teacher;
auto course = std::make_shared<Course>(id, name, credit, teacher);
if (System::addCourse(course)) {
std::cout << "课程添加成功!" << std::endl;
}
else {
std::cout << "课程添加失败!" << std::endl;
}
pauseScreen();
break;
}
case 3: {
clearScreen();
long id;
std::cout << "请输入要删除的课程编号:";
std::cin >> id;
if (System::removeCourse(id)) {
std::cout << "课程删除成功!" << std::endl;
}
else {
std::cout << "课程删除失败!" << std::endl;
}
pauseScreen();
break;
}
case 4:
return;
default:
std::cout << "无效选择!" << std::endl;
pauseScreen();
}
}
}
static void handleStudentManagement() {
while (true) {
clearScreen();
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;
int choice;
std::cout << "请选择(1-5):";
std::cin >> choice;
switch (choice) {
case 1: {
clearScreen();
std::cout << "=== 所有学生 ===" << std::endl;
for (const auto& pair : System::getAllStudents()) {
pair.second->display();
std::cout << "------------------------" << std::endl;
}
pauseScreen();
break;
}
case 2: {
clearScreen();
long id;
std::string name, gender, grade;
int maxCredit;
std::cout << "请输入学号:";
std::cin >> id;
std::cout << "请输入姓名:";
std::cin >> name;
std::cout << "请输入性别:";
std::cin >> gender;
std::cout << "请输入年级:";
std::cin >> grade;
std::cout << "请输入最大学分:";
std::cin >> maxCredit;
auto student = std::make_shared<Student>(id, name, gender, grade, maxCredit);
if (System::addStudent(student)) {
std::cout << "学生添加成功!" << std::endl;
}
std::cout << "学生添加失败!" << std::endl;
pauseScreen();
break;
}
case 3: {
clearScreen();
long id;
std::cout << "请输入要删除的学号:";
std::cin >> id;
if (System::removeStudent(id)) {
std::cout << "学生删除成功!" << std::endl;
}
else {
std::cout << "学生删除失败!" << std::endl;
}
pauseScreen();
break;
}
case 4: {
handleCourseSelection();
break;
}
case 5:
return;
default:
std::cout << "无效选择!" << std::endl;
pauseScreen();
}
}
}
static void handleCourseSelection() {
while (true) {
clearScreen();
std::cout << "=== 选课管理 ===" << std::endl;
std::cout << "1. 添加选课" << std::endl;
std::cout << "2. 删除选课" << std::endl;
std::cout << "3. 返回上级菜单" << std::endl;
int choice;
std::cout << "请选择(1-3):";
std::cin >> choice;
switch (choice) {
case 1: {
clearScreen();
long studentId, courseId;
std::cout << "请输入学号:";
std::cin >> studentId;
std::cout << "请输入课程编号:";
std::cin >> courseId;
auto student = System::findStudent(studentId);
auto course = System::findCourse(courseId);
if (!student || !course) {
std::cout << "学生或课程不存在!" << std::endl;
}
else if (student->addCourse(course)) {
std::cout << "选课成功!" << std::endl;
}
else {
std::cout << "选课失败!可能是重复选课或超出学分限制。" << std::endl;
}
pauseScreen();
break;
}
case 2: {
clearScreen();
long studentId, courseId;
std::cout << "请输入学号:";
std::cin >> studentId;
std::cout << "请输入要退选的课程编号:";
std::cin >> courseId;
auto student = System::findStudent(studentId);
if (!student) {
std::cout << "学生不存在!" << std::endl;
}
else if (student->removeCourse(courseId)) {
std::cout << "退选成功!" << std::endl;
}
else {
std::cout << "退选失败!可能未选择该课程。" << std::endl;
}
pauseScreen();
break;
}
case 3:
return;
default:
std::cout << "无效选择!" << std::endl;
pauseScreen();
}
}
}
static void handlePasswordChange() {
clearScreen();
std::string oldPwd, newPwd;
std::cout << "请输入旧密码:";
std::cin >> oldPwd;
std::cout << "请输入新密码:";
std::cin >> newPwd;
if (System::changePassword(oldPwd, newPwd)) {
std::cout << "密码修改成功!请重新登录。" << std::endl;
Sleep(1000);
System::logout();
}
else {
std::cout << "密码修改失败!旧密码错误。" << std::endl;
pauseScreen();
}
}
static void showMainMenu() {
while (System::isAuthenticated()) {
clearScreen();
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;
int choice;
std::cout << "请选择(1-5):";
std::cin >> choice;
switch (choice) {
case 1:
handleCourseManagement();
break;
case 2:
handleStudentManagement();
break;
case 3:
handlePasswordChange();
break;
case 4:
System::logout();
return;
case 5:
exit(0);
default:
std::cout << "无效选择!" << std::endl;
pauseScreen();
}
}
}
};
#endif // USER_INTERFACE_H
#define NOMINMAX
#include "UserInterface.h"
#include <iostream>
#include <string>
#include <limits>
void initializeSystem() {
// 设置初始密码
std::string password1, password2;
bool passwordMatch = false;
do {
system("cls");
std::cout << "=== 学生选课系统初始化 ===" << std::endl;
std::cout << "请设置系统管理密码:";
std::cin >> password1;
std::cout << "请再次输入密码确认:";
std::cin >> password2;
if (password1 == password2) {
passwordMatch = true;
System::setInitialPassword(password1);
std::cout << "密码设置成功!" << std::endl;
}
else {
std::cout << "两次输入的密码不一致,请重新设置!" << std::endl;
Sleep(1000);
}
} while (!passwordMatch);
// 初始化示例数据
// 添加示例课程
System::addCourse(std::make_shared<Course>(1, "C++程序设计", 2, "孙老师"));
System::addCourse(std::make_shared<Course>(2, "Java语言程序设计", 2, "程老师"));
System::addCourse(std::make_shared<Course>(3, "计算机网络使用及应用", 3, "黄老师"));
// 添加示例学生
auto student1 = std::make_shared<Student>(1, "王小明", "男", "大二", 20);
auto student2 = std::make_shared<Student>(2, "李华", "女", "大二", 22);
System::addStudent(student1);
System::addStudent(student2);
// 添加初始选课记录
student1->addCourse(System::findCourse(1));
student1->addCourse(System::findCourse(2));
student2->addCourse(System::findCourse(2));
std::cout << "\n系统初始化完成!已添加示例数据。" << std::endl;
std::cout << "按回车键继续...";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin.get();
}
int main() {
// 初始化系统数据
initializeSystem();
while (true) {
// 显示登录界面
if (!System::isAuthenticated()) {
UserInterface::showLoginMenu();
}
// 显示主菜单
if (System::isAuthenticated()) {
UserInterface::showMainMenu();
}
}
return 0;
}