未将对象作为整体写入和读出,此种方式待再写一版。
本次是将对象中的信息拆分写入文件,再以读取每个字符的方式读取出所有文件内容。
emp.h
#ifndef EMP_H_
#define EMP_H_
// emp.h -- header file for abstr_emp class and children
#include <iostream>
#include <string>
using std::fstream;
class abstr_emp
{
private:
std::string fname; // abstr_emp's first name
std::string lname; // abstr_emp's last name
std::string job;
public:
abstr_emp();
abstr_emp(const std::string & fn, const std::string & ln,
const std::string & j);
virtual void ShowAll() const; // labels and shows all data
virtual void SetAll(); // prompts user for values
virtual void Writeall(fstream& finout);// newly added for 17-6
friend std::ostream & operator<<(std::ostream & os, const abstr_emp & e);
// just displays first and last name
virtual ~abstr_emp() = 0; // virtual base class
};
class employee : public abstr_emp
{
public:
employee();
employee(const std::string & fn, const std::string & ln,
const std::string & j);
virtual void ShowAll() const;
virtual void SetAll();
virtual void Writeall(fstream& finout);// newly added for 17-6
};
class manager : virtual public abstr_emp
{
private:
int inchargeof; // number of abstr_emps managed
protected:
// create protected methods allowing derived highfink
// visit its vitual base-classes' newly added member (comparing
// with same ancestor abstr_emp
// ******************************************//
// return value use int, but not const int,because returns a copy
// no need to concern alter original value
int InChargeOf() const { return inchargeof; } // output
int & InChargeOf() { return inchargeof; } // input
public:
manager();
manager(const std::string & fn, const std::string & ln,
const std::string & j, int ico = 0);
manager(const abstr_emp & e, int ico);
manager(const manager & m);
virtual void ShowAll() const;
virtual void SetAll();
virtual void Writeall(fstream& finout);// newly added for 17-6
};
class fink : virtual public abstr_emp
{
private:
std::string reportsto; // to whom fink reports
protected:
const std::string ReportsTo() const { return reportsto; }
std::string & ReportsTo() { return reportsto; }
public:
fink();
fink(const std::string & fn, const std::string & ln,
const std::string & j, const std::string & rpo);
fink(const abstr_emp & e, const std::string & rpo);
fink(const fink & e);
virtual void ShowAll() const;
virtual void SetAll();
virtual void Writeall(fstream& finout);// newly added for 17-6
};
class highfink : public manager, public fink // management fink
{
public:
highfink();
highfink(const std::string & fn, const std::string & ln,
const std::string & j, const std::string & rpo,
int ico);
highfink(const abstr_emp & e, const std::string & rpo, int ico);
highfink(const fink & f, int ico);
highfink(const manager & m, const std::string & rpo);
highfink(const highfink & h);
virtual void ShowAll() const;
virtual void SetAll();
virtual void Writeall(fstream& finout);// newly added for 17-6
};
#endif
emp.cpp
// implementations
#include<iostream>
#include"emp.h"
#include<fstream>
using std::cout;
using std::endl;
using std::cin;
// implementations for class abstr_emp
abstr_emp::abstr_emp()
{
fname = "default_fname";
lname = "default_lname";
job = "default_job";
}
abstr_emp::abstr_emp(const std::string & fn,
const std::string & ln,
const std::string & j) :fname(fn), lname(ln),
job(j) {}
void abstr_emp::ShowAll() const
{
cout << "Name: " << fname << " " << lname << endl
<< "Job: " << job << endl;
}
void abstr_emp::SetAll()
{
cout << "Enter first name: ";
cin >> fname;
cout << "Enter last name: ";
cin >> lname;
cout << "Enter job: ";
cin >> job;
}
void abstr_emp:: Writeall(fstream& finout)
{
finout << "Name: " << fname << " " << lname << endl
<< "Job: " << job << endl;
}
std::ostream& operator<<(std::ostream & os, const abstr_emp & e)
{
os << e.fname << " " << e.lname << endl;
return os;
}
abstr_emp::~abstr_emp() {}
// implementations for class employee
// no new class-member added,all use base-class methods
employee::employee() :abstr_emp() {}
employee::employee(const std::string & fn,
const std::string & ln,
const std::string & j) : abstr_emp(fn, ln, j) {}
void employee::ShowAll() const { abstr_emp::ShowAll(); }
void employee::SetAll() { abstr_emp::SetAll(); }
void employee::Writeall(fstream& finout)
{
abstr_emp::Writeall(finout);
}
// implementations for class manager
manager::manager() :abstr_emp() { inchargeof = 0; }
manager::manager(const std::string & fn, const std::string & ln, const std::string & j,
int ico) : abstr_emp(fn, ln, j), inchargeof(ico) {}
manager::manager(const abstr_emp & e,
int ico) : abstr_emp(e), inchargeof(ico) {}
manager::manager(const manager & m) : abstr_emp(
m), inchargeof(m.inchargeof) {}
void manager::ShowAll() const
{
abstr_emp::ShowAll();
cout << "Manages " << InChargeOf() <<
" employees." << endl;
}
void manager::SetAll()
{
abstr_emp::SetAll();
cout << "Enter the numbers of employees manages: ";
cin >> InChargeOf();// or cin >> inchargeof
// protected members are set for derived class,available within derived class
// but object of derived class can't involk
// for this function,can use private member inchargeof directly. Both are okay
}
void manager::Writeall(fstream& finout)
{
abstr_emp::Writeall(finout);
finout<< "Manages " << InChargeOf() <<
" employees." << endl;
}
// implementations for class fink
fink::fink() :abstr_emp() {}
fink::fink(const std::string & fn,
const std::string & ln,
const std::string & j,
const std::string & rpo) : abstr_emp(fn, ln, j),
reportsto(rpo) {}
fink::fink(const abstr_emp & e,
const std::string & rpo) : abstr_emp(e),
reportsto(rpo) {}
fink::fink(const fink & e) : abstr_emp(e),
reportsto(e.reportsto) {}
void fink::ShowAll() const
{
abstr_emp::ShowAll();
cout << "Reports to: " << reportsto << endl;
}
void fink::SetAll()
{
abstr_emp::SetAll();
cout << "Enter manager's name reports to: ";
cin >> reportsto;
}
void fink::Writeall(fstream& finout)
{
abstr_emp::Writeall(finout);
finout << "Reports to: " << reportsto << endl;
}
// implementations for class highfink
highfink::highfink() :abstr_emp(), manager(),
fink() {}
// manager has a constructor,it is: manager(fn,ln,j,ico)
highfink::highfink(const std::string & fn,
const std::string & ln,
const std::string & j, const std::string & rpo,
int ico) : abstr_emp(fn, ln, j), manager(fn, ln, j, ico),
fink(fn, ln, j, rpo) {}
highfink::highfink(const abstr_emp & e,
const std::string & rpo, int ico) : abstr_emp(e),
fink(e, rpo), manager(e, ico) {}
// first, have to know we have to create abstr_emp,manager,fink
// second, we can create manager using ancestor's part from fink
// there is a constructor manager(const abstr_emp&,int)
// here we up-casting fink objec f to obstr_emp's object
highfink::highfink(const fink & f,
int ico) :abstr_emp(f), manager(f, ico), fink(f) {}
highfink::highfink(const manager & m,
const std::string & rpo) : abstr_emp(m), manager(m), fink(m, rpo) {}
// pointer and reference of base-class can points to derived class's derived class
highfink::highfink(const highfink & h) : abstr_emp(h), manager(h), fink(h) {}
// inside highfink,its functions can use protected methods of
// base-class (manager and fink)
void highfink::ShowAll() const
{
// part of same ancestor
abstr_emp::ShowAll();
// part of one of base-classes manager,with help of protected methods
cout << "Numbers of staff managed: " << manager::InChargeOf() << endl;
// part of one of base-classes fink,with help of protected methods
cout << "Reports to: " << fink::ReportsTo() << endl;
}
void highfink::SetAll()
{
// part of same ancestor
abstr_emp::SetAll();
// part of one of base-classes manager,with help of protected methods
cout << "Enter the numbers of employees manages: ";
cin >> InChargeOf();// or cin >> inchargeof
// part of one of base-classes fink,with help of protected methods
cout << "Enter manager's name reports to: ";
cin >> ReportsTo();
}
void highfink::Writeall(fstream& finout)
{
abstr_emp::Writeall(finout);
finout << "Numbers of staff managed: " << manager::InChargeOf() << endl;
finout << "Reports to: " << fink::ReportsTo() << endl;
}
*/
main.cpp
#include<iostream>
#include<fstream>
#include<iomanip>// left,setw()
#include"emp.h"
using namespace std;
const int SIZE = 10;
// prototypes
void caseBlockSol(abstr_emp*& pt, fstream& finout, int n);
void Solicit(abstr_emp* ps[], const int SIZE, fstream& finout);
void ReadFile(fstream& finout);
int main()
{
// solicit data from user
abstr_emp* pt[SIZE];// base class pointers
fstream finout;
// remove contents in file,avoid logs of previous-run left
finout.open("result.txt", ios_base::in | ios_base::out | ios_base::trunc);
if (!finout.is_open())
{
cerr << "Failed to open file: " << "result.txt, Bye!\n";
cin.get();
exit(EXIT_FAILURE);
}
finout.close();
// PART1: write to file
Solicit(pt, SIZE, finout);// open and close file inside the function
// PART2: read from file, show logs
cout << "\nNow we've opened file, logs in it shown as below:\n";
ReadFile(finout);
// PART3: add logs of file
cout << "\nNow you can add new logs to file.\n";
abstr_emp* Newpt[SIZE];// use a new array storing pointers of newly added data
Solicit(Newpt, SIZE, finout);
// PART4: again, read from file, show logs
cout << "\nNow we've opened file, logs in it shown as below:\n";
ReadFile(finout);
cout << "Program works fine. Bye!";
cin.get();
cin.get();
return 0;
}
// statements for switch of Solicit()
template<typename T>
void caseBlockSol(abstr_emp*& pt, fstream& finout, int n)
{
pt = new T;
pt->SetAll();// fill obj from user
cout << "\nHere is the log you input:\n";
pt->ShowAll();
// write to file,include a classtype-num and log
//int classtype = n;
//finout << classtype;
pt->Writeall(finout);
cout << "(Added to file successfully)\n";
}
// solicit data from user
void Solicit(abstr_emp* ps[], const int SIZE, fstream& finout)// accept array of base class pointers, fstream&
{
// open and check if open successfully
finout.open("result.txt", ios_base::in | ios_base::out | ios_base::app);// append, avoid cover
if (!finout.is_open())
{
cerr << "Failed to open file: " << "result.txt, Bye!\n";
cin.get();
exit(EXIT_FAILURE);
}
// menu
cout << "Enter a num to choose an options: \n";
cout << left;// format out stream
cout << setw(20) << "1. Employee" << setw(20) << "2. Manager" << "\n"
<< setw(20) << "3. Fink" << setw(20) << "4. Highfink" << endl;
int choice;
cin >> choice;
// exclude invalid value to choice
while (choice<= 0 || choice> 4)
{
cout << "Invalid choice, please input again: \n";
cin >> choice;
}
// allow input multi-times,can interupt anytime
int i = 0;
char ch = 'y';
while (i < SIZE && tolower(ch) != 'q')// max SIZE inputs, allow user to interupt
{
// switch options
switch (choice)
{
case 1:
caseBlockSol<employee>(ps[i], finout, 1);
break;
case 2:
caseBlockSol<manager>(ps[i], finout, 2);
break;
case 3:
caseBlockSol<fink>(ps[i], finout, 3);
break;
case 4:
caseBlockSol<highfink>(ps[i], finout, 4);
break;
default:
break;
}
// prompt if want to stop inputting
cout << "\n( Q/q to quit input, anyother key to continue): ";
while (cin.get() != '\n')// get rid of rest of input line
continue;
cin.get(ch);
if (ch != 'q'&&ch != 'Q')
{
ch = 'y';// exclude white space
// menu
cout << "\n\nEnter a num to choose an options: \n";
cout << left;// format out stream
cout << setw(20) << "1. Employee" << setw(20) << "2. Manager" << "\n"
<< setw(20) << "3. Fink" << setw(20) << "4. Highfink" << endl;
cin >> choice;
// exclude invalid value to choice
while (choice <= 0 || choice > 4)
{
cout << "\nInvalid choice, please input again: \n";
cin >> choice;
}
}
i++;
}
finout.close();
cout << "\nAll of you input written to file successfully. Input completed.\n";
}
// read logs from file
void ReadFile(fstream& finout)
{
// open and check if open successfully
finout.open("result.txt", ios_base::in | ios_base::out | ios_base::app);// append, avoid cover
if (!finout.is_open())
{
cerr << "Failed to open file: " << "result.txt, Bye!\n";
cin.get();
exit(EXIT_FAILURE);
}
// show current logs of file
char ch;
while (!finout.eof())
{
finout.get(ch);
cout << ch;
}
finout.close();// because Solicit() will open and close file again
}