阶段性的成果。

This commit is contained in:
unlockable
2023-06-16 23:27:17 +08:00
parent 8c4acf21e7
commit 1a0cecfb19
17 changed files with 1330 additions and 0 deletions

209
大作业/.clang-format Normal file
View File

@@ -0,0 +1,209 @@
---
Language: Cpp
# BasedOnStyle: LLVM
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: true
AlignConsecutiveBitFields:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveDeclarations:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignConsecutiveMacros:
Enabled: false
AcrossEmptyLines: false
AcrossComments: false
AlignCompound: false
PadOperators: false
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
AttributeMacros:
- __capability
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: Always
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
QualifierAlignment: Leave
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
PackConstructorInitializers: BinPack
BasedOnStyle: ''
ConstructorInitializerAllOnOneLineOrOnePerLine: false
AllowAllConstructorInitializersOnNextLine: true
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseLabels: false
IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: None
IndentExternBlock: AfterExternBlock
IndentRequiresClause: true
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertBraces: false
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
LambdaBodyIndentation: Signature
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PenaltyIndentedWhitespace: 0
PointerAlignment: Right
PPIndentWidth: -1
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
RequiresClausePosition: OwnLine
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: true
AfterOverloadedOperator: false
AfterRequiresInClause: false
AfterRequiresInExpression: false
BeforeNonEmptyParentheses: false
SpaceAroundPointerQualifiers: Default
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
BitFieldColonSpacing: Both
Standard: Latest
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 4
UseCRLF: false
UseTab: Never

53
大作业/Date.cpp Normal file
View File

@@ -0,0 +1,53 @@
#include "Date.hpp"
Date::Date() : time(0), isAny(true){};
Date::Date(const time_t &_time) : time(_time), isAny(false) {};
Date::Date(const tm &_time) : isAny(false) {
tm temp = _time;
this->time = mktime(&temp);
}
void Date::setNewDate(const time_t &newTime) {
this->time = newTime;
}
void Date::setNewDate(const tm &newTime) {
tm temp = newTime;
this->time = mktime(&temp);
}
void Date::setAny() {
this->time = 0;
this->isAny = true;
}
time_t Date::getTime() const {
return this->time;
}
std::string Date::toString() const {
char buffer[20];
strftime(buffer, 20, "%F", localtime(&this->time));
}
bool Date::operator<(const Date &otherDate) const {
return this->isAny || this->time < otherDate.time;
}
bool Date::operator>(const Date &otherDate) const {
return this->isAny || this->time > otherDate.time;
}
bool Date::operator<=(const Date &otherDate) const {
return this->isAny || this->time <= otherDate.time;
}
bool Date::operator>=(const Date &otherDate) const {
return this->isAny || this->time >= otherDate.time;
}
bool Date::operator==(const Date &otherDate) const {
return this->isAny || this->time == otherDate.time;
}

33
大作业/Date.hpp Normal file
View File

@@ -0,0 +1,33 @@
#pragma once
#include "Exceptions.hpp"
#include <ctime>
#include <string>
// Reference: https://cplusplus.com/reference/ctime
class Date {
private:
// The time stored.
time_t time;
// If this date represents "Any time".
bool isAny;
public:
Date();
Date(const time_t &_time);
Date(const tm &_time);
// Set the stored date to the argument.
void setNewDate(const time_t &newTime);
void setNewDate(const tm &newTime);
// Set the date to "any".
void setAny();
// returns the time.
time_t getTime() const;
// returns a human-readable string of the stored time.
std::string toString() const;
bool operator<(const Date &otherDate) const;
bool operator>(const Date &otherDate) const;
bool operator<=(const Date &otherDate) const;
bool operator>=(const Date &otherDate) const;
bool operator==(const Date &otherDate) const;
};

16
大作业/Exceptions.cpp Normal file
View File

@@ -0,0 +1,16 @@
#include "Exceptions.hpp"
#include <string>
BaseException::BaseException(const std::string msg) : message(msg) {};
BaseListException::BaseListException(const std::string msg) : BaseException(msg) {};
ValueError::ValueError(const std::string msg) : BaseListException(msg) {};
IndexError::IndexError(const std::string msg) : BaseListException(msg) {};
DuplicateError::DuplicateError(const std::string msg) : BaseListException(msg) {};
BaseDisplayException::BaseDisplayException(const std::string msg) : BaseException(msg) {};
PageIndexError::PageIndexError(const std::string msg) : BaseDisplayException(msg){};

