diff --git a/大作业/Date.cpp b/大作业/Date.cpp index 1abe538..7812307 100644 --- a/大作业/Date.cpp +++ b/大作业/Date.cpp @@ -11,10 +11,12 @@ Date::Date(const tm &_time) : isAny(false) { } void Date::setNewDate(const time_t &newTime) { + this->isAny = false; this->time = newTime; } void Date::setNewDate(const tm &newTime) { + this->isAny = false; tm temp = newTime; this->time = mktime(&temp); } @@ -29,6 +31,9 @@ time_t Date::getTime() const { } std::string Date::toString() const { + if (this->isAny) { + return "[Any]"; + } char buffer[20]; strftime(buffer, 20, "%F", localtime(&this->time)); return std::string(buffer); diff --git a/大作业/ListDisplay.cpp b/大作业/ListDisplay.cpp index 77b5dc1..5958799 100644 --- a/大作业/ListDisplay.cpp +++ b/大作业/ListDisplay.cpp @@ -1,21 +1,75 @@ #include "ListDisplay.hpp" #include "Exceptions.hpp" +#include "Tools.hpp" +#include -ListDisplay::ListDisplay(const List &_allRecords) - : allRecords(_allRecords), fromDate(), toDate(), recordNumPerPage(20), - currentPage(1), totalPage(allRecords.length() / recordNumPerPage + 1), - sortOrder(ASCENT), sortByProp(RecordID){}; +ListDisplay::ListDisplay(const List &_allRecordsPtrList) + : allRecordsPtrList(_allRecordsPtrList), fromDate(), toDate(), + searchForStu(), recordNumPerPage(20), currentPageIndex(0), + maxPageIndex(allRecordsPtrList.length() / recordNumPerPage), + sortOrder(ASCENT), sortByProp(RecordID), + tableTitleRow( + "│ " + setMiddle("Record ID", recordDisplayRowSize.recordID) + " │ " + + setMiddle("Date", recordDisplayRowSize.date) + " │ " + + setMiddle("Course Name", recordDisplayRowSize.courseName) + " │ " + + setMiddle("Stud. ID", recordDisplayRowSize.studentID) + " │ " + + setMiddle("Stud. name", recordDisplayRowSize.studentName) + " │ " + + setMiddle("Type", recordDisplayRowSize.type) + " │") { + this->filteredRecordsPtrList = + allRecordsPtrList.filtered([](BaseRecord *const &) { return true; }); +}; bool ListDisplay::hasNext() { - return currentPage < totalPage; + return currentPageIndex < maxPageIndex; } bool ListDisplay::hasPrev() { - return currentPage > 1; + return currentPageIndex > 0; } void ListDisplay::displayNext() { if (!this->hasNext()) { - throw(PageIndexError("No next Page!")); + throw(PageIndexError("No next page!")); + } + this->currentPageIndex++; + this->display(); +} + +void ListDisplay::displayPrev() { + if (!this->hasPrev()) { + throw(PageIndexError("No prev page!")); + } + this->currentPageIndex--; + this->display(); +} + +void ListDisplay::display() { + bool brightBG = true; + std::cout << setoutputcolor(ConsoleColorTool::blue) << " Search date: from " + << resetOutputColor << this->fromDate.toString() + << setoutputcolor(ConsoleColorTool::blue) << " to " + << resetOutputColor << this->toDate.toString(); + std::cout << " "; + std::cout << setoutputcolor(ConsoleColorTool::blue) + << "Search for student: ID: " << resetOutputColor + << this->searchForStu.getNumberString() + << setoutputcolor(ConsoleColorTool::blue) + << " Name: " << resetOutputColor << this->searchForStu.getName() + << "\n"; + // std::cout << setbgcolor(ConsoleColorTool::cyan); + std::cout << this->tableTitleRow << std::endl; + Iterator iter = this->filteredRecordsPtrList.iterate( + this->currentPageIndex * this->recordNumPerPage); + int i = recordNumPerPage; + while (i > 0 && iter) { + if (brightBG) { + std::cout << setbgcolor(ConsoleColorTool::lightGray); + } + iter.next()->display(); + if (brightBG) { + std::cout << resetOutputColor; + } + brightBG = !brightBG; + i--; } } \ No newline at end of file diff --git a/大作业/ListDisplay.hpp b/大作业/ListDisplay.hpp index b7486ee..6a545ad 100644 --- a/大作业/ListDisplay.hpp +++ b/大作业/ListDisplay.hpp @@ -15,19 +15,21 @@ enum SortBy { class ListDisplay { private: - const List &allRecords; - List filteredRecords; + const List &allRecordsPtrList; + List filteredRecordsPtrList; Date fromDate; Date toDate; + Student searchForStu; int recordNumPerPage; - int currentPage; - int totalPage; + // The current page index, starting from 0 + int currentPageIndex; + int maxPageIndex; bool sortOrder; SortBy sortByProp; + const std::string tableTitleRow; public: - ListDisplay() = delete; - ListDisplay(const List &_allRecords); + ListDisplay(const List &_allRecordsPtrList); bool hasNext(); bool hasPrev(); void displayNext(); diff --git a/大作业/ListE.hpp b/大作业/ListE.hpp index 8eaaa7a..9a082c4 100755 --- a/大作业/ListE.hpp +++ b/大作业/ListE.hpp @@ -33,9 +33,6 @@ public: // Swap the element located at index a and b. Throws IndexError if the given // index is beyond length of the list. List &swap(int index_a, int index_b); - // Sort this list. - List & - sort(std::function const &isCorrectOrderFunc); E &operator[](const int index); const E &operator[](const int index) const; List &operator=(const List &otherList); @@ -51,10 +48,15 @@ public: // Only retain item that matches the isTargetFunc List &filter(std::function const &isTargetFunc); // Returns a new filtered list. - List filtered(std::function const &isTargetFunc); + List filtered(std::function const &isTargetFunc) const; + // Sort this list. + List & + sort(std::function const &isCorrectOrderFunc); // Returns a sorted NEW list. const List sorted(std::function const &isCorrectOrderFunc) const; + Iterator &&iterate(); + Iterator &&iterate(int index); }; template int List::getIndexInRange(int index) const { @@ -182,6 +184,9 @@ template E List::pop(int index) { } template List &List::clear() { + if (this->_length == 0) { + return *this; + } this->head->destruct(); this->head = NULL; this->_length = 0; @@ -266,12 +271,13 @@ template List &List::operator=(const List &otherList) { if (otherList.length() > 0) { this->head = new Node(otherList[0]); this->_length = 1; - Node *nextPtr = otherList->head->getNextPtr(); + Node *nextPtr = otherList.head->getNextPtr(); while (nextPtr != NULL) { this->append((*nextPtr).getContent()); nextPtr = (*nextPtr).getNextPtr(); } } + return *this; } template int List::length() const { @@ -342,7 +348,7 @@ List &List::filter(std::function const &isTargetFunc) { } Node *current = this->head; - while(current->getNextPtr() != NULL) { + while (current->getNextPtr() != NULL) { if (!isTargetFunc(current->getNextPtr()->getContent())) { Node *newNext = current->getNextPtr()->getNextPtr(); delete current->getNextPtr(); @@ -354,7 +360,8 @@ List &List::filter(std::function const &isTargetFunc) { return *this; } -template List List::filtered(std::function const &isTargetFunc) { +template +List List::filtered(std::function const &isTargetFunc) const { return List(*this).filter(isTargetFunc); } @@ -362,4 +369,18 @@ template const List List::sorted( std::function const &isCorrectOrderFunc) const { return List(*this).sort(isCorrectOrderFunc); +} + +template +Iterator &&List::iterate() { + return std::move(Iterator(this->head)); +} + +template +Iterator &&List::iterate(int index) { + index = this->getIndexInRange(index); + if (index == 0) { + return std::move(Iterator(this->head)); + } + return std::move(Iterator(&this->head->getByIndex(index))); } \ No newline at end of file diff --git a/大作业/Makefile b/大作业/Makefile index 8cc67f7..d994bdd 100644 --- a/大作业/Makefile +++ b/大作业/Makefile @@ -1,6 +1,6 @@ -generalArguments = -std=c++11 +generalArguments = -std=c++20 -main.out: main.o Tools.o Exceptions.o Record.o Date.o +main.out: main.o Tools.o Exceptions.o Record.o Date.o Student.o ListDisplay.o clang++ $(generalArguments) -g $^ -o main.out main.o: main.cpp @@ -9,11 +9,17 @@ main.o: main.cpp Exceptions.o: Exceptions.cpp clang++ $(generalArguments) -g -c Exceptions.cpp -o Exceptions.o -Record.o: Record.cpp +Record.o: Record.cpp clang++ $(generalArguments) -g -c Record.cpp -o Record.o Date.o: Date.cpp clang++ $(generalArguments) -g -c Date.cpp -o Date.o Tools.o: Tools.cpp - clang++ $(generalArguments) -g -c Tools.cpp -o Tools.o \ No newline at end of file + clang++ $(generalArguments) -g -c Tools.cpp -o Tools.o + +ListDisplay.o: ListDisplay.cpp + clang++ $(generalArguments) -g -c ListDisplay.cpp -o ListDisplay.o + +Student.o: Student.cpp + clang++ $(generalArguments) -g -c Student.cpp -o Student.o \ No newline at end of file diff --git a/大作业/Node.hpp b/大作业/Node.hpp index 0262639..51d10dd 100755 --- a/大作业/Node.hpp +++ b/大作业/Node.hpp @@ -27,6 +27,18 @@ public: void destruct(); }; +template class Iterator { +private: + Node *current; + +public: + Iterator(Node *pos); + bool hasNext(); + // Return the same as hasNext(); + operator bool(); + E &next(); +}; + template Node::Node() : content(0), nextNode(NULL){}; template @@ -72,4 +84,23 @@ template void Node::destruct() { this->nextNode->destruct(); } delete this; +} + +template Iterator::Iterator(Node *start) : current(start){}; + +template bool Iterator::hasNext() { + return this->current != NULL; +} + +template Iterator::operator bool() { + return this->hasNext(); +} + +template E &Iterator::next() { + if (!this->hasNext()) { + throw(IndexError("Out of bound!")); + } + E &temp = this->current->getContent(); + this->current = this->current->getNextPtr(); + return temp; } \ No newline at end of file diff --git a/大作业/Record.cpp b/大作业/Record.cpp index 289d6f6..63cdd48 100644 --- a/大作业/Record.cpp +++ b/大作业/Record.cpp @@ -5,25 +5,19 @@ unsigned BaseRecord::nextRecordID = 1; -std::string BaseRecord::cutToLength(std::string str, int length) const { - if (str.length() <= length) { - return str; - } - else { - return str.substr(0, length) + "+"; - } -} - BaseRecord::BaseRecord(const time_t _date, const std::string _courseName, const int _studentNumber, const std::string _studentName) : recordID(nextRecordID++), date(_date), courseName(_courseName), - studentNumber(_studentNumber), studentName(_studentName){}; + student(_studentNumber, _studentName){}; BaseRecord::BaseRecord(const unsigned _recordID, const time_t _date, const std::string _courseName, const int _studentNumber, const std::string _studentName) : recordID(_recordID), date(_date), courseName(_courseName), - studentNumber(_studentNumber), studentName(_studentName){}; + student(_studentNumber, _studentName){}; + +BaseRecord::~BaseRecord() { +} const unsigned BaseRecord::getRecordID() const { return this->recordID; @@ -38,11 +32,11 @@ const std::string BaseRecord::getCourseName() const { } const int BaseRecord::getStudentNumber() const { - return this->studentNumber; + return this->student.getNumber(); } const std::string BaseRecord::getStudentName() const { - return this->studentName; + return this->student.getName(); } void BaseRecord::promptForNewDate(bool showOriginal) { @@ -52,34 +46,35 @@ void BaseRecord::promptForNewDate(bool showOriginal) { if (showOriginal) { char buffer[20]; strftime(buffer, 20, "%F", curDate); - std::cout << setoutputcolor(green) << "Current date: " << buffer + std::cout << setoutputcolor(ConsoleColorTool::green) + << "Current date: " << buffer << ". Enter 0 to retain original value." << resetOutputColor << std::endl; - std::cout << setoutputcolor(blue) << "Year: " << resetOutputColor - << std::flush; + std::cout << setoutputcolor(ConsoleColorTool::blue) + << "Year: " << resetOutputColor << std::flush; std::cin >> tempInput; curDate->tm_year = (tempInput == 0 ? curDate->tm_year : tempInput - 1900); - std::cout << setoutputcolor(blue) << "Month: " << resetOutputColor - << std::flush; + std::cout << setoutputcolor(ConsoleColorTool::blue) + << "Month: " << resetOutputColor << std::flush; std::cin >> tempInput; curDate->tm_mon = (tempInput == 0 ? curDate->tm_mon : tempInput - 1); - std::cout << setoutputcolor(blue) << "Day: " << resetOutputColor - << std::flush; + std::cout << setoutputcolor(ConsoleColorTool::blue) + << "Day: " << resetOutputColor << std::flush; std::cin >> tempInput; curDate->tm_mday = (tempInput == 0 ? curDate->tm_mday : tempInput); } else { - std::cout << setoutputcolor(blue) << "Year: " << resetOutputColor - << std::flush; + std::cout << setoutputcolor(ConsoleColorTool::blue) + << "Year: " << resetOutputColor << std::flush; std::cin >> tempInput; curDate->tm_year = tempInput - 1900; - std::cout << setoutputcolor(blue) << "Month: " << resetOutputColor - << std::flush; + std::cout << setoutputcolor(ConsoleColorTool::blue) + << "Month: " << resetOutputColor << std::flush; std::cin >> tempInput; curDate->tm_mon = tempInput - 1; - std::cout << setoutputcolor(blue) << "Day: " << resetOutputColor - << std::flush; + std::cout << setoutputcolor(ConsoleColorTool::blue) + << "Day: " << resetOutputColor << std::flush; std::cin >> tempInput; curDate->tm_mday = tempInput; } @@ -88,10 +83,10 @@ void BaseRecord::promptForNewDate(bool showOriginal) { void BaseRecord::promptForNewCourseName(bool showOriginal) { if (showOriginal) { - std::cout << setoutputcolor(green) + std::cout << setoutputcolor(ConsoleColorTool::green) << "Original course name: " << resetOutputColor << this->courseName << "\n" - << setoutputcolor(green) + << setoutputcolor(ConsoleColorTool::green) << "Enter 0 to retain original value." << std::endl; } std::cout << "Course name: " << std::flush; @@ -99,56 +94,86 @@ void BaseRecord::promptForNewCourseName(bool showOriginal) { } void BaseRecord::promptForNewStudentInfo(bool showOriginal) { + int tempStuID; + std::string tempStuName; if (showOriginal) { - int tempStuID; - std::string tempStuName; - std::cout << setoutputcolor(green) << "Current student info: \n" - << setoutputcolor(blue) << "Student ID: " << resetOutputColor - << this->studentNumber << "\n" - << setoutputcolor(blue) - << "Student Name: " << resetOutputColor << this->studentName - << "\n" - << setoutputcolor(green) + std::cout << setoutputcolor(ConsoleColorTool::green) + << "Current student info: \n" + << setoutputcolor(ConsoleColorTool::blue) + << "Student ID: " << resetOutputColor + << this->student.getNumber() << "\n" + << setoutputcolor(ConsoleColorTool::blue) + << "Student Name: " << resetOutputColor + << this->student.getName() << "\n" + << setoutputcolor(ConsoleColorTool::green) << "Enter 0 to retain original value." << std::endl; - std::cout << setoutputcolor(blue) << "Student ID: " << resetOutputColor - << std::flush; + std::cout << setoutputcolor(ConsoleColorTool::blue) + << "Student ID: " << resetOutputColor << std::flush; std::cin >> tempStuID; - this->studentNumber = - (tempStuID == 0 ? this->studentNumber : tempStuID); - std::cout << setoutputcolor(blue) - << "Studnet Name: " << resetOutputColor << std::flush; + this->student.setNumber(tempStuID == 0 ? this->student.getNumber() + : tempStuID); + std::cout << setoutputcolor(ConsoleColorTool::blue) + << "Student Name: " << resetOutputColor << std::flush; std::cin >> tempStuName; - this->studentName = - (tempStuName == "0" ? this->studentName : tempStuName); + this->student.setName(tempStuName == "0" ? this->student.getName() + : tempStuName); } else { - std::cout << setoutputcolor(blue) << "Student ID: " << resetOutputColor - << std::flush; - std::cin >> this->studentNumber; - std::cout << setoutputcolor(blue) - << "Studnet Name: " << resetOutputColor << std::flush; - std::cin >> this->studentName; + std::cout << setoutputcolor(ConsoleColorTool::blue) + << "Student ID: " << resetOutputColor << std::flush; + std::cin >> tempStuID; + this->student.setNumber(tempStuID); + std::cout << setoutputcolor(ConsoleColorTool::blue) + << "Student Name: " << resetOutputColor << std::flush; + std::cin >> tempStuName; + this->student.setName(tempStuName); } } void BaseRecord::display() const { - std::cout << std::setfill('0') << std::setw(8) << this->recordID; - std::cout << " | "; - std::cout << std::setfill(' ') << std::setw(12) - << this->cutToLength(this->date.toString(), 12); - std::cout << " | "; - std::cout << std::setfill(' ') << std::setw(15) - << this->cutToLength(this->courseName, 15); - std::cout << " | "; - std::cout << std::setfill(' ') << std::setw(10) << this->studentNumber; - std::cout << " | "; - std::cout << std::setfill(' ') << std::setw(15) - << this->cutToLength(this->studentName, 15); - std::cout << " | "; - std::cout << std::setfill(' ') << std::setw(10) << this->getRecordType(); + std::cout << "│ " << std::setfill('0') + << std::setw(recordDisplayRowSize.recordID - 2) << this->recordID; + std::cout << " │ "; + std::cout << std::setfill(' ') << std::setw(recordDisplayRowSize.date) + << cutToLength(this->date.toString(), recordDisplayRowSize.date); + std::cout << " │ "; + std::cout << std::setfill(' ') << std::setw(recordDisplayRowSize.courseName) + << cutToLength(this->courseName, recordDisplayRowSize.courseName); + std::cout << " │ "; + std::cout << std::setfill(' ') << std::setw(recordDisplayRowSize.studentID) + << this->student.getNumber(); + std::cout << " │ "; + std::cout << std::setfill(' ') + << std::setw(recordDisplayRowSize.studentName) + << cutToLength(this->student.getName(), + recordDisplayRowSize.studentName); + std::cout << " │ "; + std::cout << std::setfill(' ') << std::setw(recordDisplayRowSize.type) + << this->getRecordType() << " │"; std::cout << std::endl; } +void BaseRecord::displayComplete() const { + std::cout << setoutputcolor(true) << setbgcolor(ConsoleColorTool::cyan) + << "Record ID " << this->recordID << resetOutputColor << "\n"; + std::cout << setoutputcolor(ConsoleColorTool::green) + << "Date: " << resetOutputColor << this->date.toString() << "\n"; + std::cout << setoutputcolor(ConsoleColorTool::green) + << "Course name: " << resetOutputColor << this->courseName + << "\n"; + std::cout << setoutputcolor(ConsoleColorTool::green) + << "Student: " << resetOutputColor << "\n"; + std::cout << "├─" << setoutputcolor(ConsoleColorTool::blue) + << "ID: " << resetOutputColor << this->student.getNumber() + << "\n"; + std::cout << "└─" << setoutputcolor(ConsoleColorTool::blue) + << "Name: " << resetOutputColor << this->student.getName() + << "\n"; + std::cout << setoutputcolor(ConsoleColorTool::green) + << "Type: " << resetOutputColor << this->getRecordType() + << std::endl; +} + LateRecord::LateRecord(const time_t _date, const std::string _courseName, const int _studentNumber, const std::string _studentName) : BaseRecord(_date, _courseName, _studentNumber, _studentName){}; @@ -162,6 +187,17 @@ std::string LateRecord::getRecordType() const { return "Late"; } +LateRecord::operator SaveRecord() const { + return SaveRecord{.recordID = this->recordID, + .date = this->date.getTime(), + .courseNameLength = this->courseName.length(), + .studentNumber = this->student.getNumber(), + .studentNameLength = this->student.getName().length(), + .recordType = StuRecord::Late}; +} + +LateRecord::~LateRecord(){}; + AbsentRecord::AbsentRecord(const time_t _date, const std::string _courseName, const int _studentNumber, const std::string _studentName) @@ -177,6 +213,17 @@ std::string AbsentRecord::getRecordType() const { return "Absent"; } +AbsentRecord::operator SaveRecord() const { + return SaveRecord{.recordID = this->recordID, + .date = this->date.getTime(), + .courseNameLength = this->courseName.length(), + .studentNumber = this->student.getNumber(), + .studentNameLength = this->student.getName().length(), + .recordType = StuRecord::Absent}; +} + +AbsentRecord::~AbsentRecord(){}; + PersonalLeaveRecord::PersonalLeaveRecord(const time_t _date, const std::string _courseName, const int _studentNumber, @@ -194,27 +241,13 @@ std::string PersonalLeaveRecord::getRecordType() const { return "Personal"; } -SaveRecord::SaveRecord(const unsigned _recordID, const time_t _date, - const std::string &courseName, const int _studentNumber, - const std::string &studentName, RecordType _recordType) - : recordID(_recordID), date(_date), courseNameLength(courseName.length()), - studentNumber(_studentNumber), studentNameLength(studentName.length()), - recordType(_recordType){}; +PersonalLeaveRecord::operator SaveRecord() const { + return SaveRecord{.recordID = this->recordID, + .date = this->date.getTime(), + .courseNameLength = this->courseName.length(), + .studentNumber = this->student.getNumber(), + .studentNameLength = this->student.getName().length(), + .recordType = StuRecord::PersonalLeave}; +} -BaseRecord *SaveRecord::convertToRecord(const char *_courseName, - const char *_name) const { - switch (this->recordType) { - case Late: - return new LateRecord(this->recordID, this->date, - std::string(_courseName), this->studentNumber, - std::string(_name)); - case Absent: - return new AbsentRecord(this->recordID, this->date, - std::string(_courseName), this->studentNumber, - std::string(_name)); - case PersonalLeave: - return new PersonalLeaveRecord(this->recordID, this->date, - std::string(_courseName), - this->studentNumber, std::string(_name)); - } -} \ No newline at end of file +PersonalLeaveRecord::~PersonalLeaveRecord(){}; \ No newline at end of file diff --git a/大作业/Record.hpp b/大作业/Record.hpp index 7702539..d984f82 100644 --- a/大作业/Record.hpp +++ b/大作业/Record.hpp @@ -1,5 +1,6 @@ #pragma once #include "Date.hpp" +#include "Student.hpp" #include /* @@ -14,19 +15,33 @@ stduentName char[] SaveRecord courseName char[] */ - +const struct { + int recordID = 10; + int date = 10; + int courseName = 15; + int studentID = 10; + int studentName = 15; + int type = 10; +} recordDisplayRowSize; +namespace StuRecord { enum RecordType { Late, Absent, PersonalLeave }; +}; + +struct SaveRecord { + unsigned recordID; + time_t date; + unsigned long courseNameLength; + int studentNumber; + unsigned long studentNameLength; + StuRecord::RecordType recordType; +}; class BaseRecord { -private: +protected: unsigned recordID; Date date; std::string courseName; - int studentNumber; - std::string studentName; - // If the string is shorter than length, returns the string; if the string - // is longer than length, takes the first lenght - 1 letters and add a "+". - std::string cutToLength(std::string str, int length) const; + Student student; public: static unsigned nextRecordID; @@ -38,6 +53,7 @@ public: BaseRecord(const unsigned _recordID, const time_t _date, const std::string _courseName, const int _studentNumber, const std::string _studentName); + virtual ~BaseRecord(); const unsigned getRecordID() const; const Date &getDate() const; const std::string getCourseName() const; @@ -46,11 +62,12 @@ public: void promptForNewDate(bool showOriginal = true); void promptForNewCourseName(bool showOriginal = true); void promptForNewStudentInfo(bool showOriginal = true); + // Show the infomation in a line. void display() const; + // Show the infomation in multiple lines. void displayComplete() const; - const char *getCourseNameChar() const; - const char *getStudentNameChar() const; virtual std::string getRecordType() const = 0; + virtual operator SaveRecord() const = 0; }; class LateRecord : public BaseRecord { @@ -60,7 +77,9 @@ public: LateRecord(const unsigned _recordID, const time_t _date, const std::string _courseName, const int _studentNumber, const std::string _studentName); + virtual ~LateRecord(); virtual std::string getRecordType() const; + virtual operator SaveRecord() const; }; class AbsentRecord : public BaseRecord { @@ -70,7 +89,9 @@ public: AbsentRecord(const unsigned _recordID, const time_t _date, const std::string _courseName, const int _studentNumber, const std::string _studentName); + virtual ~AbsentRecord(); virtual std::string getRecordType() const; + virtual operator SaveRecord() const; }; class PersonalLeaveRecord : public BaseRecord { @@ -81,23 +102,7 @@ public: PersonalLeaveRecord(const unsigned _recordID, const time_t _date, const std::string _courseName, const int _studentNumber, const std::string _studentName); + virtual ~PersonalLeaveRecord(); virtual std::string getRecordType() const; -}; - -class SaveRecord { -private: - unsigned recordID; - time_t date; - int courseNameLength; - int studentNumber; - int studentNameLength; - RecordType recordType; - -public: - SaveRecord() = delete; - SaveRecord(const unsigned _recordID, const time_t _date, - const std::string &courseName, const int _studentNumber, - const std::string &studentName, RecordType _recordType); - BaseRecord *convertToRecord(const char *_courseName, - const char *_name) const; + virtual operator SaveRecord() const; }; \ No newline at end of file diff --git a/大作业/Student.cpp b/大作业/Student.cpp new file mode 100644 index 0000000..68c74f8 --- /dev/null +++ b/大作业/Student.cpp @@ -0,0 +1,59 @@ +#include "Student.hpp" + +Student::Student() : number(0), name(""), isAnyName(true), isAnyNumber(true) {}; + +Student::Student(const int _number, const std::string _name) : number(_number), name(_name), isAnyNumber(false), isAnyName(false) {}; + +const int Student::getNumber() const { + return this->number; +} + +const std::string Student::getNumberString() const { + if (this->isAnyNumber) { + return "[Any]"; + } + return std::to_string(this->number); +} + +const std::string Student::getName() const { + if (this->isAnyName) { + return "[Any]"; + } + return this->name; +} + +void Student::setNumber(const int newNumber) { + this->isAnyNumber = false; + this->number = newNumber; +} + +void Student::setName(const std::string newName) { + this->isAnyName = false; + this->name = newName; +} + +void Student::setAnyNumber() { + this->isAnyNumber = true; + this->number = 0; +} + +void Student::setAnyName() { + this->isAnyName = true; + this->name = ""; +} + +bool Student::matchesNumber(const Student &otherStu) const { + return this->isAnyNumber || this->number == otherStu.number; +} + +bool Student::matchesName(const Student &otherStu) const { + return this->isAnyName || this->name == otherStu.name; +} + +bool Student::matches(const Student &otherStu) const { + return this->matchesNumber(otherStu) && this->matchesName(otherStu); +} + +bool Student::operator==(const Student &otherStu) const { + return this->matches(otherStu); +} \ No newline at end of file diff --git a/大作业/Student.hpp b/大作业/Student.hpp index 9643777..bd8d561 100644 --- a/大作业/Student.hpp +++ b/大作业/Student.hpp @@ -4,19 +4,29 @@ class Student { private: int number; std::string name; + bool isAnyNumber; + bool isAnyName; public: Student(); Student(const int _number, const std::string _name); - Student(const Student &otherStudent); - // Return the student in format 'number name'. - std::string toString(); // Returns student number. - int getNumber(); + const int getNumber() const; + // Returns the string from of the number, so as to display "any" + const std::string getNumberString() const; // Returns student name. - std::string getName(); - // Set the new name (especially when reading from file) + const std::string getName() const; + // Set the new number + void setNumber(const int newNumber); + // Set the new name void setName(const std::string newName); - void setName(const char *newName); + // Set the number to "any" + void setAnyNumber(); + // Set the name to "any" + void setAnyName(); + bool matchesNumber(const Student &otherStu) const; + bool matchesName(const Student &otherStu) const; + bool matches(const Student &otherStu) const; + bool operator==(const Student &otherStu) const; }; diff --git a/大作业/Tools.cpp b/大作业/Tools.cpp index cfca06b..3efc4b0 100644 --- a/大作业/Tools.cpp +++ b/大作业/Tools.cpp @@ -1,4 +1,5 @@ #include "Tools.hpp" +using namespace ConsoleColorTool; setoutputcolor::setoutputcolor(ConsoleColors _color) : color(_color), bold(false){}; @@ -30,6 +31,9 @@ std::ostream &operator<<(std::ostream &out, setoutputcolor setOutput) { case green: out << ";32m"; break; + case brown: + out << ";33m"; + break; case blue: out << ";34m"; break; @@ -59,6 +63,9 @@ std::ostream &operator<<(std::ostream &out, setbgcolor setbg) { case green: out << "\033[7;32m"; break; + case brown: + out << "\033[7;33m"; + break; case blue: out << "\033[7;34m"; break; @@ -84,4 +91,31 @@ setbgcolor::setbgcolor(ConsoleColors _color) : color(_color){}; std::ostream &resetOutputColor(std::ostream &out) { out << setoutputcolor(clear); return out; +} + +const std::string cutToLength(const std::string str, const int length) { + if (str.length() <= length) { + return str; + } + else { + return str.substr(0, length - 3) + "..."; + } +} + +const std::string setMiddle(const std::string str, const int targetLength, char fillChar) { + if (str.length() >= targetLength) { + return cutToLength(str, targetLength); + } + int left, right; + right = (targetLength - str.length()) / 2; + left = targetLength - str.length() - right; + std::string result; + for (int i = 0; i < left; i++) { + result += fillChar; + } + result += str; + for (int i = 0; i < right; i++) { + result += fillChar; + } + return result; } \ No newline at end of file diff --git a/大作业/Tools.hpp b/大作业/Tools.hpp index 12ffadd..41efa15 100644 --- a/大作业/Tools.hpp +++ b/大作业/Tools.hpp @@ -3,28 +3,46 @@ // Reference: https://cplusplus.com/forum/unices/36461/ -enum ConsoleColors { black, red, green, blue, magenta, cyan, lightGray, clear }; +namespace ConsoleColorTool { +enum ConsoleColors { + black, + red, + green, + brown, + blue, + magenta, + cyan, + lightGray, + clear +}; +}; class setoutputcolor { private: - ConsoleColors color; + ConsoleColorTool::ConsoleColors color; bool bold; friend std::ostream &operator<<(std::ostream &out, setoutputcolor setOutput); public: - setoutputcolor(ConsoleColors _color); + setoutputcolor(ConsoleColorTool::ConsoleColors _color); setoutputcolor(bool bold); - setoutputcolor(ConsoleColors _color, bool bold); + setoutputcolor(ConsoleColorTool::ConsoleColors _color, bool bold); }; class setbgcolor { private: - ConsoleColors color; + ConsoleColorTool::ConsoleColors color; friend std::ostream &operator<<(std::ostream &out, setbgcolor setbg); public: - setbgcolor(ConsoleColors _color); + setbgcolor(ConsoleColorTool::ConsoleColors _color); }; -std::ostream &resetOutputColor(std::ostream &out); \ No newline at end of file +std::ostream &resetOutputColor(std::ostream &out); + +// If the string is shorter than length, returns the string; if the string +// is longer than length, takes the first lenght - 1 letters and add a "+". +const std::string cutToLength(const std::string str, const int length); + +const std::string setMiddle(const std::string str, const int targetLength, char fillChar = ' '); \ No newline at end of file diff --git a/大作业/main.cpp b/大作业/main.cpp index 82c644f..ff81fb3 100644 --- a/大作业/main.cpp +++ b/大作业/main.cpp @@ -1,8 +1,9 @@ +#include "ListDisplay.hpp" #include "ListE.hpp" -#include "Tools.hpp" #include "Record.hpp" -#include +#include "Tools.hpp" #include +#include template void display(List list) { for (int i = 0; i < list.length(); i++) { @@ -25,12 +26,12 @@ int main() { aList.swap(0, 3); display(aList); - // aList.sort([=](const int &a, const int &b) { return a > b; }); + // aList.sort([](const int &a, const int &b) { return a > b; }); // display(aList); List bList = - aList.sorted([=](const int &a, const int &b) { return a > b; }); + aList.sorted([](const int &a, const int &b) { return a > b; }); display(bList); @@ -38,17 +39,34 @@ int main() { display(bList); - bList.filter([=](const int &a) { return a > 6; }); + bList.filter([](const int &a) { return a > 6; }); display(bList); - std::cout << "hhh" << setoutputcolor(blue, true) << "aaa" << setoutputcolor(blue, false) << "bbb" << resetOutputColor << std::endl; - LateRecord la(125534456, "SomeCourse", 10821398, "SomeStu"); - AbsentRecord lb(2874238743, "SomeotherCourse", 10239944, "SomeotherStu"); + std::cout << "hhh" << setoutputcolor(ConsoleColorTool::blue, true) << "aaa" + << setoutputcolor(ConsoleColorTool::blue, false) << "bbb" + << resetOutputColor << std::endl; + LateRecord la(125534456, "SomeCourselonglonglonglonglong", 10821398, "SomeStu"); + AbsentRecord lb(2874238743, "SomeOtherCourse", 10239944, "SomeotherStu"); la.display(); - std::cout << setbgcolor(lightGray); + std::cout << setbgcolor(ConsoleColorTool::lightGray); lb.display(); std::cout << resetOutputColor; - la.promptForNewStudentInfo(); - la.display(); + // la.promptForNewStudentInfo(); + + // la.display(); + la.displayComplete(); + + std::cout << "------------" << std::endl; + List recordPtrList; + + recordPtrList.append(new LateRecord(122333, "hhhh", 10394, "aneiei")); + recordPtrList.append(new AbsentRecord(123994994, "aadkfk", 129939948, "adiorrr")); + recordPtrList.append(new PersonalLeaveRecord(132934949, "mumu", 129293, "s999")); + ListDisplay displayer(recordPtrList); + displayer.display(); + Iterator it = recordPtrList.iterate(); + while (it) { + delete it.next(); + } return 0; } \ No newline at end of file