C++學生成績管理系統
編寫一個統計存儲在文件中的學生成績管理程序。設學生成績以一個學生一條記錄的形式存儲在文件中。每一個學生記錄的信息有姓名﹑學號和各門功課的成績。
功能以下:
1. 求各門課程的總分﹑平均分。
2.按姓名尋找記錄並顯示。
3. 按學號尋找記錄並顯示。
4.查詢所有學生成績。
5.按總分由高到低顯示學生信息。
提示:設每位學生語文﹑數學﹑英語3門課程。主程序輸入文件名後,進入接受命令﹑執行命令處理程序循環。
按問題的要求共設5條命令:
1. 求各門課程的總分。
2.求各門課程的平均分。
3.按姓名尋找記錄並顯示。
4. 按學號尋找記錄並顯示。
5.結束命令
爲求各門課程的總分,從文件中逐一讀出學生記錄。累計各門課程的分數,待文件處理完便可獲得各門課程的總分。爲求各門課程的平均分,從文件中逐一讀出學生記錄。累計各門課程的分數。並統計學生人數,待文件處理完畢,將獲得的各門課程的平均分。按學生名字尋找學生信息的處理,首先要求輸入待尋找學生的名字,順序讀入學生記錄。凡名字與待尋找學生的名字相同的記錄在屏幕上顯示,直到文件結束。按學生學號尋找學生信息的處理,首先要求輸入待尋找學生的學號,順序讀入學生記錄。凡學號與待尋找學生的學號相同的記錄在屏幕上顯示,直到文件結束。瀏覽學生所有成績,順序讀入學生記錄。並在屏幕上顯示,直到文件結束。按總分由高到低顯示學生信息。順序讀入學生記錄並構造一個有序鏈表。而後顯示鏈表上的元素ios
/* minGW 4.8.1及以上版本編譯器下編譯 */ #include <iostream> #include <fstream> #include <string> #include <algorithm> #include <string> #include <type_traits> #include <array> enum Subject : int{ Chinese = 0, Math = 1, English = 2 }; template<typename T> typename std::remove_reference<T>::type&& my_move(T&& value)noexcept { using type = typename std::remove_reference<T>::type&&; return static_cast<type>(value); } class StudentInfo{ private: std::string name_; std::string id_; int chinese_; int math_; int english_; inline int& getChineseScore()noexcept { return (this->chinese_); } inline int getChineseScore()const noexcept { return (this->chinese_); } inline int& getMathScore()noexcept { return (this->math_); } inline int getMathScore()const noexcept { return (this->math_); } inline int& getEnglishScore()noexcept { return (this->english_); } inline int getEnglishScore()const noexcept { return (this->english_); } using array = int& (StudentInfo::*)()noexcept; using cArray = int (StudentInfo::*)()const noexcept; array functionArray[3] = {&StudentInfo::getChineseScore, &StudentInfo::getMathScore, &StudentInfo::getEnglishScore}; cArray functionCArray[3] = {static_cast<cArray>(&StudentInfo::getChineseScore), static_cast<cArray>(&StudentInfo::getMathScore), static_cast<cArray>(&StudentInfo::getEnglishScore)}; public: StudentInfo()=default; StudentInfo(const std::string& name, const std::string& id, const int& chinese=0, const int& math=0, const int& english=0); ~StudentInfo()=default; StudentInfo(const StudentInfo& other); StudentInfo(StudentInfo&& other); StudentInfo& operator=(const StudentInfo& other); StudentInfo& operator=(StudentInfo&& other); int& getScore(const Subject& obj)noexcept; int getScore(const Subject& obj)const noexcept; inline std::string& getId()noexcept { return (this->id_); } inline std::string getId()const noexcept { return (this->id_); } friend bool operator==(const StudentInfo& lh, const StudentInfo& rh)noexcept; friend std::ostream& operator<<(std::ostream& os, const StudentInfo& student); }; StudentInfo::StudentInfo(const std::string& name, const std::string& id, const int& chinese, const int& math, const int& english) :name_(name), id_(id), chinese_(chinese), math_(math), english_(english) { //constructor. } StudentInfo::StudentInfo(const StudentInfo& other) :name_(other.name_), id_(other.id_), chinese_(other.chinese_), math_(other.math_), english_(other.english_) { //copy-constructor. } StudentInfo::StudentInfo(StudentInfo&& other) :name_(my_move(other.name_)), id_(my_move(other.id_)), chinese_(my_move(other.chinese_)), math_(my_move(other.math_)), english_(my_move(other.english_)) { //move-constructor. } StudentInfo& StudentInfo::operator=(const StudentInfo& other) { this->name_ = other.name_; this->id_ = other.id_; this->chinese_ = other.chinese_; this->math_ = other.math_; this->english_ = other.english_; return *this; } StudentInfo& StudentInfo::operator=(StudentInfo&& other) { this->name_ = my_move(other.name_); this->id_ = my_move(other.id_), this->chinese_ = my_move(other.chinese_); this->math_ = my_move(other.math_), this->english_ = my_move(other.english_); return *this; } std::ostream& operator<<(std::ostream& os, const StudentInfo& student) { os<< student.name_ << " " << student.id_ << " " << student.chinese_ << " " << student.math_ << " " << student.english_; return os; } int& StudentInfo::getScore(const Subject& obj)noexcept { return (this->*functionArray[static_cast<int>(obj)])(); //注意這裏->*,由於是成員函數的指針. } int StudentInfo::getScore(const Subject& obj)const noexcept { int index = static_cast<int>(obj); return (this->*functionCArray[index])(); } bool operator==(const StudentInfo& lh, const StudentInfo& rh)noexcept { if(lh.id_ == rh.id_){ return true; } return false; } class RWFile{ private: class FindObject{ private: std::pair<std::string, std::string> getNameAndId(const std::string& sTr)noexcept //得到名字. { std::pair<std::string, std::string> nameAndID; std::string name; std::string ID; std::size_t indexS; std::size_t indexE; if(!sTr.empty()){ std::runtime_error(std::string("Cant not get data!")); } indexS = sTr.find(std::string("姓名")); indexE = sTr.find_first_of(" "); name = sTr.substr(indexS, indexE); indexS = name.find_first_of(":"); name = name.substr(indexS + 1); nameAndID.first = name; //得到名字. indexS = sTr.find(std::string("學號")); name = sTr.substr(indexS); indexS = name.find_first_of(":"); indexE = name.find_first_of(" "); ID = name.substr(indexS+1, indexE); indexE = ID.find_first_of(" "); ID = ID.substr(0, indexE); nameAndID.second = ID; //保存得到的ID. return nameAndID; } std::array<int, 3> getScore(const std::string& sTr)noexcept { std::array<int, 3> scores; //保存各個學科的成績. std::string scoreStr; std::size_t indexS; std::size_t indexE; if(!sTr.empty()){ std::runtime_error(std::string("Can not read data!")); } indexS = sTr.find_first_of(std::string("語文")); scoreStr = sTr.substr(indexS); indexS = scoreStr.find_first_of(":"); indexE = scoreStr.find_first_of(" "); scoreStr = scoreStr.substr(indexS+1, indexE); indexE = scoreStr.find_first_of(" "); scoreStr = scoreStr.substr(0, indexE); scores[0] = std::stod(scoreStr); //存儲語文成績. indexS = sTr.find_first_of(std::string("數學")); scoreStr = sTr.substr(indexS); indexS = scoreStr.find_first_of(":"); indexE = scoreStr.find_first_of(" "); scoreStr = scoreStr.substr(indexS+1, indexE); indexE = scoreStr.find_first_of(" "); scoreStr = scoreStr.substr(0, indexE); scores[1] = std::stod(scoreStr); //存儲數學成績. indexS = sTr.find_last_of(":"); scoreStr = sTr.substr(indexS+1); scores[2] = std::stod(scoreStr); //存儲英語成績. } public: FindObject()=default; ~FindObject()=default; StudentInfo operator()(const std::string& sTr) //構建學生信息. { std::pair<std::string, std::string> pair = this->getNameAndId(sTr); std::array<int, 3> array = this->getScore(sTr); StudentInfo student(pair.first, pair.second, array[0], array[1], array[2]); return student; } }; std::vector<StudentInfo> students_{}; std::string file_name_; std::ifstream read_txt_; //讀取txt文件裏的內容讀取完畢後txt文件爲空. std::ofstream write_txt_; //寫入內容到txt文件中. std::fstream stream_; //讀取文件中的內容可是不會修改原來txt中的內容. //std::pair<object, std::vector<double>> average_{}; //該學科的全部同窗的成績. //std::pair<name, std::vector<StudentInfo>> name_search_{}; //姓名索引. //std::pair<id, StudentInfo> id_search{}; //id索引 void readContents(); void closeDoc()noexcept; void saveContentToDoc()noexcept; public: using ID = std::string; using name = std::string; using object = std::string; RWFile(); RWFile(const std::string& txt); ~RWFile()=default; RWFile(const RWFile& other) = delete; RWFile& operator=(const RWFile& other) = delete; void searchObjectAverage(const Object& obj); //void searchID(const std::string& idStr); //void searchName(const std::string& nameStr); void showAllBody()const noexcept; void changeScore(const double& realScore, const std::string& id, const Object& obj); }; RWFile::RWFile() :file_name_(std::string("")) { std::cout<< "Please enter the name of t(e)xt: "<<std::endl; std::cin>> (this->file_name_); (this->stream_).open(this->file_name_); if(!(this->stream_).is_open()){ std::cout<< "There is not this text: "<< (this->file_name_)<< ". Plese enter again"<<std::endl; std::cin>>(this->file_name_); (this->stream_).open(this->file_name_); (this->stream_).close(); } this->readContents(); } RWFile::RWFile(const std::string& txt)try :file_name_(txt) { (this->stream_).open(this->file_name_); if(!(this->stream_).is_open()){ throw std::runtime_error(std::string("Please give a conrrect name!")); } (this->stream_).close(); this->readContents(); }catch(const std::runtime_error& error){ std::cout<< error.what() <<std::endl; } void RWFile::readContents() { FindObject find; std::string str; (this->read_txt_).open(this->file_name_, std::fstream::out); while(getline((this->read_txt_), str)){ //讀取txt文件. StudentInfo student = find(str); (this->students_).push_back(student); } (this->students_).shrink_to_fit(); (this->read_txt_).close(); } void RWFile::searchObjectAverage(const Subject& obj) { int totalScore; if(!(this->students_).empty()){ for(const StudentInfo& student : (this->students_)){ totalScore += (student.getScore(obj)); } } std::cout<< "This object total score: " << totalScore <<std::endl; std::cout<< "The average of this object: " << totalScore/(this->students_).size() <<std::endl; } void RWFile::changeScore(const double& realScore, const std::string& id, const Object& obj) { if(!(this->students_).empty()){ for(StudentInfo& student : (this->students_)){ if(id == student.getId()){ student.getScore(obj) = realScore; } } } this->saveContentToDoc(); } void RWFile::closeDoc()noexcept { if(!(this->stream_).is_open()){ (this->stream_).close(); } if(!(this->read_txt_).is_open()){ (this->read_txt_).close(); } if(!(this->write_txt_).is_open()){ (this->write_txt_).close(); } } void RWFile::saveContentToDoc()noexcept { (this->write_txt_).open(this->file_name_, std::ofstream::in); if((this->write_txt_).is_open() && !(this->students_).empty()){ for(const StudentInfo& info : (this->students_)){ (this->write_txt_) << info << '\n'; } } } void RWFile::showAllBody()const noexcept { if(!(this->students_).empty()){ for(const StudentInfo student : (this->students_)){ std::cout<< student <<std::endl; } } } int main() { std::string ID("013"); std::string Dir("成績.txt"); RWFile system(Dir); system.showAllBody(); system.searchObjectAverage(Object::Math); system.changeScore(150, ID, Object::Math); return 0; }