37
大作业/Exceptions.hpp Normal file
View File

@@ -0,0 +1,37 @@
#pragma once
#include <string>
class BaseException {
public:
const std::string message;
BaseException(const std::string msg);
};
class BaseListException : public BaseException {
public:
BaseListException(const std::string msg);
};
class ValueError : public BaseListException {
public:
ValueError(const std::string msg);
};
class IndexError : public BaseListException {
public:
IndexError(const std::string msg);
};
class DuplicateError : public BaseListException {
public:
DuplicateError(const std::string msg);
};
class BaseDisplayException : public BaseException {
public:
BaseDisplayException(const std::string msg);
};
class PageIndexError : public BaseDisplayException {
public:
PageIndexError(const std::string msg);
};

21
大作业/ListDisplay.cpp Normal file
View File

@@ -0,0 +1,21 @@
#include "ListDisplay.hpp"
#include "Exceptions.hpp"
ListDisplay::ListDisplay(const List<BaseRecord> &_allRecords)
: allRecords(_allRecords), fromDate(), toDate(), recordNumPerPage(20),
currentPage(1), totalPage(allRecords.length() / recordNumPerPage + 1),
sortOrder(ASCENT), sortByProp(RecordID){};
bool ListDisplay::hasNext() {
return currentPage < totalPage;
}
bool ListDisplay::hasPrev() {
return currentPage > 1;
}
void ListDisplay::displayNext() {
if (!this->hasNext()) {
throw(PageIndexError("No next Page!"));
}
}

40
大作业/ListDisplay.hpp Normal file
View File

@@ -0,0 +1,40 @@
#pragma once
#include "ListE.hpp"
#include "Record.hpp"
#define ASCENT true
#define DESCENT false
enum SortBy {
RecordID,
RecordDate,
RecordCourseName,
RecordStudentID,
RecordStudentName,
RecordType
};
class ListDisplay {
private:
const List<BaseRecord> &allRecords;
List<BaseRecord> filteredRecords;
Date fromDate;
Date toDate;
int recordNumPerPage;
int currentPage;
int totalPage;
bool sortOrder;
SortBy sortByProp;
public:
ListDisplay() = delete;
ListDisplay(const List<BaseRecord> &_allRecords);
bool hasNext();
bool hasPrev();
void displayNext();
void displayPrev();
void display();
void setSortBy(SortBy _propName);
void setSortOrder(bool newOrder);
void reapplyFilter();
void setRecordNumPerPage(int count);
};

365
大作业/ListE.hpp Executable file
View File

