From 52dd9b6adf14e9c38473f0a2368162bcdb61627a Mon Sep 17 00:00:00 2001 From: smh Date: Sat, 2 Sep 2023 15:36:45 +0800 Subject: [PATCH] hello world --- Exam.cpp | 134 ++++++++ Exam.h | 47 +++ Item.cpp | 122 +++++++ Item.h | 32 ++ Manager.cpp | 907 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Manager.h | 67 ++++ Student.cpp | 124 +++++++ Student.h | 36 +++ main.cpp | 8 + 9 files changed, 1477 insertions(+) create mode 100644 Exam.cpp create mode 100644 Exam.h create mode 100644 Item.cpp create mode 100644 Item.h create mode 100644 Manager.cpp create mode 100644 Manager.h create mode 100644 Student.cpp create mode 100644 Student.h create mode 100644 main.cpp diff --git a/Exam.cpp b/Exam.cpp new file mode 100644 index 0000000..d2b3b77 --- /dev/null +++ b/Exam.cpp @@ -0,0 +1,134 @@ +#pragma warning(disable:4996) +#include"Exam.h" +using namespace std; + +Exam::Exam(Examsave* insave) { + this->save = *insave; + studentnum = insave->studentnum; + strcpy(name, insave->name); + strcpy(filename, insave->filename); + ifstream ibin(filename, ios::in, ios::binary); + Item tmp; + for (int i = 0; i < studentnum; i++) { + ibin.read((char*)&tmp, sizeof(Item)); + items.push_back(tmp); + } + ibin.close(); + if (items.size() > 0) { + sort(items.begin(), items.end()); + reverse(items.begin(), items.end()); + } +} +Exam::Exam(char inname[]) { + strcpy(name, inname); + studentnum = 0; + ifstream tmp(inname, ios::in, ios::binary); + if (tmp.good()) { + string nname; + nname += inname; + for (auto i = 1; i < 100; i++) { + nname += to_string(i); + ifstream tmp(nname, ios::in, ios::binary); + if (!tmp.good()) { + break; + } + } + strcpy(filename, nname.c_str()); + } + else { + strcpy(filename, inname); + } +} +void Exam::addItem(long long int studentNo, double score[9]) { + rmvItem(studentNo); + Item tmp(studentNo, score); + items.push_back(tmp); + sort(items.begin(), items.end()); + reverse(items.begin(), items.end()); + studentnum++; +} +void Exam::addItem(const Item& item) { + rmvItem(item.getStuNo()); + items.push_back(item); + sort(items.begin(), items.end()); + reverse(items.begin(), items.end()); + studentnum++; +} +void Exam::saveAll(ofstream& examsout) { + strcpy(save.filename, filename); + strcpy(save.name, name); + studentnum = items.size(); + save.studentnum = studentnum; + ofstream obin(filename, ios::out, ios::binary); + Item tmp; + for (auto i = items.begin(); i < items.end(); i++) { + tmp = *i; + obin.write((char*)&tmp, sizeof(Item)); + } + obin.close(); + examsout.write((char*)&this->save, sizeof(Examsave)); +} +void Exam::dspHeader() { + cout << setw(20) << "名称" << setw(15) << "学生数" << endl; +} +void Exam::dsp() const { + cout << setw(20) << name << setw(15) << studentnum << endl; +} +void Exam::dspName() const { + cout << name; +} +void Exam::dspName(int w) const { + cout << setw(w) << name; +} +void Exam::dspItems() const { + for (auto i = items.begin(); i < items.end(); i++) { + i->dsp(); + cout << setw(6) << distance(items.begin(), i) + 1 << endl; + } +} +void Exam::toCsvItems(ofstream& csv) const { + for (auto i = items.begin(); i < items.end(); i++) { + i->toCsv(csv); + csv << distance(items.begin(), i) + 1 << endl; + } +} +bool Exam::itemExists(long long int studentNo) const { + for (auto i = items.begin(); i < items.end(); i++) { + if (i->getStuNo()== studentNo) { + return true; + } + } + return false; +} +bool Exam::rmvItem(long long int studentNo) { + for (auto i = items.begin(); i < items.end(); i++) { + if (i->getStuNo() == studentNo) { + items.erase(i); + studentnum--; + return true; + } + } + return false; +} +void Exam::changeName(char name[]) { + strcpy(this->name, name); +} +const Item* Exam::StudentInquiry(long long int studentNo) const{ + for (auto item = items.begin(); item < items.end(); item++) { + if (item->getStuNo() == studentNo) { + return &(*item); + } + } + return nullptr; +} +int Exam::getStuRanking(const Item& item) { + for (auto i = items.begin(); i < items.end(); i++) { + if (i->stuNoEqual(item)) { + return distance(items.begin(), i) + 1; + } + } + return -1; +} +void Exam::rm() const { + remove(filename); +} diff --git a/Exam.h b/Exam.h new file mode 100644 index 0000000..0328eea --- /dev/null +++ b/Exam.h @@ -0,0 +1,47 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include"Item.h" +using namespace std; + +struct Examsave { + int studentnum; + char name[100]; + char filename[100]; +}; +class Exam { + +public: + Exam(Examsave* insave); + Exam(char inname[]); + + void saveAll(ofstream& examsout); + void addItem(long long int studentNo, double score[9]); + void addItem(const Item& item); + bool rmvItem(long long int studentNo); + static void dspHeader(); + void dsp() const; + void dspName() const; + void dspName(int w) const; + void dspItems() const; + void toCsvItems(ofstream& csv) const; + bool itemExists(long long int studentNo) const; + void changeName(char name[]); + const Item* StudentInquiry(long long int studentNo) const; + int getStuRanking(const Item& item); + void rm() const; + + virtual ~Exam(){}; +private: + vector items; + struct Examsave save; + int studentnum; + char name[100]; + char filename[100]; + + +}; \ No newline at end of file diff --git a/Item.cpp b/Item.cpp new file mode 100644 index 0000000..83cabfe --- /dev/null +++ b/Item.cpp @@ -0,0 +1,122 @@ +#include"Item.h" +#include"Student.h" +#include"Manager.h" +using namespace std; +extern Manager mainManager; +Item::Item(long long int studentNo, double inscore[]) { + sum = 0; + for (int i = 0; i < 9; i++) { + score[i] = inscore[i]; + sum = sum + score[i]; + } + this->studentNo = studentNo; +} +Item::Item() { + studentNo = -1; +} +bool Item::operator<(const Item& i) const { + if (this->sum < i.sum) { + return true; + } + else if (this->sum > i.sum) { + return false; + } + else if (this->studentNo < i.sum) { + return true; + } + else { + return false; + } +} +bool Item::operator>(const Item& i) const { + if (this->sum < i.sum) { + return false; + } + else if (this->sum > i.sum) { + return true; + } + else if (this->studentNo < i.sum) { + return false; + } + else { + return true; + } +} +long long int Item::getStuNo() const { + return studentNo; +} +bool Item::stuNoEqual(const Item& i) const { + if (this->studentNo == i.studentNo) { + return true; + } + else { + return false; + } +} +void Item::dspHeader() { + Student::dspHeader(); + cout << setw(5) << "数学" << setw(5) << "语文" << setw(5) << "英语" << setw(5) << "物理" << setw(5) << "化学" << setw(5) << "生物" << setw(5) << "历史" << setw(5) << "政治" << setw(5) << "地理" << setw(6) << "总分"; +} +void Item::dspHeader(int w) { + cout << setw(5) << "数学" << setw(5) << "语文" << setw(5) << "英语" << setw(5) << "物理" << setw(5) << "化学" << setw(5) << "生物" << setw(5) << "历史" << setw(5) << "政治" << setw(5) << "地理" << setw(6) << "总分"; +} +void Item::dsp() const { + Student* stup = mainManager.searchByNo(this->studentNo); + Student stu; + if (stup == nullptr) { + stu = Student(this->studentNo); + } + else { + stu = *stup; + } + + stu.dsp(); + cout << setw(5) << score[0] << setw(5) << score[1] << setw(5) << score[2] << setw(5) << score[3] << setw(5) << score[4] << setw(5) << score[5] << setw(5) << score[6] << setw(5) << score[7] << setw(5) << score[8] << setw(6) << sum; +} +void Item::dsp(int w) const { + cout << setw(5) << score[0] << setw(5) << score[1] << setw(5) << score[2] << setw(5) << score[3] << setw(5) << score[4] << setw(5) << score[5] << setw(5) << score[6] << setw(5) << score[7] << setw(5) << score[8] << setw(6) << sum; +} +void Item::toCsvHeader(ofstream& csv) { + Student::toCsvHeader(csv); + csv << "数学," << "语文," << "英语," << "物理," << "化学," << "生物," << "历史," << "政治," << "地理," << "总分,"; +} +void Item::toCsv(ofstream& csv) const { + Student* stup = mainManager.searchByNo(this->studentNo); + Student stu; + if (stup == nullptr) { + stu = Student(this->studentNo); + } + else { + stu = *stup; + } + stu.toCsv(csv); + csv << score[0] << "," << score[1] << "," << score[2] << "," << score[3] << "," << score[4] << "," << score[5] << "," << score[6] << "," << score[7] << "," << score[8] << "," << sum << ","; +} +Item::Item(ifstream& csv, int stuNoColumn,int scoreColumn[]) { + string line, tmp; + vector tmpvector; + sum = 0; + if (!getline(csv,line)) { + studentNo = -1; + return; + } + stringstream linestream(line); + while (getline(linestream, tmp, ',')) { + tmpvector.push_back(tmp); + }; + try { + studentNo = stoi(tmpvector.at(stuNoColumn-1)); + } + catch (const exception& e) { + studentNo = 0; + } + for (auto i = 0; i < 9; i++) { + try { + score[i] = stoi(tmpvector.at(scoreColumn[i]-1)); + } + catch (const exception& e) { + score[i] = 0; + } + sum += score[i]; + } +} diff --git a/Item.h b/Item.h new file mode 100644 index 0000000..1e64129 --- /dev/null +++ b/Item.h @@ -0,0 +1,32 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include +using namespace std; +class Item { +public: + Item(long long int studentNo, double inscore[]); + Item(ifstream& csv, int stuNoColumn, int scoreColumn[]); + Item(); + + bool operator>(const Item& i) const; + bool operator<(const Item& i) const; + long long int getStuNo() const; + bool stuNoEqual(const Item& i) const; + static void dspHeader(); + static void dspHeader(int w); + void dsp() const; + void dsp(int w) const; + static void toCsvHeader(ofstream& csv); + void toCsv(ofstream& csv) const; + + virtual ~Item() {} +private: + long long int studentNo; + double score[9]; + double sum; +}; \ No newline at end of file diff --git a/Manager.cpp b/Manager.cpp new file mode 100644 index 0000000..3a08e31 --- /dev/null +++ b/Manager.cpp @@ -0,0 +1,907 @@ +#include "Manager.h" +#include"Exceptions.h" +#pragma warning(disable:4996) +Manager::Manager() { + centeredPrint("##########################################"); + centeredPrint("## 学生成绩管理系统 ##"); + centeredPrint("##########################################"); + cout << endl; + centeredPrint("加载中..."); + + ifstream numsin("nums.bin", ios::in, ios::binary); + if (!numsin.good()) { + ExamNum = 0; + StudentNum = 0; + numsin.close(); + return; + } + numsin.read((char*)&StudentNum, sizeof(int)); + numsin.read((char*)&ExamNum, sizeof(int)); + numsin.close(); + ifstream studentsin("students.bin", ios::in, ios::binary); + Student tmpstu; + for (int i = 0; i < StudentNum; i++) { + studentsin.read((char*)&tmpstu, sizeof(Student)); + Students.push_back(tmpstu); + } + studentsin.close(); + ifstream examsin("examsaves.bin", ios::in, ios::binary); + Examsave tmpexam; + for (int i = 0; i < ExamNum; i++) { + examsin.read((char*)&tmpexam, sizeof(Examsave)); + auto sp1 = make_shared(&tmpexam); + Exams.push_back(sp1); + } + examsin.close(); + + cout << endl; + centeredPrint("欢迎使用!"); +} +Manager::~Manager() { + centeredPrint("保存中..."); + ofstream examsout("examsaves.bin", ios::out, ios::binary); + for (auto i = Exams.begin(); i < Exams.end(); i++) { + (*i)->saveAll(examsout); + } + ExamNum = Exams.size(); + examsout.close(); + ofstream studentsout("students.bin", ios::out, ios::binary); + for (auto i = Students.begin(); i < Students.end(); i++) { + studentsout.write((char*)&(*i), sizeof(Student)); + } + StudentNum = Students.size(); + studentsout.close(); + ofstream numsout("nums.bin", ios::out, ios::binary); + numsout.write((char*)&StudentNum, sizeof(int)); + numsout.write((char*)&ExamNum, sizeof(int)); + numsout.close(); + centeredPrint("已保存!"); +} +void Manager::mainLoop() { + + while (1) { + try { + switch (status) { + case 0: + welcomePage(); + break; + case 1: + stuPage(); + break; + case 11: + stuDspPage(); + break; + case 12: + stuAddPage(); + break; + case 13: + stuSearchPage(); + break; + case 14: + stuEdtRmvPage(); + break; + case 15: + stuExportPage(); + break; + case 16: + stuImportPage(); + break; + case 2: + examPage(); + break; + case 21: + examAddPage(); + break; + case 22: + examChoosePage(); + break; + case 23: + examSubPage(); + break; + case 231: + examViewPage(); + break; + case 232: + examExportPage(); + break; + case 233: + examAddRowPage(); + break; + case 234: + examDelRowPage(); + break; + case 235: + examNamePage(); + break; + case 236: + examImportPage(); + break; + case 237: + examRmvPage(); + break; + case 3: + stuPfmPage(); + break; + } + system("cls"); + if (status == -1) + break; + } + catch (const InputError& e) { + system("cls"); + cerr << e.what() << endl; + cin.clear(); + cin.ignore(1024,'\n'); + goBack(); + } + catch (const FileError& e) { + system("cls"); + cerr << e.what() << endl; + goBack(); + } + catch (const IndexError& e) { + system("cls"); + cerr << e.what() << endl; + goBack(); + } + } + + + +} +void Manager::goBack() { + status /= 10; +} +void Manager::centeredPrint(const string& content) { + HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); + CONSOLE_SCREEN_BUFFER_INFO bInfo; + GetConsoleScreenBufferInfo(hOutput, &bInfo); + int dwSizeX = bInfo.dwSize.X, dwSizeY = bInfo.dwSize.Y; + int cursorX = bInfo.dwCursorPosition.X, cursorY = bInfo.dwCursorPosition.Y; + int len = content.length(); + COORD pos; + pos.X = (dwSizeX - len) / 2; + pos.Y = cursorY; + SetConsoleCursorPosition(hOutput, pos); + cout << content << endl; +} +Student* Manager::searchByNo(long long int studentNo) { + for (auto i = Students.begin(); i < Students.end(); i++) { + if (i->stuNoEqual(studentNo)) { + return &(*i); + } + } + return nullptr; +} +//status 0 +void Manager::welcomePage() { + char choice = '0'; + cout << "主菜单" << endl; + cout << "请选择" << endl; + cout << "1: 学生信息管理" << endl; + cout << "2: 考试信息" << endl; + cout << "3: 学生成绩查询" << endl; + cout << "q: 退出" << endl; + cin >> choice; + switch (choice) { + case '1': + status = 1; + break; + case '2': + status = 2; + break; + case '3': + status = 3; + break; + case 'q': + case 'Q': + status = -1; + break; + } +} +//status 1 +void Manager::stuPage() { + char choice = '0'; + cout << "主菜单-学生" << endl; + cout << "请选择" << endl; + cout << "1: 全部学生信息" << endl; + cout << "2: 添加新学生" << endl; + cout << "3: 学生信息搜索" << endl; + cout << "4: 编辑/删除已有学生" << endl; + cout << "5: 将全部学生信息导出到CSV" << endl; + cout << "6: 从CSV导入学生信息" << endl; + cout << "b: 返回" << endl; + cin >> choice; + switch (choice) { + case '1': + status = 11; + break; + case '2': + status = 12; + break; + case '3': + status = 13; + break; + case '4': + status = 14; + break; + case '5': + status = 15; + break; + case '6': + status = 16; + break; + case 'b': + case 'B': + goBack(); + } +} +//status 11 +void Manager::stuDspPage() { + cout << "主菜单-学生-信息查看" << endl; + cout << setw(6) << "编号"; + Student::dspHeader(); + cout << endl; + int count = 1; + for (auto student = Students.begin(); student < Students.end(); student++) { + cout << setw(6) << count++; + student->dsp(); + cout << endl; + } + string tmp; + cout << endl << "b: 返回" << endl; + cin >> tmp; + goBack(); +} +//status 12 +void Manager::stuAddPage() { + char choice = '0'; + cout << "主菜单-学生-添加" << endl; + int year; + int selectionNo; + int classNo; + char name[100]; + cout << "姓名:" << endl; + do { + cin.getline(name, 100); + } while (name[0] == '\0'); + cout << "入学年份:" << endl; + cin >> year; + cout << "选科组合:" << endl; + cin >> selectionNo; + cout << "班级:" << endl; + cin >> classNo; + if (!cin.good()) { + throw InputError("输入字符非法!"); + } + Students.push_back(Student(year, selectionNo, classNo, name)); + cout << "已添加!" << endl; + string tmp; + cout << endl << "b: 返回" << endl; + cin >> tmp; + goBack(); +} +//status 13 +void Manager::stuSearchPage() { + char choice = '0'; + cout << "主菜单-学生-搜索" << endl; + cout << "请选择:" << endl; + cout << "1: 按学号搜索" << endl; + cout << "2: 按姓名搜索" << endl; + cout << "3: 按班级搜索" << endl; + cout << "4: 按选科组合搜索" << endl; + cout << "5: 按入学年份搜索" << endl; + cout << "b: 返回" << endl; + cin >> choice; + vector result; + int enrollmentYear; + switch (choice) { + case '1': + long long int inputNo; + cout << "请输入学号:"; + cin >> inputNo; + if (!cin.good()) { + throw InputError("输入字符非法!"); + } + for (auto stu = Students.begin(); stu < Students.end(); stu++) { + if (stu->stuNoEqual(inputNo)) { + result.push_back(*stu); + } + } + break; + case '2': + char inputName[100]; + cout << "请输入学生姓名:"; + do { + cin.getline(inputName, 100); + } while (inputName[0] == '\0'); + for (auto stu = Students.begin(); stu < Students.end(); stu++) { + if (stu->nameEqual(inputName)) { + result.push_back(*stu); + } + } + break; + case '3': + int inputClassNo; + cout << "请输入入学年份:"; + cin >> enrollmentYear; + cout << "请输入班级:"; + cin >> inputClassNo; + if (!cin.good()) { + throw InputError("输入字符非法!"); + } + for (auto stu = Students.begin(); stu < Students.end(); stu++) { + if (stu->clsNoEqual(inputClassNo) && stu->yearEqual(enrollmentYear)) { + result.push_back(*stu); + } + } + break; + case '4': + int inputSelectionNo; + cout << "请输入入学年份:"; + cin >> enrollmentYear; + cout << "请输入选科组合:"; + cin >> inputSelectionNo; + if (!cin.good()) { + throw InputError("输入字符非法!"); + } + for (auto stu = Students.begin(); stu < Students.end(); stu++) { + if (stu->slcNoEqual(inputSelectionNo) && stu->yearEqual(enrollmentYear)) { + result.push_back(*stu); + } + } + break; + case '5': + cout << "请输入入学年份:"; + cin >> enrollmentYear; + if (!cin.good()) { + throw InputError("输入字符非法!"); + } + for (auto stu = Students.begin(); stu < Students.end(); stu++) { + if (stu->yearEqual(enrollmentYear)) { + result.push_back(*stu); + } + } + break; + case 'b': + case 'B': + goBack(); + } + if (status != 1) { + cout << setw(6) << "编号"; + Student::dspHeader(); + cout << endl; + int count = 1; + for (auto student = result.begin(); student < result.end(); student++) { + cout << setw(6) << count++; + student->dsp(); + cout << endl; + } + cout << endl; + if (result.size() == 0) { + cout << "未找到符合条件的学生" << endl; + } + cout << "b: 返回" << endl; + string tmp; + cin >> tmp; + goBack(); + } +} +//status 14 +void Manager::stuEdtRmvPage() { + int inputNo; + string tmp; + cout << "主菜单-学生-编辑/删除" << endl; + cout << "请输入学号:"; + cin >> inputNo; + if (!cin.good()) { + throw InputError("输入字符非法!"); + } + auto it = Students.end(); + for (auto stu = Students.begin(); stu < Students.end(); stu++) { + if (stu->stuNoEqual(inputNo)) { + it = stu; + } + } + if (it == Students.end()) { + cout << "查无此人" << endl; + cout << "b: 返回" << endl; + cin >> tmp; + goBack(); + } + else { + char choice; + cout << "1: 编辑学生信息" << endl; + cout << "2: 删除" << endl; + cin >> choice; + Student::dspHeader(); + cout << endl; + it->dsp(); + cout << endl; + if (choice == '1') { + + int year; + int selectionNo; + int classNo; + char name[100]; + cout << "姓名:" << endl; + do { + cin.getline(name, 100); + } while (name[0] == '\0'); + cout << "入学年份:" << endl; + cin >> year; + cout << "选科组合:" << endl; + cin >> selectionNo; + cout << "班级:" << endl; + cin >> classNo; + if (!cin.good()) { + throw InputError("输入字符非法!"); + } + it->setInfo(year, selectionNo, classNo, name); + cout << "已修改" << endl; + } + else if (choice == '2') { + cout << "删除上述学生?(Y(是)/N(否))" << endl; + char yorn; + cin >> yorn; + if (yorn == 'y' || yorn == 'Y') { + Students.erase(it); + } + cout << "已删除" << endl; + } + cout << "b: 返回" << endl; + string tmp; + cin >> tmp; + goBack(); + } +} +//status 15 +void::Manager::stuExportPage() { + cout << "主菜单-学生-导出" << endl; + string csvName; + cout << "请输入导出文件名:" << endl; + do { + getline(cin, csvName); + } while (csvName == ""); + csvName = csvName + ".csv"; + ofstream csv(csvName); + if (!csv.good()) { + throw FileError("文件创建失败!"); + } + Student::toCsvHeader(csv); + csv << '\n'; + for (auto student = Students.begin(); student < Students.end(); student++) { + student->toCsv(csv); + csv << '\n'; + } + string tmp; + cout << "导出成功" << endl; + cout << "b: 返回" << endl; + cin >> tmp; + goBack(); +} +//status 16 +void::Manager::stuImportPage() { + string fileName; + string tmp; + bool eof = false; + int firstRow=1; + int clsColumn, slcColumn, yearColumn,nameColumn; + cout << "主菜单-学生-导入" << endl; + cout << "请输入文件名称或路径,注意包含扩展名" << endl; + cin >> fileName; + if (!cin.good()) { + throw InputError("输入字符非法!"); + } + ifstream csvFile(fileName); + if (!csvFile.good()) { + throw FileError("文件打开失败!"); + } + cout << "请输入有效数据开始的行数: " << endl; + cin >> firstRow; + cout << "请输入学生姓名所在的列数: " << endl; + cin >> nameColumn; + cout << "请输入入学年份所在的列数: " << endl; + cin >> yearColumn; + cout << "请输入班号所在的列数: " << endl; + cin >> clsColumn; + cout << "请输入选科组合所在的列数: " << endl; + cin >> slcColumn; + if (!cin.good()) { + throw InputError("输入字符非法!"); + } + for (int i = 1; i < firstRow; i++) { + getline(csvFile, tmp); + } + while (!eof) { + Student tmpStu(csvFile, yearColumn, clsColumn, slcColumn, nameColumn); + if (tmpStu.stuNoEqual(-1)) { + eof = true; + + } + else if (tmpStu.stuNoEqual(0)) { + continue; + } + else { + Students.push_back(tmpStu); + } + } + + cout << "已导入" << endl; + cout << "b: 返回" << endl; + cin >> tmp; + goBack(); +} +//status 2 +void Manager::examPage() { + char choice = '0'; + cout << "主菜单-考试" << endl; + cout << setw(6) << "编号"; + Exam::dspHeader(); + for (auto exam = Exams.begin(); exam < Exams.end(); exam++) { + cout << setw(4) << distance(Exams.begin(), exam) + 1; + (*exam)->dsp(); + } + cout << endl; + cout << "请选择" << endl; + cout << "1: 添加考试" << endl; + cout << "2: 选择考试" << endl; + cout << "b: 返回" << endl; + cin >> choice; + switch (choice) { + case '1': + status = 21; + break; + case '2': + status = 22; + break; + case 'b': + case 'B': + goBack(); + break; + } +} +//status 21 +void Manager::examAddPage() { + cout << "主菜单-考试-添加" << endl; + cout << "名称:" << endl; + char name[100]; + do { + cin.getline(name, 100); + } while (name[0] == '\0'); + auto p = make_shared(name); + Exams.push_back(p); + cout << "添加成功!" << endl; + cout << "b: 返回" << endl; + string tmp; + cin >> tmp; + goBack(); +} +//status 22 +void Manager::examChoosePage() { + int examNo; + string tmp; + cout << "主菜单-考试-选择" << endl; + cout << setw(6) << "编号"; + Exam::dspHeader(); + for (auto exam = Exams.begin(); exam < Exams.end(); exam++) { + cout << setw(6) << distance(Exams.begin(), exam) + 1; + (*exam)->dsp(); + } + cout << endl; + cout << "编号:" << endl; + cin >> examNo; + if (!cin.good()) { + throw InputError("输入字符非法!"); + } + examNo--; + if (examNo >= 0 && examNo < Exams.size()) { + currentExam = Exams.begin() + examNo; + + status = 23; + } + else { + throw IndexError("编号无效!"); + } +} +//status 23 +void Manager::examSubPage() { + cout << "主菜单-考试-"; + (*currentExam)->dspName(); + cout << endl; + + cout << "请选择:" << endl; + cout << "1: 查看全部成绩" << endl; + cout << "2: 导出为CSV" << endl; + cout << "3: 新增成绩" << endl; + cout << "4: 删除成绩" << endl; + cout << "5: 修改考试名称" << endl; + cout << "6: 从CSV导入" << endl; + cout << "7: 删除此考试及其所有成绩信息" << endl; + cout << "b: 返回" << endl; + char choice = '0'; + cin >> choice; + switch (choice) { + case '1': + status = 231; + break; + case '2': + status = 232; + break; + case '3': + status = 233; + break; + case '4': + status = 234; + break; + case '5': + status = 235; + break; + case '6': + status = 236; + break; + case '7': + status = 237; + break; + case 'b': + case 'B': + goBack(); + } +} +//status 231 +void Manager::examViewPage() { + + cout << "主菜单-考试-"; + (*currentExam)->dspName(); + cout << "-查看" << endl; + Item::dspHeader(); + cout <dspItems(); + string tmp; + cout << endl << "b: 返回" << endl; + cin >> tmp; + goBack(); +} +//status 232 +void Manager::examExportPage() { + + string csvName; + + cout << "主菜单-考试-"; + (*currentExam)->dspName(); + cout << "-导出" << endl; + cout << "请输入导出文件名:" << endl; + do { + getline(cin, csvName); + } while (csvName == ""); + csvName = csvName + ".csv"; + ofstream csv(csvName); + if (!csv.good()) { + throw FileError("文件创建失败!"); + } + Item::toCsvHeader(csv); + csv << "名次" << endl; + (*currentExam)->toCsvItems(csv); + csv.close(); + cout << "导出完成" << endl; + string tmp; + cout << endl << "b: 返回" << endl; + cin >> tmp; + goBack(); +} +//status 233 +void Manager::examAddRowPage() { + long long int studentNo; + double score[9]; + char yorn; + + cout << "主菜单-考试-"; + (*currentExam)->dspName(); + cout << "-新增成绩" << endl; + + cout << "学号:" << endl; + cin >> studentNo; + if (!cin.good()) { + throw InputError("输入字符非法!"); + } + if ((*currentExam)->itemExists(studentNo)) { + cout << "学号" << studentNo << "的成绩已存在, 是否覆盖? (Y(是)/N(否))" << endl; + cin >> yorn; + if (yorn != 'Y' && yorn != 'y') { + status = 23; + return; + } + } + cout << "数学:" << endl; + cin >> score[0]; + cout << "语文:" << endl; + cin >> score[1]; + cout << "英语:" << endl; + cin >> score[2]; + cout << "物理:" << endl; + cin >> score[3]; + cout << "化学:" << endl; + cin >> score[4]; + cout << "生物:" << endl; + cin >> score[5]; + cout << "历史:" << endl; + cin >> score[6]; + cout << "政治:" << endl; + cin >> score[7]; + cout << "地理:" << endl; + cin >> score[8]; + if (!cin.good()) { + throw InputError("输入字符非法!"); + } + (*currentExam)->addItem(studentNo, score); + cout << "已添加" << endl; + string tmp; + cout << endl << "b: 返回" << endl; + cin >> tmp; + goBack(); +} +//status 234 +void Manager::examDelRowPage() { + char yorn; + long long int studentNo; + string tmp; + + cout << "主菜单-考试-"; + (*currentExam)->dspName(); + cout << "-删除成绩" << endl; + + cout << "学号:" << endl; + cin >> studentNo; + if (!cin.good()) { + throw InputError("输入字符非法!"); + } + cout << "确认删除(Y(是)/N(否))" << endl; + cin >> yorn; + if (yorn == 'Y' || yorn == 'y') { + yorn=(*currentExam)->rmvItem(studentNo); + if (yorn) { + cout << "已删除" << endl; + } + else { + cout << "未找到" << endl; + } + } + else { + cout << "已取消" << endl; + } + cout << "b: 返回" << endl; + cin >> tmp; + goBack(); +} +//status 235 +void Manager::examNamePage() { + string tmp; + char name[100]; + cout << "主菜单-考试-"; + (*currentExam)->dspName(); + cout << "-修改名称" << endl; + cout << "新名称:" << endl; + do { + cin.getline(name, 100); + } while (name[0] == '\0'); + (*currentExam)->changeName(name); + cout << "已修改" << endl; + cout << "b: 返回" << endl; + cin >> tmp; + goBack(); +} +//status 236 +void Manager::examImportPage() { + string tmp; + string fileName; + int firstRow; + int stuNoColumn; + int scoreColumn[9]; + bool eof=false; + char name[100]; + cout << "主菜单-考试-"; + (*currentExam)->dspName(); + cout << "-导入" << endl; + cout << "注意,若此考试中已存在相同学号学生的成绩数据,从CSV导入的数据会将其覆盖" << endl; + cout << "请输入文件名称或路径,注意包含扩展名" << endl; + cin >> fileName; + ifstream csvFile(fileName); + if (!csvFile.good()) { + throw FileError("文件打开失败!"); + } + cout << "请输入有效数据开始的行数: " << endl; + cin >> firstRow; + cout << "请输入学号所在的列数:" << endl; + cin >> stuNoColumn; + cout << "请输入数学、语文、英语、物理、化学、生物、历史、政治、地理成绩所在的列数,以空格分隔" << endl; + cin >> scoreColumn[0] >> scoreColumn[1] >> scoreColumn[2] >> scoreColumn[3] >> scoreColumn[4] >> scoreColumn[5] >> scoreColumn[6] >> scoreColumn[7] >> scoreColumn[8]; + if (!cin.good()) { + throw InputError("输入字符非法!"); + } + for (int i = 1; i < firstRow; i++) { + getline(csvFile, tmp); + } + while (!eof) { + Item tmpItem(csvFile, stuNoColumn, scoreColumn); + if (tmpItem.getStuNo()==-1) { + eof = true; + } + else if(tmpItem.getStuNo()==0) { + continue; + } + else { + (*currentExam)->addItem(tmpItem); + } + } + + cout << "已导入" << endl; + cout << "b: 返回" << endl; + cin >> tmp; + goBack(); +} +//status 237 +void Manager::examRmvPage() { + string tmp; + + cout << "主菜单-考试-"; + (*currentExam)->dspName(); + cout << "-删除考试" << endl; + cout << "你确定要删除考试\""; + (*currentExam)->dspName(); + cout<< "\"吗" << endl; + cout << "输入 \"confirm\" 以确认删除" << endl; + cin >> tmp; + if (tmp == "confirm") { + (*currentExam)->rm(); + Exams.erase(currentExam); + currentExam = Exams.begin(); + goBack(); + goBack(); + cout << "已删除" << endl; + } + else { + goBack(); + cout << "已取消" << endl; + } + cout << "b: 返回" << endl; + cin >> tmp; + +} +//status 3 +void Manager::stuPfmPage() { + long long int studentNo; + cout << "主菜单-学生成绩查询" << endl; + cout << "学号:" << endl; + cin >> studentNo; + if (!cin.good()) { + throw InputError("输入字符非法!"); + } + Student::dspHeader(); + cout << endl; + if (searchByNo(studentNo) == nullptr) { + cout << setw(20) << "未找到数据" << endl; + } + else { + searchByNo(studentNo)->dsp(); + } + cout << endl << endl; + cout << "历次考试成绩:" << endl<StudentInquiry(studentNo); + (*exam)->dspName(20); + if (item == nullptr) { + cout << setw(20) << "未找到数据" << endl; + } + else { + item->dsp(0); + cout << setw(6)<<(*exam)->getStuRanking(*item)<> tmp; + goBack(); +} diff --git a/Manager.h b/Manager.h new file mode 100644 index 0000000..e261281 --- /dev/null +++ b/Manager.h @@ -0,0 +1,67 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include"Student.h" +#include"Exam.h" +using namespace std; +class Manager { +public: + Manager(); + + void mainLoop(); + void goBack(); + void centeredPrint(const string& content); + Student* searchByNo(long long int studentNo); + //status 0 + void welcomePage(); + //status 1 + void stuPage(); + //status 11 + void stuDspPage(); + //status 12 + void stuAddPage(); + //status 13 + void stuSearchPage(); + //status 14 + void stuEdtRmvPage(); + //status 15 + void stuExportPage(); + //status 16 + void stuImportPage(); + //status 2 + void examPage(); + //status 21 + void examAddPage(); + //status 22 + void examChoosePage(); + //status 23 + void examSubPage(); + //status 231 + void examViewPage(); + //status 232 + void examExportPage(); + //status 233 + void examAddRowPage(); + //status 234 + void examDelRowPage(); + //status 235 + void examNamePage(); + //status 236 + void examImportPage(); + //status 237 + void examRmvPage(); + //status 3 + void stuPfmPage(); + + virtual ~Manager(); +private: + int status = 0; + int ExamNum = 0, StudentNum = 0; + vector Students; + vector> Exams; + vector>::iterator currentExam = Exams.begin(); +}; \ No newline at end of file diff --git a/Student.cpp b/Student.cpp new file mode 100644 index 0000000..6eb1c9a --- /dev/null +++ b/Student.cpp @@ -0,0 +1,124 @@ +#include"Student.h" +#include"Manager.h" +#pragma warning(disable:4996) +using namespace std; +extern Manager mainManager; +Student::Student(int year, int selectionNo, int classNo, char name[]) :year(year), selectionNo(selectionNo), classNo(classNo), serialNo(serialNo) { + strcpy_s(this->name, name); + studentNo = infoToNo(year, selectionNo, classNo); + serialNo = studentNo % 100; +} +Student::Student(long long int studentNo) { + this->studentNo = studentNo; + strcpy(this->name, "查无此人"); + year = 0; + selectionNo = 0; + classNo = 0; + serialNo = 0; +} +Student::Student(ifstream& csv, int yearColumn, int clsColumn, int slcColumn,int nameColumn) { + string line, tmp; + vector tmpvector; + if (!getline(csv, line)) { + studentNo = -1; + return; + } + stringstream linestream(line); + while (getline(linestream, tmp, ',')) { + tmpvector.push_back(tmp); + }; + try { + year = stoi(tmpvector.at(yearColumn - 1)); + } + catch (const exception& e) { + year = 0; + } + try { + classNo = stoi(tmpvector.at(clsColumn - 1)); + } + catch (const exception& e) { + classNo = 0; + } + try { + selectionNo = stoi(tmpvector.at(slcColumn - 1)); + } + catch (const exception& e) { + selectionNo = 0; + } + strcpy(this->name, tmpvector.at(nameColumn - 1).c_str()); + if (year != 0 && classNo != 0 && selectionNo != 0) { + studentNo = infoToNo(year, selectionNo, classNo); + serialNo = studentNo % 100; + } + else { + studentNo = 0; + serialNo = 0; + } +} +void Student::dspHeader() { + cout << setw(10) << "姓名" << setw(12) << "学号" << setw(10) << "入学年份" << setw(5) << "班级" << setw(5) << "选科"; +} +void Student::dsp() const { + cout << setw(10) << name << setw(12) << studentNo << setw(10) << year << setw(5) << classNo << setw(5) << selectionNo; +} +void Student::toCsvHeader(ofstream& csv) { + csv<< "姓名,"<< "学号,"<< "入学年份,"<< "班级," << "选科,"; +} +void Student::toCsv (ofstream& csv) const { + csv << name << ',' << studentNo << ',' << year << ',' << classNo << ',' << selectionNo << ','; +} +void Student::setInfo(int year, int selectionNo, int classNo, char name[]) { + this->year = year; + this->selectionNo = selectionNo; + this->classNo = classNo; + strcpy(this->name, name); +} +bool Student::stuNoEqual(long long int studentNo) const { + if (this->studentNo == studentNo) { + return true; + } + else { + return false; + } +} +bool Student::slcNoEqual(int selectionNo) const { + if (this->selectionNo == selectionNo) { + return true; + } + else { + return false; + } +} +bool Student::clsNoEqual(int classNo) const { + if (this->classNo == classNo) { + return true; + } + else { + return false; + } +} +bool Student::nameEqual(char name[]) const { + if (strcmp(this->name, name) == 0) { + return true; + } + else { + return false; + } +} +bool Student::yearEqual(int year) const { + if (this->year == year) { + return true; + } + else { + return false; + } +} +long long int Student::infoToNo(int year, int selectionNo, int classNo) { + long long int initNo = year * 1000000 + selectionNo * 10000 + classNo * 100 + 1; + for (auto i = initNo; i < initNo + 99; i++) { + if (mainManager.searchByNo(i) == nullptr) { + return i; + } + } + return -1; +} diff --git a/Student.h b/Student.h new file mode 100644 index 0000000..3f96775 --- /dev/null +++ b/Student.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include +#include +using namespace std; + +class Student { +public: + Student(int year, int selectionNo, int classNo, char name[]); + Student(long long int studentNo); + Student(ifstream& csv, int yearColumn, int clsColumn, int slcColumn,int nameColumn); + Student(){} + + void setInfo(int year, int selectionNo, int classNo, char name[]); + bool stuNoEqual(long long int studentNo) const; + bool slcNoEqual(int selectionNo) const; + bool clsNoEqual(int classNo) const; + bool yearEqual(int year) const; + bool nameEqual(char name[]) const; + static void dspHeader(); + void dsp() const; + static void toCsvHeader(ofstream& csv); + void toCsv(ofstream& csv) const; + static long long int infoToNo(int year,int selectionNo, int classNo); + + virtual ~Student(){}; +private: + long long int studentNo; + char name[100]; + int year; + int selectionNo; + int classNo; + int serialNo; +}; diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..118fb42 --- /dev/null +++ b/main.cpp @@ -0,0 +1,8 @@ +#include"Exam.h" +#include"Student.h" +#include"Manager.h" +Manager mainManager; +using namespace std; +int main() { + mainManager.mainLoop(); +} \ No newline at end of file