Algorithm: 學生成績管理系統

 

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;
}
相關文章
相關標籤/搜索