@@ -0,0 +1,365 @@
#pragma once
#include "Exceptions.hpp"
#include "Node.hpp"
template <class E> class List {
private:
Node<E> *head;
int _length;
int getIndexInRange(int index) const;
void quickSort(
int leftBound, int rightBound,
std::function<bool(const E &, const E &)> const &isCorrentOrderFunc);
public:
List();
List(const E &newItem);
List(const E *newItemList, const int itemCount);
List(const List<E> &otherList);
~List();
// Append _newItem at last. Returns the List itself.
List<E> &append(const E &_newItem);
// Insert _newItem at index, and move all items at and after [index] 1 step.
// Throws IndexError if index is not in the range of [-_length, _length -
// 1]. Returns the List itself.
List<E> &insert(const int index, const E &_newItem);
// Pop the item at given index, default is the to pop the last one.
E pop(int index = -1);
// Remove the first occurance of target. Throws ValueError if target does
// not exist. Returns the List itself.
List<E> &remove(const E &target);
// Clear all nodes.
List<E> &clear();
// Swap the element located at index a and b. Throws IndexError if the given
// index is beyond length of the list.
List<E> &swap(int index_a, int index_b);
// Sort this list.
List<E> &
sort(std::function<bool(const E &, const E &)> const &isCorrectOrderFunc);
E &operator[](const int index);
const E &operator[](const int index) const;
List<E> &operator=(const List<E> &otherList);
int length() const;
bool contains(const E &target) const;
// Give the index of target in the list on its first appearance. Throws
// ValueError if target does not exist.
int index(const E &target) const;
// Give the reference to the target in the list on its first appearance.
E &search(const E &target);
E &search(std::function<bool(const E &)> const &isTargetFunc);
// Only retain item that matches the isTargetFunc
List<E> &filter(std::function<bool(const E &)> const &isTargetFunc);
// Returns a new filtered list.
List<E> filtered(std::function<bool(const E &)> const &isTargetFunc);
// Returns a sorted NEW list.
const List<E> sorted(std::function<bool(const E &, const E &)> const
&isCorrectOrderFunc) const;
};
template <class E> int List<E>::getIndexInRange(int index) const {
if (index < 0) {
index += this->_length;
}
if (index < 0 || index >= _length) {
throw(IndexError("Index not in range!"));
}
return index;
}
template <class E>
void List<E>::quickSort(
int leftBound, int rightBound,
std::function<bool(const E &, const E &)> const &isCorrentOrderFunc) {
if (leftBound >= rightBound) {
return;
}
int pivot = leftBound;
int left = leftBound;
int right = rightBound;
while (left < right) {
while (isCorrentOrderFunc((*this)[pivot], (*this)[right]) &&
right > left) {
right--;
}
this->swap(pivot, right);
pivot = right;
while (isCorrentOrderFunc((*this)[left], (*this)[pivot]) &&
right > left) {
left++;
}
this->swap(left, pivot);
pivot = left;
}
quickSort(leftBound, pivot - 1, isCorrentOrderFunc);
quickSort(pivot + 1, rightBound, isCorrentOrderFunc);
}
template <class E> List<E>::List() : head(NULL), _length(0){};
template <class E>
List<E>::List(const E &newItem) : head(new Node<E>(newItem)), _length(1){};
template <class E> List<E>::List(const E *newItemList, const int itemCount) {
for (int i = 0; i < itemCount; i++) {
this->append(newItemList[i]);
}
};
template <class E> List<E>::List(const List<E> &otherList) {
if (otherList.length() > 0) {
this->head = new Node<E>(otherList[0]);
this->_length = 1;
Node<E> *nextPtr = otherList.head->getNextPtr();
while (nextPtr != NULL) {
this->append((*nextPtr).getContent());
nextPtr = (*nextPtr).getNextPtr();
}
}
else {
this->head = NULL;
this->_length = 0;
}
}
template <class E> List<E>::~List() {
if (this->head != NULL) {
this->head->destruct();
}
head = NULL;
}
template <class E> List<E> &List<E>::append(const E &_newItem) {
if (this->head == NULL) {
this->head = new Node<E>(_newItem);
}
else {
this->head->getTail().setNext(new Node<E>(_newItem));
}
this->_length++;
return *this;
}
template <class E> List<E> &List<E>::insert(int index, const E &_newItem) {
index = this->getIndexInRange(index);
if (index == 0) {
this->head = new Node<E>(_newItem, this->head);
}
else {
Node<E> &prev = this->head->getByIndex(index - 1);
prev.setNext(new Node<E>(_newItem, prev.getNextPtr()));
}
this->_length++;
return *this;
}
template <class E> List<E> &List<E>::remove(const E &target) {
this->pop(this->index(target));
return *this;
}
template <class E> E List<E>::pop(int index) {
index = this->getIndexInRange(index);
Node<E> removed = this->head->getByIndex(index);
this->_length--;
if (index == 0) {
Node<E> *newHead = this->head->getNextPtr();
delete this->head;
this->head = newHead;
}
else {
Node<E> &prev = this->head->getByIndex(index - 1);
delete prev.getNextPtr();
prev.setNext(removed.getNextPtr());
}
return removed.getContent();
}
template <class E> List<E> &List<E>::clear() {
this->head->destruct();
this->head = NULL;
this->_length = 0;
return *this;
}
template <class E> List<E> &List<E>::swap(int index_a, int index_b) {
index_a = this->getIndexInRange(index_a);
index_b = this->getIndexInRange(index_b);
if (index_a == index_b) {
return *this;
}
Node<E> *tempPtr;
if (index_a == 0) {
if (index_b == 1) {
Node<E> &A = this->head->getByIndex(0);
Node<E> &B = this->head->getByIndex(1);
Node<E> *afterB = B.getNextPtr();
this->head = &B;
B.setNext(&A);
A.setNext(afterB);
}
else {
Node<E> &A = this->head->getByIndex(index_a);
Node<E> *afterA = A.getNextPtr();
Node<E> &beforeB = this->head->getByIndex(index_b - 1);
Node<E> &B = this->head->getByIndex(index_b);
Node<E> *afterB = B.getNextPtr();
this->head = &B;
beforeB.setNext(&A);
A.setNext(afterB);
B.setNext(afterA);
}
}
else {
if (index_b == index_a + 1) {
Node<E> &beforeA = this->head->getByIndex(index_a - 1);
Node<E> &A = beforeA.getByIndex(1);
Node<E> &B = A.getByIndex(1);
Node<E> *afterB = B.getNextPtr();
beforeA.setNext(&B);
B.setNext(&A);
A.setNext(afterB);
}
else {
Node<E> &beforeA = this->head->getByIndex(index_a - 1);
Node<E> &A = this->head->getByIndex(index_a);
Node<E> *afterA = A.getNextPtr();
Node<E> &beforeB = this->head->getByIndex(index_b - 1);
Node<E> &B = this->head->getByIndex(index_b);
Node<E> *afterB = B.getNextPtr();
beforeA.setNext(&B);
B.setNext(afterA);
beforeB.setNext(&A);
A.setNext(afterB);
}
}
return *this;
}
template <class E>
List<E> &List<E>::sort(
std::function<bool(const E &, const E &)> const &isCorrectOrderFunc) {
this->quickSort(0, this->_length - 1, isCorrectOrderFunc);
return *this;
}
template <class E> E &List<E>::operator[](const int index) {
return this->head->getByIndex(getIndexInRange(index)).getContent();
}
template <class E> const E &List<E>::operator[](const int index) const {
return this->head->getByIndex(getIndexInRange(index)).getContent();
}
template <class E> List<E> &List<E>::operator=(const List<E> &otherList) {
this->clear();
if (otherList.length() > 0) {
this->head = new Node<E>(otherList[0]);
this->_length = 1;
Node<E> *nextPtr = otherList->head->getNextPtr();
while (nextPtr != NULL) {
this->append((*nextPtr).getContent());
nextPtr = (*nextPtr).getNextPtr();
}
}
}
template <class E> int List<E>::length() const {
return this->_length;
}
template <class E> bool List<E>::contains(const E &target) const {
if (this->_length == 0) {
return false;
}
Node<E> *current = this->head;
do {
if (current->getContent() == target) {
return true;
}
current = current->getNextPtr();
} while (current != NULL);
return false;
}
template <class E> int List<E>::index(const E &target) const {
Node<E> *nextPtr = this->head;
int pos = 0;
while (nextPtr != NULL) {
if (nextPtr->getContent() == target) {
return pos;
}
pos++;
nextPtr = nextPtr->getNextPtr();
}
throw(ValueError("Target not found!"));
}
template <class E> E &List<E>::search(const E &target) {
Node<E> *nextPtr = this->head;
while (nextPtr != NULL) {
if (nextPtr->getContent() == target) {
return nextPtr->getContent();
}
nextPtr = nextPtr->getNextPtr();
}
throw(ValueError("Target not found!"));
}
template <class E>
E &List<E>::search(std::function<bool(const E &)> const &isTargetFunc) {
Node<E> *nextPtr = this->head;
while (nextPtr != NULL) {
if (isTargetFunc(nextPtr->getContent())) {
return nextPtr->getContent();
}
nextPtr = nextPtr->getNextPtr();
}
throw(ValueError("Target not found!"));
}
template <class E>
List<E> &List<E>::filter(std::function<bool(const E &)> const &isTargetFunc) {
if (this->_length == 0) {
return *this;
}
while (this->_length > 0 && !isTargetFunc(this->head->getContent())) {
Node<E> *newHead = this->head->getNextPtr();
delete this->head;
this->head = newHead;
this->_length--;
}
Node<E> *current = this->head;
while(current->getNextPtr() != NULL) {
if (!isTargetFunc(current->getNextPtr()->getContent())) {
Node<E> *newNext = current->getNextPtr()->getNextPtr();
delete current->getNextPtr();
current->setNext(newNext);
continue;
}
current = current->getNextPtr();
}
return *this;
}
template <class E> List<E> List<E>::filtered(std::function<bool(const E&)> const &isTargetFunc) {
return List<E>(*this).filter(isTargetFunc);
}
template <class E>
const List<E> List<E>::sorted(
std::function<bool(const E &, const E &)> const &isCorrectOrderFunc) const {
return List<E>(*this).sort(isCorrectOrderFunc);
}

