这是我们课设目前的代码,接下来还需要:数据持久化
实现CSV读写
添加错误处理
设计数据验证,这些应该如何实现
// DateTime.h
#pragma once
#include <string>
#include <ctime>
#include <sstream>
#include <iomanip>
#include <iostream>
// 日期类
class Date {
private:
int year, month, day;
public:
Date(int y = 0, int m = 0, int d = 0)
: year(y), month(m), day(d) {}
static Date fromString(const std::string& str) {
if (str.empty()) return Date();
int y, m, d;
char delim;
std::stringstream ss(str);
ss >> y >> delim >> m >> delim >> d;
return Date(y, m, d);
}
std::string toString() const {
std::stringstream ss;
ss << std::setfill('0') << std::setw(4) << year << "-"
<< std::setw(2) << month << "-" << std::setw(2) << day;
return ss.str();
}
bool operator==(const Date& other) const {
return year == other.year &&
month == other.month &&
day == other.day;
}
bool operator<(const Date& other) const {
if (year != other.year) return year < other.year;
if (month != other.month) return month < other.month;
return day < other.day;
}
// 修复了 operator> 的实现
bool operator>(const Date& other) const {
if (year != other.year) return year > other.year;
if (month != other.month) return month > other.month;
return day > other.day;
}
};
// 时间类
class Time {
private:
int hour, minute;
public:
Time(int h = 0, int m = 0) : hour(h), minute(m) {}
static Time fromString(const std::string& str) {
if (str.empty()) return Time();
int h, m;
char delim;
std::stringstream ss(str);
ss >> h >> delim >> m;
return Time(h, m);
}
std::string toString() const {
std::stringstream ss;
ss << std::setfill('0') << std::setw(2) << hour << ":"
<< std::setw(2) << minute;
return ss.str();
}
int toMinutes() const { return hour * 60 + minute; }
bool operator==(const Time& other) const {
return hour == other.hour && minute == other.minute;
}
bool operator<(const Time& other) const {
return toMinutes() < other.toMinutes();
}
bool operator>(const Time& other) const {
return toMinutes() > other.toMinutes();
}
};
// 时间段类
class TimeRange {
private:
Time start, end;
public:
TimeRange(const Time& s = Time(), const Time& e = Time())
: start(s), end(e) {}
static TimeRange fromString(const std::string& str) {
if (str.empty()) return TimeRange();
size_t pos = str.find('-');
if (pos == std::string::npos) return TimeRange();
return TimeRange(
Time::fromString(str.substr(0, pos)),
Time::fromString(str.substr(pos + 1))
);
}
std::string toString() const {
return start.toString() + "-" + end.toString();
}
bool overlaps(const TimeRange& other) const {
return start < other.end&& end > other.start;
}
// 添加相等运算符重载
bool operator==(const TimeRange& other) const {
return start == other.start && end == other.end;
}
};
// 考试时间段
class ExamSlot {
private:
Date date;
TimeRange time;
public:
ExamSlot(const Date& d = Date(), const TimeRange& t = TimeRange())
: date(d), time(t) {}
static ExamSlot fromString(const std::string& str) {
if (str.empty()) return ExamSlot();
size_t pos = str.find(' ');
if (pos == std::string::npos) return ExamSlot();
return ExamSlot(
Date::fromString(str.substr(0, pos)),
TimeRange::fromString(str.substr(pos + 1))
);
}
std::string toString() const {
return date.toString() + " " + time.toString();
}
bool conflictsWith(const ExamSlot& other) const {
return date == other.date && time.overlaps(other.time);
}
// 添加相等运算符重载(修复了编译错误)
bool operator==(const ExamSlot& other) const {
return date == other.date && time == other.time;
}
};
// Teacher.h
#include <vector>
#include <string>
#include <algorithm>
class Teacher {
private:
std::string id;
std::string name;
std::vector<ExamSlot> assignedSlots;
public:
Teacher(const std::string& id = "", const std::string& name = "")
: id(id), name(name) {}
// 访问器
const std::string& getId() const { return id; }
const std::string& getName() const { return name; }
// 添加清除监考任务的方法
void clearAssignments() {
assignedSlots.clear();
}
// 添加监考任务
void assignExam(const ExamSlot& slot) {
if (std::find(assignedSlots.begin(), assignedSlots.end(), slot) == assignedSlots.end()) {
assignedSlots.push_back(slot);
}
}
// 检查时间段是否可用
bool isAvailable(const ExamSlot& slot) const {
for (const auto& assigned : assignedSlots) {
if (assigned.conflictsWith(slot)) {
return false;
}
}
return true;
}
// 统计监考次数
int totalProctorCount() const {
return static_cast<int>(assignedSlots.size());
}
// 序列化
std::string toString() const {
return id + "," + name + "," + std::to_string(totalProctorCount());
}
};
// Exam.h
#include <vector>
#include <string>
#include <algorithm>
class Exam {
private:
std::string courseCode;
std::string courseName;
ExamSlot slot;
std::string location;
int studentCount;
std::vector<std::string> instructors;
std::vector<std::string> proctors;
public:
Exam(const std::string& code = "", const std::string& name = "",
const ExamSlot& slot = ExamSlot(), const std::string& loc = "",
int students = 0)
: courseCode(code), courseName(name), slot(slot),
location(loc), studentCount(students) {}
// 访问器
const std::string& getCourseCode() const { return courseCode; }
const std::string& getCourseName() const { return courseName; }
const ExamSlot& getSlot() const { return slot; }
const std::string& getLocation() const { return location; }
int getStudentCount() const { return studentCount; }
// 添加清除监考教师的方法
void clearProctors() {
proctors.clear();
}
// 教师管理
void addInstructor(const std::string& teacher) {
if (std::find(instructors.begin(), instructors.end(), teacher) == instructors.end()) {
instructors.push_back(teacher);
}
}
void addProctor(const std::string& teacher) {
if (std::find(proctors.begin(), proctors.end(), teacher) == proctors.end()) {
proctors.push_back(teacher);
}
}
const std::vector<std::string>& getInstructors() const { return instructors; }
const std::vector<std::string>& getProctors() const { return proctors; }
// 检查教师身份
bool isInstructor(const std::string& teacher) const {
return std::find(instructors.begin(), instructors.end(), teacher) != instructors.end();
}
// 计算所需监考人数
int requiredProctors() const {
return studentCount > 50 ? 3 : 2;
}
// 当前监考人数
int currentProctors() const {
return static_cast<int>(proctors.size());
}
// 序列化
std::string toString() const {
std::string result = courseCode + "," + courseName + "," +
slot.toString() + "," + location + "," +
std::to_string(studentCount) + ",";
// 添加任课教师
for (size_t i = 0; i < instructors.size(); ++i) {
if (i > 0) result += ";";
result += instructors[i];
}
result += ",";
// 添加监考教师
for (size_t i = 0; i < proctors.size(); ++i) {
if (i > 0) result += ";";
result += proctors[i];
}
return result;
}
// 反序列化
static Exam fromString(const std::string& str) {
std::vector<std::string> parts;
std::stringstream ss(str);
std::string item;
while (std::getline(ss, item, ',')) {
parts.push_back(item);
}
if (parts.size() < 7) return Exam();
Exam exam(
parts[0],
parts[1],
ExamSlot::fromString(parts[2]),
parts[3],
std::stoi(parts[4])
);
// 解析任课教师
std::stringstream instructorsStream(parts[5]);
while (std::getline(instructorsStream, item, ';')) {
if (!item.empty()) exam.addInstructor(item);
}
// 解析监考教师
std::stringstream proctorsStream(parts[6]);
while (std::getline(proctorsStream, item, ';')) {
if (!item.empty()) exam.addProctor(item);
}
return exam;
}
};
// ProctorAssigner.h
#include <vector>
#include <algorithm>
#include <random>
#include <unordered_map>
#include <climits>
class ProctorAssigner {
public:
// 执行监考分配
void assign(std::vector<Exam>& exams, std::vector<Teacher>& teachers) {
// 1. 按时间排序考试
std::sort(exams.begin(), exams.end(), [](const Exam& a, const Exam& b) {
return a.getSlot().toString() < b.getSlot().toString();
});
// 2. 重置所有监考分配
for (auto& teacher : teachers) {
teacher.clearAssignments(); // 使用新添加的方法
}
for (auto& exam : exams) {
exam.clearProctors(); // 使用新添加的方法
}
// 3. 准备教师映射
std::unordered_map<std::string, Teacher*> teacherMap;
for (auto& teacher : teachers) {
teacherMap[teacher.getName()] = &teacher;
}
// 4. 分配任课教师
assignInstructors(exams, teacherMap);
// 5. 分配额外监考
assignAdditionalProctors(exams, teachers);
}
private:
// 分配任课教师
void assignInstructors(std::vector<Exam>& exams,
std::unordered_map<std::string, Teacher*>& teacherMap) {
for (auto& exam : exams) {
for (const auto& instructor : exam.getInstructors()) {
auto it = teacherMap.find(instructor);
if (it != teacherMap.end()) {
Teacher* teacher = it->second;
if (teacher->isAvailable(exam.getSlot())) {
exam.addProctor(instructor);
teacher->assignExam(exam.getSlot());
}
}
}
}
}
// 分配额外监考
void assignAdditionalProctors(std::vector<Exam>& exams,
std::vector<Teacher>& teachers) {
// 创建随机数生成器
static std::mt19937 rng(std::random_device{}());
for (auto& exam : exams) {
int needed = exam.requiredProctors() - exam.currentProctors();
while (needed > 0) {
// 随机打乱教师顺序以确保均衡性
std::shuffle(teachers.begin(), teachers.end(), rng);
Teacher* bestCandidate = nullptr;
int minAssignments = INT_MAX;
// 寻找最合适的教师
for (auto& teacher : teachers) {
// 跳过任课教师
if (exam.isInstructor(teacher.getName())) continue;
// 检查时间冲突
if (!teacher.isAvailable(exam.getSlot())) continue;
// 选择监考次数最少的教师
if (teacher.totalProctorCount() < minAssignments) {
minAssignments = teacher.totalProctorCount();
bestCandidate = &teacher;
}
}
// 如果没有可用教师,退出循环
if (!bestCandidate) break;
// 分配监考
exam.addProctor(bestCandidate->getName());
bestCandidate->assignExam(exam.getSlot());
needed--;
}
}
}
};
// CsvHandler.h
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
class CsvHandler {
public:
// 加载考试数据
static std::vector<Exam> loadExams(const std::string& filePath) {
std::vector<Exam> exams;
std::ifstream file(filePath);
if (!file.is_open()) {
return exams;
}
std::string line;
std::getline(file, line); // 跳过标题行
while (std::getline(file, line)) {
if (line.empty()) continue;
Exam exam = Exam::fromString(line);
if (!exam.getCourseCode().empty()) {
exams.push_back(exam);
}
}
file.close();
return exams;
}
// 加载教师数据
static std::vector<Teacher> loadTeachers(const std::string& filePath) {
std::vector<Teacher> teachers;
std::ifstream file(filePath);
if (!file.is_open()) {
return teachers;
}
std::string line;
std::getline(file, line); // 跳过标题行
while (std::getline(file, line)) {
if (line.empty()) continue;
std::stringstream ss(line);
std::string id, name;
std::getline(ss, id, ',');
std::getline(ss, name);
if (!id.empty() && !name.empty()) {
teachers.push_back(Teacher(id, name));
}
}
file.close();
return teachers;
}
// 保存考试数据
static bool saveExams(const std::vector<Exam>& exams, const std::string& filePath) {
std::ofstream file(filePath);
if (!file.is_open()) {
return false;
}
// 标题行
file << "课程代码,课程名称,考试时间,地点,学生人数,任课教师,监考教师\n";
for (const auto& exam : exams) {
file << exam.toString() << "\n";
}
file.close();
return true;
}
// 保存统计数据
static bool saveStatistics(const std::vector<Teacher>& teachers, const std::string& filePath) {
std::ofstream file(filePath);
if (!file.is_open()) {
return false;
}
// 标题行
file << "教师ID,教师姓名,总监考次数\n";
for (const auto& teacher : teachers) {
file << teacher.toString() << "\n";
}
file.close();
return true;
}
};
// main.cpp
int main() {
try {
// 1. 加载数据
auto exams = CsvHandler::loadExams("all_exams.csv");
auto teachers = CsvHandler::loadTeachers("teachers.csv");
// 2. 筛选本系考试
std::string department = "计算机科学与技术系";
std::vector<Exam> deptExams;
for (const auto& exam : exams) {
// 根据实际数据结构实现筛选逻辑
// 示例:if (exam.getDepartment() == department)...
deptExams.push_back(exam);
}
// 3. 执行监考分配
ProctorAssigner assigner;
assigner.assign(deptExams, teachers);
// 4. 保存结果
CsvHandler::saveExams(deptExams, "dept_exams.csv");
CsvHandler::saveStatistics(teachers, "statistics.csv");
std::cout << "监考分配完成!结果已保存到文件。" << std::endl;
}
catch (const std::exception& e) {
std::cerr << "发生错误: " << e.what() << std::endl;
return 1;
}
return 0;
}
最新发布