避免使用cin >>。

This commit is contained in:
unlockable
2023-06-24 01:22:11 +08:00
parent ab35d0d2ce
commit 69bf58e48f
5 changed files with 179 additions and 95 deletions

View File

@@ -229,11 +229,12 @@ void ListDisplay::reapplyFilter() {
}
void ListDisplay::promptForRecordID() {
unsigned targetID;
int targetID;
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Record ID to search for: " << resetOutputColor;
std::cin >> targetID;
std::cin.ignore();
<< "Record ID to search for: " << resetOutputColor << std::flush;
// std::cin >> targetID;
targetID = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
try {
this->allRecordsPtrList
.search([&](BaseRecord *const &rescordPtr) -> bool {
@@ -261,36 +262,48 @@ void ListDisplay::promptForFromDate() {
<< std::endl;
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Year: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
curDate->tm_year =
(tempInput == 0 ? curDate->tm_year : tempInput - 1900);
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Month: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
curDate->tm_mon = (tempInput == 0 ? curDate->tm_mon : tempInput - 1);
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Day: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
curDate->tm_mday = (tempInput == 0 ? curDate->tm_mday : tempInput);
}
else {
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Year: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
curDate->tm_year = tempInput - 1900;
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Month: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
curDate->tm_mon = tempInput - 1;
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Day: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
curDate->tm_mday = tempInput;
}
this->fromDate = mktime(curDate);
@@ -310,36 +323,48 @@ void ListDisplay::promptForToDate() {
<< std::endl;
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Year: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
curDate->tm_year =
(tempInput == 0 ? curDate->tm_year : tempInput - 1900);
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Month: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
curDate->tm_mon = (tempInput == 0 ? curDate->tm_mon : tempInput - 1);
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Day: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
curDate->tm_mday = (tempInput == 0 ? curDate->tm_mday : tempInput);
}
else {
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Year: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
curDate->tm_year = tempInput - 1900;
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Month: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
curDate->tm_mon = tempInput - 1;
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Day: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
curDate->tm_mday = tempInput;
}
curDate->tm_hour = 0;
@@ -364,8 +389,10 @@ void ListDisplay::promptForSearchStuID() {
<< "Enter 0 to retain original value." << std::endl;
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Student ID: " << resetOutputColor << std::flush;
std::cin >> tempStuID;
std::cin.ignore();
// std::cin >> tempStuID;
// std::cin.ignore();
tempStuID = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
this->searchForStu.setNumber(tempStuID == 0 ? this->searchForStu.getNumber()
: tempStuID);
this->reapplyFilter();
@@ -385,8 +412,9 @@ void ListDisplay::promptForSearchStuName() {
<< "Enter 0 to retain original value." << std::endl;
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Student Name: " << resetOutputColor << std::flush;
std::cin >> tempStuName;
std::cin.ignore();
// std::cin >> tempStuName;
// std::cin.ignore();
std::getline(std::cin, tempStuName);
this->searchForStu.setName(tempStuName == "0" ? this->searchForStu.getName()
: tempStuName);
this->reapplyFilter();
@@ -402,8 +430,9 @@ void ListDisplay::promptForCourseName() {
<< std::endl;
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Course name: " << resetOutputColor << std::flush;
std::cin >> tempCourseName;
std::cin.ignore();
// std::cin >> tempCourseName;
// std::cin.ignore();
std::getline(std::cin, tempCourseName);
this->searchForCourseName =
(tempCourseName == "0" ? this->searchForCourseName : tempCourseName);
this->reapplyFilter();
@@ -420,8 +449,9 @@ void ListDisplay::promptForRecordType() {
std::cout << "Choices are: 1. (L)ate, 2. (A)bsent, 3. (P)ersonal\n";
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Search for record type: " << resetOutputColor << std::flush;
std::cin >> tempIn;
std::cin.ignore();
// std::cin >> tempIn;
// std::cin.ignore();
std::getline(std::cin, tempIn);
if (tempIn == "0") {
return;
}
@@ -453,8 +483,10 @@ void ListDisplay::promptRecordNumPerPage() {
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "New record number per page: " << resetOutputColor
<< std::flush;
std::cin >> tempPerPageNum;
std::cin.ignore();
// std::cin >> tempPerPageNum;
// std::cin.ignore();
tempPerPageNum = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
if (tempPerPageNum <= 0) {
std::cout << setoutputcolor(ConsoleColorTool::red)
<< "Not a valid number! Record number per page not changed."

View File

@@ -3,14 +3,14 @@
#include <iomanip>
#include <iostream>
unsigned BaseRecord::nextRecordID = 1;
int BaseRecord::nextRecordID = 1;
BaseRecord::BaseRecord(const time_t _date, const std::string _courseName,
const int _studentNumber, const std::string _studentName)
: recordID(nextRecordID++), date(_date), courseName(_courseName),
student(_studentNumber, _studentName){};
BaseRecord::BaseRecord(const unsigned _recordID, const time_t _date,
BaseRecord::BaseRecord(const int _recordID, const time_t _date,
const std::string _courseName, const int _studentNumber,
const std::string _studentName)
: recordID(_recordID), date(_date), courseName(_courseName),
@@ -19,7 +19,7 @@ BaseRecord::BaseRecord(const unsigned _recordID, const time_t _date,
BaseRecord::~BaseRecord() {
}
const unsigned BaseRecord::getRecordID() const {
const int BaseRecord::getRecordID() const {
return this->recordID;
}
@@ -57,36 +57,48 @@ void BaseRecord::promptForNewDate(bool showOriginal) {
<< std::endl;
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Year: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
newDate.tm_year =
(tempInput == 0 ? curDate->tm_year : tempInput - 1900);
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Month: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
newDate.tm_mon = (tempInput == 0 ? curDate->tm_mon : tempInput - 1);
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Day: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
newDate.tm_mday = (tempInput == 0 ? curDate->tm_mday : tempInput);
}
else {
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Year: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
newDate.tm_year = tempInput - 1900;
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Month: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
newDate.tm_mon = tempInput - 1;
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Day: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
newDate.tm_mday = tempInput;
}
this->date = mktime(&newDate);
@@ -110,8 +122,9 @@ void BaseRecord::promptForNewCourseName(bool showOriginal) {
}
else {
std::cout << "Course name: " << std::flush;
std::cin >> this->courseName;
std::cin.ignore();
// std::cin >> this->courseName;
// std::cin.ignore();
std::getline(std::cin, courseName);
}
}
@@ -131,9 +144,10 @@ void BaseRecord::promptForNewStudentInfo(bool showOriginal) {
<< "Enter 0 to retain original value." << std::endl;
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Student ID: " << resetOutputColor << std::flush;
std::cin >> tempStuID;
std::cin.ignore();
std::cin.ignore();
// std::cin >> tempStuID;
// std::cin.ignore();
tempStuID = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
this->student.setNumber(tempStuID == 0 ? this->student.getNumber()
: tempStuID);
std::cout << setoutputcolor(ConsoleColorTool::blue)
@@ -145,14 +159,17 @@ void BaseRecord::promptForNewStudentInfo(bool showOriginal) {
else {
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Student ID: " << resetOutputColor << std::flush;
std::cin >> tempStuID;
std::cin.ignore();
// std::cin >> tempStuID;
// std::cin.ignore();
tempStuID = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
this->student.setNumber(tempStuID);
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Student Name: " << resetOutputColor << std::flush;
std::cin >> tempStuName;
// std::cin >> tempStuName;
// std::cin.ignore();
std::getline(std::cin, tempStuName);
this->student.setName(tempStuName);
std::cin.ignore();
}
}
@@ -204,7 +221,7 @@ 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,
LateRecord::LateRecord(const int _recordID, const time_t _date,
const std::string _courseName, const int _studentNumber,
const std::string _studentName)
: BaseRecord(_recordID, _date, _courseName, _studentNumber, _studentName){};
@@ -233,7 +250,7 @@ AbsentRecord::AbsentRecord(const time_t _date, const std::string _courseName,
const std::string _studentName)
: BaseRecord(_date, _courseName, _studentNumber, _studentName){};
AbsentRecord::AbsentRecord(const unsigned _recordID, const time_t _date,
AbsentRecord::AbsentRecord(const int _recordID, const time_t _date,
const std::string _courseName,
const int _studentNumber,
const std::string _studentName)
@@ -264,7 +281,7 @@ PersonalLeaveRecord::PersonalLeaveRecord(const time_t _date,
const std::string _studentName)
: BaseRecord(_date, _courseName, _studentNumber, _studentName){};
PersonalLeaveRecord::PersonalLeaveRecord(const unsigned _recordID,
PersonalLeaveRecord::PersonalLeaveRecord(const int _recordID,
const time_t _date,
const std::string _courseName,
const int _studentNumber,

View File

@@ -6,7 +6,7 @@
/*
The file should be in this stucture:
int totalRecordNum
unsigned nextRecordID
int nextRecordID
SaveRecord
courseName char[]
@@ -28,7 +28,7 @@ enum RecordType { Late, Absent, PersonalLeave, Any };
};
struct SaveRecord {
unsigned recordID;
int recordID;
time_t date;
unsigned long courseNameLength;
int studentNumber;
@@ -39,23 +39,23 @@ struct SaveRecord {
class BaseRecord {
protected:
unsigned recordID;
int recordID;
Date date;
std::string courseName;
Student student;
public:
static unsigned nextRecordID;
static int 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,
BaseRecord(const int _recordID, const time_t _date,
const std::string _courseName, const int _studentNumber,
const std::string _studentName);
virtual ~BaseRecord();
const unsigned getRecordID() const;
const int getRecordID() const;
const Date &getDate() const;
const std::string getCourseName() const;
const int getStudentNumber() const;
@@ -77,7 +77,7 @@ 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,
LateRecord(const int _recordID, const time_t _date,
const std::string _courseName, const int _studentNumber,
const std::string _studentName);
virtual ~LateRecord();
@@ -90,7 +90,7 @@ 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,
AbsentRecord(const int _recordID, const time_t _date,
const std::string _courseName, const int _studentNumber,
const std::string _studentName);
virtual ~AbsentRecord();
@@ -104,7 +104,7 @@ 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,
PersonalLeaveRecord(const int _recordID, const time_t _date,
const std::string _courseName, const int _studentNumber,
const std::string _studentName);
virtual ~PersonalLeaveRecord();

View File

@@ -148,7 +148,7 @@ void StudentInfoManager::readFile() {
}
fileObj.read((char *)&totalNum, sizeof(int));
fileObj.read((char *)&BaseRecord::nextRecordID, sizeof(unsigned));
fileObj.read((char *)&BaseRecord::nextRecordID, sizeof(int));
while (totalNum > 0 && !fileObj.rdstate()) {
fileObj.read((char *)&tempReadRecord, sizeof(SaveRecord));
@@ -206,7 +206,7 @@ void StudentInfoManager::saveFile() {
}
fileObj.write((char *)&totalNum, sizeof(int));
fileObj.write((char *)&BaseRecord::nextRecordID, sizeof(unsigned));
fileObj.write((char *)&BaseRecord::nextRecordID, sizeof(int));
Iterator<BaseRecord *> iter = this->recordPtrList.iterate();
while (iter) {
@@ -223,7 +223,6 @@ void StudentInfoManager::saveFile() {
}
void StudentInfoManager::closeFile() {
if (this->hasChangePendingSave) {
char commandLetter;
int backSpaceCount = 0;
@@ -366,18 +365,24 @@ bool StudentInfoManager::cmdNew() {
tm newDate;
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Year: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
newDate.tm_year = tempInput - 1900;
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Month: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
newDate.tm_mon = tempInput - 1;
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Day: " << resetOutputColor << std::flush;
std::cin >> tempInput;
std::cin.ignore();
// std::cin >> tempInput;
// std::cin.ignore();
tempInput = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
newDate.tm_mday = tempInput;
newDate.tm_hour = 0;
newDate.tm_min = 0;
@@ -392,8 +397,10 @@ bool StudentInfoManager::cmdNew() {
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Student ID: " << resetOutputColor << std::flush;
std::cin >> studentID;
std::cin.ignore();
// std::cin >> studentID;
// std::cin.ignore();
studentID = safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Student Name: " << resetOutputColor << std::flush;
@@ -424,8 +431,11 @@ bool StudentInfoManager::cmdRemove() {
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Record ID of which to be removed: " << resetOutputColor
<< std::endl;
std::cin >> recordIDToRemove;
std::cin.ignore();
// std::cin >> recordIDToRemove;
// std::cin.ignore();
recordIDToRemove =
safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
try {
this->recordPtrList.remove([=](BaseRecord *const &recordPtr) -> bool {
return recordPtr->getRecordID() == recordIDToRemove;
@@ -447,8 +457,11 @@ bool StudentInfoManager::cmdModify() {
std::cout << setoutputcolor(ConsoleColorTool::blue)
<< "Record ID of which to be modified: " << resetOutputColor
<< std::endl;
std::cin >> recordIDToModify;
std::cin.ignore();
// std::cin >> recordIDToModify;
// std::cin.ignore();
recordIDToModify =
safeInputNum<int>("Please input a positive integer.\n",
[](const int &num) { return num > 0; });
try {
toChangeRecordPtr = this->recordPtrList.search(
[=](BaseRecord *const &recordPtr) -> bool {
@@ -897,12 +910,10 @@ void StudentInfoManager::mainloop() {
}
else if (cmd == infoManagerCommand::home::closeFile) {
this->closeFile();
this->hasChangePendingSave = false;
this->promptForFileName();
}
else if (cmd == infoManagerCommand::home::quit) {
this->closeFile();
this->hasChangePendingSave = false;
run = false;
}
}

View File

@@ -1,5 +1,6 @@
#pragma once
#include <iostream>
#include <sstream>
// Reference: https://cplusplus.com/forum/unices/36461/
// Reference: https://isocpp.org/wiki/faq/input-output#turn-off-tty-echo
@@ -53,14 +54,17 @@ const std::string setMiddle(const std::string str, const int targetLength,
void clearScreen();
// Disables user input to be echoed back to the console. Operating system specific.
// Disables user input to be echoed back to the console. Operating system
// specific.
void disableEchoBack();
// Enables user input to be echoed back to the console. Operating system specific
// Enables user input to be echoed back to the console. Operating system
// specific
void enableEchoBack();
// Go back num characters, print num spaces, and then go back num spaces, so
// that the previous num characters are removed. Operating system specific (maybe?)
// that the previous num characters are removed. Operating system specific
// (maybe?)
void backSpace(int num);
struct termSize {
@@ -72,3 +76,23 @@ struct termSize {
const termSize getConsoleSize();
void waitForAnyInput();
template <typename T>
T safeInputNum(
std::string notValidNumberWarning = "Not a valid number, try again.\n",
std::function<bool(const T &)> const &isValidNumberFunc =
[](const T &) -> bool { return true; }) {
std::string temp;
T result;
while (true) {
std::getline(std::cin, temp);
std::stringstream tempStrStream(temp);
if (tempStrStream >> result && isValidNumberFunc(result)) {
break;
}
std::cout << notValidNumberWarning << std::flush;
}
return result;
}