19
大作业/Makefile Normal file
View File

@@ -0,0 +1,19 @@
generalArguments = -std=c++11
main.out: main.o Tools.o Exceptions.o
clang++ $(generalArguments) -g $^ -o main.out
main.o: main.cpp
clang++ $(generalArguments) -g -c main.cpp -o main.o
Exceptions.o: Exceptions.cpp
clang++ $(generalArguments) -g -c Exceptions.cpp -o Exceptions.o
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

75
大作业/Node.hpp Executable file
View File

@@ -0,0 +1,75 @@
#pragma once
#include <iostream>
template <class E> class Node {
private:
E content;
Node *nextNode;
public:
Node();
Node(E _content, Node<E> *_nextNode = NULL);
~Node();
// Returns a reference to the content.
E &getContent();
// Returns a reference to the next Node. May return NULL if this Node is the
// last one.
Node<E> *getNextPtr();
// Set the next Node _nextNode. Returns original pointer.
Node<E> *setNext(Node<E> *_nextNode);
// Returns a reference to the Tail.
Node<E> &getTail();
// Returns a reference to the Node of given index.
Node<E> &getByIndex(const int index);
// Compare the content with the argument.
bool operator==(const E &other);
// Destructs the Node itself and all the node behind it.
void destruct();
};
template <class E> Node<E>::Node() : content(0), nextNode(NULL){};
template <class E>
Node<E>::Node(E _content, Node *_nextNode)
: content(_content), nextNode(_nextNode){};
template <class E> Node<E>::~Node(){};
template <class E> E &Node<E>::getContent() {
return this->content;
}
template <class E> Node<E> *Node<E>::getNextPtr() {
return this->nextNode;
}
template <class E> Node<E> *Node<E>::setNext(Node<E> *_nextNode) {
Node<E> *temp = this->nextNode;
this->nextNode = _nextNode;
return temp;
}
template <class E> Node<E> &Node<E>::getTail() {
if (this->nextNode == NULL) {
return *this;
}
return this->nextNode->getTail();
}
template <class E> Node<E> &Node<E>::getByIndex(const int index) {
if (index == 0) {
return *this;
}
return this->nextNode->getByIndex(index - 1);
}
template <class E> bool Node<E>::operator==(const E &other) {
return this->content == other;
}
template <class E> void Node<E>::destruct() {
if (this->nextNode != NULL) {
this->nextNode->destruct();
}
delete this;
}

