尽量用OOP的方式实现。分层实现。
#ifndef C_STUDENT_H #define C_STUDENT_H #include <string> #include <iostream> class CStudent { /* friend function */ friend std::ostream & operator<<(std::ostream & os, CStudent & stu); friend std::istream & operator>>(std::istream & is, CStudent & stu); public: CStudent(); ~CStudent(); int getId() const; void setId(int val); std::string getName() const; void setName(std::string val); int getAge() const; void setAge(int val); private: int id; std::string name; int age; }; #endif再到CStu的CPP文件里,实现这些简单的函数。在CStu的构造函数中,先把stu的id设为-1,做一个无效标记。下面会提到为什么要这样做。
#include <iostream> #include <string> #include "CStudent.h" using namespace std; // 学生默认id是-1,说明这暂时是一个无效的学生。 CStudent::CStudent(){this->id = -1;} CStudent::~CStudent(){} int CStudent::getId() const { return id; } void CStudent:: setId(int val) { id = val; } std::string CStudent:: getName() const { return name; } void CStudent:: setName(std::string val) { name = val; } int CStudent:: getAge() const { return age; } void CStudent:: setAge(int val) { age = val; } std::ostream & operator<<(std::ostream & os, CStudent & stu) { // 保存的时候,千万不要把,也保存进去!不然输入的时候,非常不好解决!-_-! // ss >> x; 会失败!!有逗号!! // os<<"id: "<<stu.getId()<<", name: "<<stu.getName()<<", age: " // <<stu.getAge(); os<<stu.getId()<<" "<<stu.getName()<<" "<<stu.getAge(); return os; } std::istream & operator>>(std::istream & is, CStudent & stu) { is>>stu.id>>stu.name>>stu.age; return is; }唯一需要注意的就是在重载<<的时候。问题见代码中的注释。
这里为了开发业务类,为了让软件的功能不重不漏,我就对照着最开始的需求里的功能列表来写。见上文,一共7个功能。
这里就只有一个业务类,叫CStuMg。(Mg就是management的意思……)
和开发CStu类一样,先写头文件。
#ifndef C_STUDENT_MG_H #define C_STUDENT_MG_H #include "CStudent.h" #include <map> #include <string> class CStudentMg { public: CStudentMg(); ~CStudentMg(); // 增 CStudent addAStu(std::map<int,CStudent> & m1,CStudent & stu); // 删 bool deleteStuById(std::map<int, CStudent> & m1,const int & id); // 改 CStudent updateStu(std::map<int, CStudent> & m1, const CStudent & stu); // 查 by id CStudent findById(const std::map<int, CStudent> & m1, const int & id) const; // showAll void showAll(const std::map<int, CStudent> & m1 ) const; // save to file bool saveToFile(const std::map <int,CStudent> & m1,const std::string & pathName) const; // read from file bool readFromFile(std::map<int, CStudent> & m1, std::string path); private: }; #endif这样一来,就看得见我这个软件最后一共有哪些功能了。
#include <iostream> #include <fstream> #include <string> #include <map> #include <sstream> #include "CStudent.h" #include "CStudentMg.h" using namespace std; CStudentMg::CStudentMg() { } CStudentMg::~CStudentMg() { } // 增 CStudent CStudentMg:: addAStu(map<int,CStudent> & m1,CStudent & stu) { return stu; } // 删 bool CStudentMg:: deleteStuById(map<int, CStudent> & m1, const int & id) { bool b = false; return b; } // 改 CStudent CStudentMg:: updateStu(map<int,CStudent> & m1,const CStudent & cStu) { CStudent stu; return stu; } // 查 by id CStudent CStudentMg:: findById(const map <int, CStudent> & m1, const int & id) const{ CStudent stu ; return stu; } // showAll void CStudentMg:: showAll(const map<int,CStudent> & m1) const{ } // save to file bool CStudentMg::saveToFile(const map <int,CStudent> & m1,const string & pathName) const{ bool b = true; return b; } // read from file bool CStudentMg:: readFromFile(std::map<int,CStudent> & m1, std::string path) { bool b = true; return b; }发现了咩???其实到现在为止,就根本还没有写什么具体的业务!!!但是,软件在语法上是可以满足的。这些代码是可以编译成功的!
#ifndef C_MAIN_VIEW_H #define C_MAIN_VIEW_H #include <iostream> #include <map> #include <string> #include "CStudent.h" #include "CStudentMg.h" class CMainView { public: CMainView(); ~CMainView(); /* 欢迎 */ void welcome(); /* 显示菜单 */ void showMenu(); /* view 显示所有学生 */ void showAllStuAtView(const std::map<int, CStudent> & stu_m1); /* view层 添加一个学生 */ void addStuAtView( std::map<int, CStudent> & stu_m1 ); /* view 查找一个学生 */ void findStuAtView(const std::map<int, CStudent> & m1) ; /* view层删除一个学生 */ void deleteByIdAtView(std::map<int, CStudent> & v1); /* view层 更新一个学生 */ void updateByIdAtView(std::map<int, CStudent> & m1); /* view层 把map保存进文件 */ void saveToFileAtView(const std::map<int, CStudent> & m1, std::string pathName); /* view层 把文件中的东西导入 map */ void readFromFileAtView(std::map<int, CStudent> & m, std::string pathName); private: }; #endif然后,再到对应的CPP文件里,把函数都抄一遍……
#include "CMainView.h" CMainView::CMainView() { } CMainView::~CMainView() { } /* 欢迎 */ void CMainView:: welcome() { } /* 显示菜单 */ void CMainView:: showMenu() { } /* view 显示所有学生 */ void CMainView:: showAllStuAtView(const std::map<int, CStudent> & stu_m1 ){ } /* view层 添加一个学生 */ void CMainView:: addStuAtView( std::map<int, CStudent> & stu_m1 ){ } /* view 查找一个学生 */ void CMainView:: findStuAtView(const std::map<int, CStudent> & m1) { } /* view层删除一个学生 */ void CMainView:: deleteByIdAtView(std::map<int, CStudent> & v1) { } /* view层 更新一个学生 */ void CMainView:: updateByIdAtView(std::map<int, CStudent> & m1) { } /* view层 把vec保存进文件 */ void CMainView:: saveToFileAtView(const std::map<int, CStudent> & m1, std::string pathName) { } /* view层 把文件中的东西导入 vec */ void CMainView:: readFromFileAtView(std::map<int, CStudent> & m, std::string pathName) { }View框架也写好了。
#include <iostream> #include <string> #include <map> #include "CStudent.h" #include "CStudentMg.h" #include "CMainView.h" using namespace std; int main() { string pathName = "d:/student_manegement.txt"; map<int, CStudent> stu_v1; CMainView cView; cView.welcome(); cView.showMenu(); string operateType; cin>>operateType; while (operateType!="0") { if (operateType=="1") {// 录入 cView.addStuAtView(stu_v1); } else if(operateType=="2") { // 修改 cView.updateByIdAtView(stu_v1); } else if(operateType=="3") { // 查找 cView.findStuAtView(stu_v1); } else if (operateType=="4") { cView.deleteByIdAtView(stu_v1); } else if( operateType == "5") { // 显示所有 cView.showAllStuAtView(stu_v1); } else if( operateType=="6") { // 保存至文件 cView.saveToFileAtView(stu_v1,pathName); } else if(operateType=="7") {// 从文件读取 cView.readFromFileAtView(stu_v1,pathName); } else { cView.welcome(); cView.showMenu(); } cin>>operateType; } return 0; }至此,软件的框架就开发好了。剩下的内容,就是去把没有填上的函数体都填上。
#include "CMainView.h" CMainView::CMainView() { } CMainView::~CMainView() { } /* 欢迎 */ void CMainView:: welcome() { system("cls"); std::cout<<"欢迎来到xxx大系统"<<std::endl; } /* 显示菜单 */ void CMainView:: showMenu() { std::cout<<"\n"; std::cout<<"操作步骤"<<std::endl; std::cout<<"1. 录入"<<std::endl; std::cout<<"2. 修改"<<std::endl; std::cout<<"3. 查找"<<std::endl; std::cout<<"4. 删除"<<std::endl; std::cout<<"5. 显示所有"<<std::endl; std::cout<<"6. 保存至文件"<<std::endl; std::cout<<"7. 从文件导入"<<std::endl; std::cout<<"0. 退出"<<std::endl; std::cout<<"\n"; std::cout<<"Author:qcy"<<std::endl; std::cout<<"2016/11/28"<<std::endl; std::cout<<"\n"; std::cout<<"请选择操作:"; } /* view 显示所有学生 */ void CMainView:: showAllStuAtView(const std::map<int, CStudent> & stu_m1 ) { system("cls"); std::cout<<"id |"<<"name |"<<"age"<<std::endl; CStudentMg cStuMg; cStuMg.showAll(stu_m1); system("pause"); system("cls"); welcome(); showMenu(); } /* view层 添加一个学生 */ void CMainView:: addStuAtView( std::map<int, CStudent> & stu_m1 ) { CStudentMg cStuMg; int id; std::string name; int age; CStudent cStu; system("cls"); std::cout<<"录入\n"; std::cout<<"id:"; std::cin>>id; std::cout<<"name:"; std::cin>>name; std::cout<<"age:"; std::cin>>age; cStu.setId(id); cStu.setName(name); cStu.setAge(age); // 保存 cStuMg.addAStu(stu_m1,cStu); system("cls"); welcome(); showMenu(); } /* view 查找一个学生 */ void CMainView:: findStuAtView(const std::map<int, CStudent> & m1) { system("cls"); std::cout<<"请输入要查找学生的id"<<std::endl; int id; std::cin>>id; CStudentMg cStuMg; CStudent cStu; cStu = cStuMg.findById(m1,id); if (cStu.getId()!=-1) { std::cout<<cStu<<std::endl; } else { std::cout<<"查无此人"<<std::endl; } system("pause"); system("cls"); welcome(); showMenu(); } /* view层删除一个学生 */ void CMainView:: deleteByIdAtView(std::map<int, CStudent> & v1) { system("cls"); std::cout<<"请输入要删除的学生的id"<<std::endl; int id; std::cin>>id; CStudentMg cStuMg; bool b = cStuMg.deleteStuById(v1,id); if (b) { std::cout<<"删除成功"<<std::endl; } else { std::cout<<"查无此人"<<std::endl; } system("pause"); system("cls"); welcome(); showMenu(); } /* view层 更新一个学生 */ void CMainView:: updateByIdAtView(std::map<int, CStudent> & m1) { system("cls"); std::cout<<"请输入要修改的学生的id"<<std::endl; int id; std::cin>>id; std::string name; std::cout<<"name:"; std::cin>>name; int age; std::cout<<"age:"; std::cin>>age; CStudent cStu; cStu.setId(id); cStu.setName(name); cStu.setAge(age); CStudentMg cStuMg; CStudent cStu2 = cStuMg.updateStu(m1,cStu); if (cStu2.getId()!=-1) { std::cout<<cStu2<<std::endl; std::cout<<"修改成功"<<std::endl; } else { std::cout<<"查无此人"<<std::endl; } system("pause"); system("cls"); welcome(); showMenu(); } /* view层 把vec保存进文件 */ void CMainView:: saveToFileAtView(const std::map<int, CStudent> & m1, std::string pathName) { if (m1.begin()==m1.end()) { system("cls"); std::cout<<"还没有任何学生信息,无法保存"<<std::endl; } else { // 保存 CStudentMg cStuMg; bool b = cStuMg.saveToFile(m1,pathName); if (b) { system("cls"); std::cout<<"保存成功"<<std::endl; } else { std::cout<<"保存失败"<<std::endl; } } system("pause"); system("cls"); welcome(); showMenu(); } /* view层 把文件中的东西导入 vec */ void CMainView:: readFromFileAtView(std::map<int, CStudent> & m, std::string pathName) { system("cls"); CStudentMg cStuMg; bool b = cStuMg.readFromFile(m,pathName); if (b){ std::cout<<"读取成功"<<std::endl; } else { std::cout<<"读取失败"<<std::endl; } system("pause"); system("cls"); welcome(); showMenu(); }注意,View层是在:
#include <iostream> #include <fstream> #include <string> #include <map> #include <sstream> #include "CStudent.h" #include "CStudentMg.h" using namespace std; CStudentMg::CStudentMg() { } CStudentMg::~CStudentMg() { } // 增 CStudent CStudentMg:: addAStu(map<int,CStudent> & m1,CStudent & stu) { // 先假设id可以重复了 m1.insert(make_pair(stu.getId(),stu)); return stu; } // 删 bool CStudentMg:: deleteStuById(map<int, CStudent> & m1, const int & id) { bool b = false; map<int,CStudent> ::iterator iter; iter = m1.find(id); if (iter!=m1.end()) { m1.erase(iter); b = true; // 删除成功 } return b; } // 改 CStudent CStudentMg:: updateStu(map<int,CStudent> & m1,const CStudent & cStu) { // 迭代器是一个smart point! // 是可以通过迭代器去访问到 m1里的东西,并且做出修改的! // 除非迭代器是const迭代器 CStudent stu; int id = cStu.getId(); map<int,CStudent> :: iterator iter; iter = m1.find(id); if (iter!=m1.end()) { // 修改 iter->second = cStu; stu = cStu; // 把修改后的对象,赋值,再返回上层 } return stu; } // 查 by id CStudent CStudentMg:: findById(const map <int, CStudent> & m1, const int & id) const{ CStudent stu ; map<int,CStudent> ::const_iterator iter; iter = m1.find(id); if (iter!=m1.end()) { stu = iter->second; } return stu; } // showAll void CStudentMg:: showAll(const map<int,CStudent> & m1) const{ for (auto p : m1) { cout<<p.second<<endl; } } // save to file bool CStudentMg::saveToFile(const map <int,CStudent> & m1,const string & pathName) const{ bool b = true; //fstream ofs(pathName,ios::out+ios::binary); // 为什么不是以binary保存? fstream ofs(pathName,ios::out); if (ofs) { stringstream ss; cout<<"文件打开"<<endl; CStudent stu; for (auto p = m1.begin();p!=m1.end();p++) { stu = p->second; ss<<stu<<endl; } ofs<<ss.str(); // 注意,输出一定是 ss.str(); ofs.close(); } else { cout<<"文件打开失败"<<endl; b = false; } return b; } // read from file bool CStudentMg:: readFromFile(std::map<int,CStudent> & m1, std::string path) { bool b = true; m1.clear(); // 清掉原来的 fstream ifs(path,ios::in); if (ifs) { cout<<"文件打开"<<endl; string s; stringstream ss; while (getline(ifs,s)) // 怎么一行行地读取? { CStudent cStu; ss<<s; // cout<<ss.str(); ss>>cStu; ss.clear(); m1.insert(make_pair(cStu.getId(),cStu)); } ifs.close(); } else { cout<<"文件打开失败"<<endl; b = false; } return b; }