Hello, 大家好,我是爱吃香蕉的猴子,今天找个例子,练练C++
CStudent.h
#ifndef C_STUDENT_H
#define C_STUDENT_H
#include <string>
#include <iostream>
class CStudent
{
/* 友元函数
* 类的友元函数是定义在类外部,但有权访问类的所有私有
*(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,
*但是友元函数并不是成员函数。
*/
//operator 是C++的一个关键字,它和运算符(如=)一起使用,
//表示一个运算符重载函数,在理解时可将operator和运算符(如operator=)视为一个函数名
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
/*
友元的解释
#include <iostream>
using namespace std;
class Box
{
double width;
public:
friend void printWidth( Box box );
void setWidth( double wid );
};
// 成员函数定义
void Box::setWidth( double wid )
{
width = wid;
}
// 请注意:printWidth() 不是任何类的成员函数
void printWidth( Box box )
{
// 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员
cout << "Width of box : " << box.width << endl;
}
// 程序的主函数
int main()
{
Box box;
// 使用成员函数设置宽度
box.setWidth(10.0);
// 使用友元函数输出宽度
printWidth(box);
return 0;
}
*/
CStudent.cpp
#include <iostream>
#include <string>
#include "CStudent.h"
using namespace std;
// 学生默认id是-1,说明这暂时是一个无效的学生。
CStudent::CStudent(){
this->id = -1;
}
CStudent::~CStudent(){}
//不需要再改变的就使用const
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) {
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;
}
CStudentMg.h
#ifndef C_STUDENT_MG_H
#define C_STUDENT_MG_H
#include "CStudent.h"
#include <map>
#include <string>
using namespace std;
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
CStudentMg.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <sstream>
#include "CStudent.h"
#include "CStudentMg.h"
using namespace std;
CStudentMg::CStudentMg()
{
}
CStudentMg::~CStudentMg()
{
}
//int &b=a; //b是a的引用,加后对b操作就是对a操作!
//这里&就是一个引用,之前理解取地址,是取的逻辑地址,物理地址是指针指向的地址;
//这个实际上是C++里的形参符号,必须要在跟在数据类型的后面使用。在函数内部对形参的操作都等同于直接操作原变量。
// 增
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(map<int,CStudent> & m1, 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;
}
CMainView.h
#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
main_1.cpp
/************************************************************************/
/*
* student management 1
* v1.2
* 更加OOP的版本
* 把界面的函数,也封到CMainView里面了
*
* v1.1
* qcy
* 2016年11月28日18:50:49
*
* 分层。MVC。
*
* 1. 学生信息录入 (姓名、年龄、id)
* 2. 学生信息修改
* 3. 学生删除
* 4. 显示
* 5. 根据id查找
* 6. 保存至文件
* 7. 从文件恢复
*
/************************************************************************/
#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;
}
Code的搬运工V1.0