216
大作业/Record.cpp Normal file
View File

@@ -0,0 +1,216 @@
#include "Record.hpp"
#include "Tools.hpp"
#include <iomanip>
#include <iostream>
unsigned BaseRecord::nextRecordID = 0;
std::string BaseRecord::cutToLength(std::string str, int length) const {
if (str.length() <= length) {
return str;
}
else {
return str.substr(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){};
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){};
const unsigned BaseRecord::getRecordID() const {
return this->recordID;
}
const Date &BaseRecord::getDate() const {
return this->date;
}
const std::string BaseRecord::getCourseName() const {
return this->courseName;
}
const int BaseRecord::getStudentNumber() const {
return this->studentNumber;
}
const std::string BaseRecord::getStudentName() const {
return this->studentName;
}
void BaseRecord::promptForNewDate(bool showOriginal = true) {
time_t originTime = this->date.getTime();
tm *curDate = localtime(&originTime);
int tempInput;
if (showOriginal) {
char buffer[20];
strftime(buffer, 20, "%F", curDate);
std::cout << setoutputcolor(green) << "Current date: " << buffer
<< ". Enter 0 to retain original value." << resetOutputColor
<< std::endl;
std::cout << setoutputcolor(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::cin >> tempInput;
curDate->tm_mon = (tempInput == 0 ? curDate->tm_mon : tempInput - 1);
std::cout << setoutputcolor(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::cin >> tempInput;
curDate->tm_year = tempInput - 1900;
std::cout << setoutputcolor(blue) << "Month: " << resetOutputColor
<< std::flush;
std::cin >> tempInput;
curDate->tm_mon = tempInput - 1;
std::cout << setoutputcolor(blue) << "Day: " << resetOutputColor
<< std::flush;
std::cin >> tempInput;
curDate->tm_mday = tempInput;
}
this->date = mktime(curDate);
}
void BaseRecord::promptForNewCourseName(bool showOriginal = true) {
if (showOriginal) {
std::cout << setoutputcolor(green)
<< "Original course name: " << resetOutputColor
<< this->courseName << std::endl;
}
std::cout << "Course name: " << std::flush;
std::cin >> this->courseName;
}
void BaseRecord::promptForNewStudentInfo(bool showOriginal = true) {
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)
<< "Enter 0 to retain original value." << std::endl;
std::cout << setoutputcolor(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;
std::cin >> tempStuName;
this->studentName =
(tempStuName == "0" ? this->studentName : 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;
}
}
void BaseRecord::display() const {
std::cout << std::setfill('0') << std::setw(8) << this->recordID;
std::cout << " ";
std::cout << std::setfill(' ') << std::setw(8)
<< this->cutToLength(this->date.toString(), 8);
std::cout << " ";
std::cout << std::setfill(' ') << std::setw(15)
<< this->cutToLength(this->courseName, 15);
std::cout << " ";
std::cout << std::setfill(' ') << std::setw(8) << this->studentNumber;
std::cout << " ";
std::cout << std::setfill(' ') << std::setw(15)
<< this->cutToLength(this->studentName, 15);
std::cout << std::setfill(' ') << std::setw(10) << this->getRecordType();
std::cout << std::endl;
}
LateRecord::LateRecord(const time_t _date, const std::string _courseName,
const int _studentNumber, const std::string _studentName)
: BaseRecord(_date, _courseName, _studentNumber, _studentName){};
LateRecord::LateRecord(const unsigned _recordID, const time_t _date,
const std::string _courseName, const int _studentNumber,
const std::string _studentName)
: BaseRecord(_recordID, _date, _courseName, _studentNumber, _studentName){};
std::string LateRecord::getRecordType() const {
return "Late";
}
AbsentRecord::AbsentRecord(const time_t _date, const std::string _courseName,
const int _studentNumber,
const std::string _studentName)
: BaseRecord(_date, _courseName, _studentNumber, _studentName){};
AbsentRecord::AbsentRecord(const unsigned _recordID, const time_t _date,
const std::string _courseName,
const int _studentNumber,
const std::string _studentName)
: BaseRecord(_recordID, _date, _courseName, _studentNumber, _studentName){};
std::string AbsentRecord::getRecordType() const {
return "Absent";
}
PersonalLeaveRecord::PersonalLeaveRecord(const time_t _date,
const std::string _courseName,
const int _studentNumber,
const std::string _studentName)
: BaseRecord(_date, _courseName, _studentNumber, _studentName){};
PersonalLeaveRecord::PersonalLeaveRecord(const unsigned _recordID,
const time_t _date,
const std::string _courseName,
const int _studentNumber,
const std::string _studentName)
: BaseRecord(_recordID, _date, _courseName, _studentNumber, _studentName){};
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){};
BaseRecord &&SaveRecord::convertToRecord(const char *_courseName,
const char *_name) const {
switch (this->recordType) {
case Late:
return LateRecord(this->recordID, this->date, std::string(_courseName),
this->studentNumber, std::string(_name));
case Absent:
return AbsentRecord(this->recordID, this->date,
std::string(_courseName), this->studentNumber,
std::string(_name));
case PersonalLeave:
return PersonalLeaveRecord(this->recordID, this->date,
std::string(_courseName),
this->studentNumber, std::string(_name));
}
}

102
大作业/Record.hpp Normal file
View File

@@ -0,0 +1,102 @@
#pragma once
#include "Date.hpp"
#include <ctime>
/*
The file should be in this stucture:
int totalRecordNum
unsigned nextRecordID
SaveRecord
courseName char[]
stduentName char[]
SaveRecord
courseName char[]
*/
enum RecordType { Late, Absent, PersonalLeave };
class BaseRecord {
private:
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;
public:
static unsigned nextRecordID;
BaseRecord() = delete;
// Create new record
BaseRecord(const time_t _date, const std::string _courseName,
const int _studentNumber, const std::string _studentName);
// Read from file
BaseRecord(const unsigned _recordID, const time_t _date,
const std::string _courseName, const int _studentNumber,
const std::string _studentName);
const unsigned getRecordID() const;
const Date &getDate() const;
const std::string getCourseName() const;
const int getStudentNumber() const;
const std::string getStudentName() const;
void promptForNewDate(bool showOriginal = true);
void promptForNewCourseName(bool showOriginal = true);
void promptForNewStudentInfo(bool showOriginal = true);
void display() const;
const char *getCourseNameChar() const;
const char *getStudentNameChar() const;
virtual std::string getRecordType() const = 0;
};
class LateRecord : public BaseRecord {
public:
LateRecord(const time_t _date, const std::string _courseName,
const int _studentNumber, const std::string _studentName);
LateRecord(const unsigned _recordID, const time_t _date,
const std::string _courseName, const int _studentNumber,
const std::string _studentName);
virtual std::string getRecordType() const;
};
class AbsentRecord : public BaseRecord {
public:
AbsentRecord(const time_t _date, const std::string _courseName,
const int _studentNumber, const std::string _studentName);
AbsentRecord(const unsigned _recordID, const time_t _date,
const std::string _courseName, const int _studentNumber,
const std::string _studentName);
virtual std::string getRecordType() const;
};
class PersonalLeaveRecord : public BaseRecord {
public:
PersonalLeaveRecord(const time_t _date, const std::string _courseName,
const int _studentNumber,
const std::string _studentName);
PersonalLeaveRecord(const unsigned _recordID, const time_t _date,
const std::string _courseName, const int _studentNumber,
const std::string _studentName);
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;
};

22
大作业/Student.hpp Normal file
View File

@@ -0,0 +1,22 @@
#pragma once
#include <string>
class Student {
private:
int number;
std::string name;
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();
// Returns student name.
std::string getName();
// Set the new name (especially when reading from file)
void setName(const std::string newName);
void setName(const char *newName);
};

View File

@@ -0,0 +1,14 @@
#pragma once
#include "Date.hpp"
#include <ctime>
#include <string>
class StudentInfoManager {
private:
public:
StudentInfoManager();
StudentInfoManager(std::string fileName);
};

42
大作业/Tools.cpp Normal file
View File

@@ -0,0 +1,42 @@
#include "Tools.hpp"
setoutputcolor::setoutputcolor() : color(clear), bold(false) {};
setoutputcolor::setoutputcolor(ConsoleColors _color) : color(_color), bold(false) {};
setoutputcolor::setoutputcolor(bool _bold) : color(clear), bold(_bold) {};
setoutputcolor::setoutputcolor(ConsoleColors _color, bool _bold) : color(_color), bold(_bold) {};
std::ostream &operator<<(std::ostream &out, setoutputcolor setOutput) {
out << "\033[";
if (setOutput.color == clear) {
out << "0m";
return out;
}
if (setOutput.bold) {
out << "1";
}
else {
out << "0";
}
switch (setOutput.color) {
case red:
out << ";31m";
break;
case green:
out << ";32m";
break;
case blue:
out << ";34m";
break;
default:
out << ";0m";
break;
}
return out;
}
std::ostream &resetOutputColor(std::ostream &out) {
out << setoutputcolor();
return out;
}

22
大作业/Tools.hpp Normal file
View File

@@ -0,0 +1,22 @@
#pragma once
#include <iostream>
// Reference: https://cplusplus.com/forum/unices/36461/
enum ConsoleColors { red, green, blue, clear };
class setoutputcolor {
private:
ConsoleColors color;
bool bold;
friend std::ostream &operator<<(std::ostream &out,
setoutputcolor setOutput);
public:
setoutputcolor();
setoutputcolor(ConsoleColors _color);
setoutputcolor(bool bold);
setoutputcolor(ConsoleColors _color, bool bold);
};
std::ostream &resetOutputColor(std::ostream &out);

44
大作业/main.cpp Normal file
View File

@@ -0,0 +1,44 @@
#include "ListE.hpp"
#include "Tools.hpp"
#include <iostream>
#include <iomanip>
template <class E> void display(List<E> list) {
for (int i = 0; i < list.length(); i++) {
std::cout << list[i] << ' ';
}
std::cout << std::endl;
}
int main() {
List<int> aList;
aList.append(4);
aList.append(5);
aList.append(6);
aList.append(7);
display(aList);
aList.append(8);
aList.pop(0);
display(aList);
aList.swap(0, 3);
display(aList);
// aList.sort([=](const int &a, const int &b) { return a > b; });
// display(aList);
List<int> bList =
aList.sorted([=](const int &a, const int &b) { return a > b; });
display(bList);
bList.append(5);
display(bList);
bList.filter([=](const int &a) { return a > 6; });
display(bList);
std::cout << "hhh" << setoutputcolor(blue, true) << "aaa" << setoutputcolor(blue, false) << "bbb" << setoutputcolor() << std::endl;
return 0;
}