본문 바로가기
개인공부/C++ 기초플러스

C++ Primer 14 Exercise

by 하고싶은건많은놈 2023. 2. 21.

01

// winec.h

#ifndef WINEC_H_
#define WINEC_H_
#include <iostream>
#include <valarray>
#include <string>

template <class T1, class T2>
class Pair
{
	private:
		T1 a;
		T2 b;
	public:
		T1 & first();
		T2 & second();
		T1 first() const { return a; }
		T2 second() const { return b; }
		Pair(const T1 & aval, const T2 & bval) : a(aval), b(bval) {}
		Pair() {}
};

typedef std::valarray<int> ArrayInt;
typedef Pair<ArrayInt, ArrayInt> PairArray;

class Wine
{
	private:
		std::string name;
		int year_num;
		PairArray num;
	public:
		Wine(const char * l, int y, const int yr[], const int bot[]);
		Wine(const char * l, int y);
		~Wine();
		void GetBottles();
		const std::string & Label() const { return name; };
		int sum() const;
		void Show() const;
};

#endif
// winec.cpp

#include "winec.h"

template<class T1, class T2>
T1 & Pair<T1, T2>::first()
{
	return a;
}

template<class T1, class T2>
T2 & Pair<T1, T2>::second()
{
	return b;
}

Wine::Wine(const char * l, int y, const int yr[], const int bot[])
	: name(l), year_num(y)
{
	num.first().resize(year_num);
	num.second().resize(year_num);
	for (int i = 0; i < year_num; i++)
	{
		num.first()[i] = yr[i];
		num.second()[i] = bot[i];
	}
}

Wine::Wine(const char * l, int y) : name(l), year_num(y)
{
	num.first().resize(year_num);
	num.second().resize(year_num);
}

Wine::~Wine()
{
}

void Wine::GetBottles()
{
	using std::cout;
	using std::cin;
	using std::endl;

	cout << year_num <<"년간의 " << name << " 데이터를 입력하세요 : " << endl;
	for (int i = 0; i < year_num; i++)
	{
		cout << "수확 년도를 입력하세요 : ";
		cin >> num.first()[i];
		cout << "와인 수량을 입력하세요 : ";
		cin >> num.second()[i];
	}
}

void Wine::Show() const
{
	using std::cout;
	using std::endl;

	cout << "와인 : " << name << endl;
	cout << "	년도	수량" << endl;
	for (int i = 0; i < year_num; i++)
	{
		cout << "	" << num.first()[i]
			 << "	" << num.second()[i];
		cout << endl;
	}
}

int Wine::sum() const
{
	int sum = 0;

	for (int i = 0; i < year_num; i++)
		sum += num.second()[i];

	return sum;
}
// pe14-1.cpp

#include <iostream>
#include "winec.h"

int main()
{
	using std::cin;
	using std::cout;
	using std::endl;

	cout << "와인 이름을 입력하시오 : ";
	char lab[50];
	cin.getline(lab, 50);
	cout << "수확 년도 개수를 입력하시오 : ";
	int yrs;
	cin >> yrs;

	Wine holding(lab, yrs);
	holding.GetBottles();
	holding.Show();

	const int YRS = 3;
	int y[YRS] = {1993, 1995, 1998};
	int b[YRS] = {48, 60, 72};
	Wine more("Gushing Grape Red", YRS, y, b);
	more.Show();
	cout << more.Label() << " 전체 수량 : "
		 << more.sum() << endl;
	cout << "프로그램을 종료합니다.\n";
	return 0; 
}

02

// winec_private.h

#ifndef WINEC_PRIVATE_H_
#define WINEC_PRIVATE_H_
#include <iostream>
#include <valarray>
#include <string>

template <class T1, class T2>
class Pair
{
	private:
		T1 a;
		T2 b;
	public:
		T1 & first();
		T2 & second();
		T1 first() const { return a; }
		T2 second() const { return b; }
		Pair(const T1 & aval, const T2 & bval) : a(aval), b(bval) {}
		Pair() {}
};

typedef std::valarray<int> ArrayInt;
typedef Pair<ArrayInt, ArrayInt> PairArray;

class Wine : private std::string, private PairArray
{
	private:
		int year_num;
	public:
		Wine(const char * l, int y, const int yr[], const int bot[]);
		Wine(const char * l, int y);
		~Wine();
		void GetBottles();
		const std::string & Label() const;
		int sum() const;
		void Show() const;
};

#endif
// winec_private.cpp

#include "winec_private.h"

template<class T1, class T2>
T1 & Pair<T1, T2>::first()
{
	return a;
}

template<class T1, class T2>
T2 & Pair<T1, T2>::second()
{
	return b;
}

Wine::Wine(const char * l, int y, const int yr[], const int bot[])
	: std::string(l), year_num(y)
{
	PairArray::first().resize(year_num);
	PairArray::second().resize(year_num);
	for (int i = 0; i < year_num; i++)
	{
		PairArray::first()[i] = yr[i];
		PairArray::second()[i] = bot[i];
	}
}

Wine::Wine(const char * l, int y) : std::string(l), year_num(y)
{
	PairArray::first().resize(year_num);
	PairArray::second().resize(year_num);
}

Wine::~Wine()
{
}

void Wine::GetBottles()
{
	using std::cout;
	using std::cin;
	using std::endl;

	cout << year_num <<"년간의 " << Label() << " 데이터를 입력하세요 : " << endl;
	for (int i = 0; i < year_num; i++)
	{
		cout << "수확 년도를 입력하세요 : ";
		cin >> PairArray::first()[i];
		cout << "와인 수량을 입력하세요 : ";
		cin >> PairArray::second()[i];
	}
}

const std::string & Wine::Label() const
{
	return (const std::string &)(*this);
}

void Wine::Show() const
{
	using std::cout;
	using std::endl;

	cout << "와인 : " << Label() << endl;
	cout << "	년도	수량" << endl;
	for (int i = 0; i < year_num; i++)
	{
		cout << "	" << PairArray::first()[i]
			 << "	" << PairArray::second()[i];
		cout << endl;
	}
}

int Wine::sum() const
{
	int sum = 0;

	for (int i = 0; i < year_num; i++)
		sum += PairArray::second()[i];

	return sum;
}

03

// workermi.h

#ifndef WORKERMI_H_
#define WORKERMI_H_
#include <iostream>
#include <string>

class Worker
{
	private:
		std::string fullname;
		long id;
	protected:
		virtual void Data() const;
		virtual void Get();
	public:
		Worker() : fullname("no name"), id(0L) {}
		Worker(const std::string & s, long n) : fullname(s), id(n) {}
		virtual ~Worker() = 0;
		virtual void Set() = 0;
		virtual void Show() const = 0;
};

class Waiter : virtual public Worker
{
	private:
		int panache;
	protected:
		void Data() const;
		void Get();
	public :
		Waiter() : Worker(), panache(0) {}
		Waiter(const std::string & s, long n, int p = 0)
			: Worker(s, n), panache(p) {}
		Waiter(const Worker & wk, int p = 0)
			: Worker(wk), panache(p) {}
		void Set();
		void Show() const;
};

class Singer : virtual public Worker
{
	protected:
		enum {other, alto, contralto, soprano, bass, baritone, tenor};
		enum {Vtypes = 7};
		void Data() const;
		void Get();
	private:
		static char *pv[Vtypes];
		int voice;
	public:
		Singer() : Worker(), voice(other) {}
		Singer(const std::string & s, long n, int v = other)
			: Worker(s, n), voice(v) {}
		Singer(const Worker & wk, int v = other)
			: Worker(wk), voice(v) {}
		void Set();
		void Show() const;
};

class SingingWaiter : public Singer, public Waiter
{
	protected:
		void Data() const;
		void Get();
	public:
		SingingWaiter() {}
		SingingWaiter(const std::string & s, long n, int p = 0, int v = other)
			: Worker(s, n), Waiter(s, n, p), Singer(s, n, v) {}
		SingingWaiter(const Worker & wk, int p = 0, int v = other)
			: Worker(wk), Waiter(wk, p), Singer(wk, v) {}
		SingingWaiter(const Singer & wt, int p = 0)
			: Worker(wt), Waiter(wt, p), Singer(wt) {}
		void Set();
		void Show() const;
};
// workermi.cpp

#include "worekremi.h"
using std::cout;
using std::cin;
using std::endl;

Worker::~Worker() {}

void Worker::Data() const
{
	cout << "사원 이름 : " << fullname << endl;
	cout << "사원 번호 : " << id << endl;
}

void Worker::Get()
{
	getline(cin, fullname);
	cout << "사원 번호를 입력하십시오 : ";
	cin >> id;
	while (cin.get() != '\n')
		continue;
}

void Waiter::Set()
{
	cout << "웨이터의 이름을 입력하십시오 : ";
	Worker::Get();
	Get();
}

void Waiter::Show() const
{
	cout << "직종 : 웨이터 \n";
	Worker::Data();
	Data();
}

void Waiter::Data() const
{
	cout << "웨이터 등급 : " << panache << endl;
}

void Waiter::Get()
{
	cout << "웨이터 등급을 입력하십시오 : ";
	cin >> panache;
	while (cin.get() != '\n')
		continue;
}

char * Singer::pv[] = {"other", "alto", "contralto",
					"soprano", "bass", "baritone", "tenor"};

void Singer::Set()
{
	cout << "가수의 이름을 입력하십시오 : ";
	Worker::Get();
	Get();
}

void Singer::Show() const
{
	cout << "직종 : 가수\n";
	Worker::Data();
	Data();
}

void Singer::Data() const
{
	cout << "목소리 유형 : " << pv[voice] << endl;
}

void Singer::Get()
{
	cout << "가수의 목소리 유형 번호를 입력하십시오::\n";
	int i;
	for (i = 0; i < Vtypes; i++)
	{
		cout << i << " : " << pv[i] << " ";
		if (i % 4 == 3)
			cout << endl;
	}
	if (i % 4 != 0)
		cout << endl;
	while (cin >> voice && (voice < 0 || voice >= Vtypes))
		cout << "0보다 크거나 같고 " << Vtypes << "보다 작은 값을 입력하세요." << endl;
	while (cin.get() != '\n')
		continue;
}

void SingingWaiter::Data() const
{
	Waiter::Data();
	Singer::Data();
}

void SingingWaiter::Get()
{
	Waiter::Get();
	Singer::Get();
}

void SingingWaiter::Set()
{
	cout << "가수 겸 웨이터의 이름을 입력하십시오 : ";
	Worker::Get();
	Get();
}

void SingingWaiter::Show() const
{
	cout << "직종 : 가수 겸 웨이터\n";
	Worker::Data();
	Data();
}
// queuetp.h

#ifndef QUEUETP_H_
#define QUEUETP_H_

template <class Type>
class QueueTp
{
	private:
		enum {MAX = 10};
		Type items[MAX];
		int last;
		int first;
	public:
		QueueTp();
		bool isempty();
		bool isfull();
		bool push(const Type & item);
		bool pop(Type & item);
};

template <class Type>
QueueTp<Type>::QueueTp()
{
	first = 0;
	last = 0;
}

template <class Type>
bool QueueTp<Type>::isempty()
{
	return first == last;
}

template <class Type>
bool QueueTp<Type>::isfull()
{
	return (abs(last - first) == MAX - 1);
}

template <class Type>
bool QueueTp<Type>::push(const Type & item)
{
	if (!isfull())
	{
		items[last] = item;
		last = (last + 1) % MAX;
		return true;
	}
	else
		return false;
}

template <class Type>
bool QueueTp<Type>::pop(Type & item)
{
	if (!isempty())
	{
		item = items[first];
		first = (first + 1) % MAX;
		return true;
	}
	else
		return false;
}

#endif
// usequeuetp.cpp

#include "workermi.h"
#include "queuetp.h"
#include <cstring>

const int SIZE = 5;

int main()
{
	using std::cin;
	using std::cout;
	using std::endl;
	using std::strchr;

	Worker * lolas;

	QueueTp<Worker *> qt;

	int ct;
	for (ct = 0; ct < SIZE; ct++)
	{
		char choice;
		cout << "직종을 입력하십시오 : \n"
			 << "w : 웨이터		s : 가수		"
			 << "t : 가수 겸 웨이터		q : 종료\n";
		cin >> choice;
		while (strchr("wstq", choice) == NULL)
		{
			cout << "w, s, t, q 중에서 하나를 선택하십시오 : ";
			cin >> choice;
		}
		if (choice == 'q')
			break;
		switch(choice)
		{
			case 'w': lolas = new Waiter;
				break;
			case 's': lolas = new Singer;
				break;
			case 't': lolas = new SingingWaiter;
				break;
		}
		cin.get();
		lolas->Set();
		qt.push(lolas);
	}
	
	cout << "\n사원 현황은 다음과 같습니다 : \n";
	int i;

	while (qt.pop(lolas))
	{
		cout << endl;
		lolas->Show();
		delete lolas;
	}

	cout << "프로그램을 종료합니다.\n";
	return 0;
}

04

// baddude.h

#ifndef BADDUDE_H_
#define BADDUDE_H_
#include <string>

class Person
{
	private:
		std::string first_name;
		std::string last_name;
	public:
		Person(std::string f = "", std::string l = "");
		virtual ~Person() {};
		virtual void Show() const;
};

class Gunslinger : virtual public Person
{
	private:
		int notch;
		double drawtime;
	public:
		Gunslinger(std::string f = "", std::string l = "", int n = 0, double d = 0);
		~Gunslinger() {}
		int shownotch() const { return notch; };
		double showdrawtime() const { return drawtime; };
		double Draw() const { return drawtime; }
		virtual void Show() const;
};

class PokerPlayer : virtual public Person
{
	private:
	public:
		PokerPlayer(std::string f ="", std::string l = "");
		~PokerPlayer() {}
		int Draw() const { return rand() % 52; }
		virtual void Show() const;
};

class BadDude : public Gunslinger, public PokerPlayer
{
	private:
	public:
		BadDude(std::string f = "", std::string l = "", int n = 0, double d = 0);
		~BadDude() {}
		double Gdraw() const { return Gunslinger::Draw(); }
		int Cdraw() const { return PokerPlayer::Draw(); }
		virtual void Show() const;
};

#endif
// baddude.cpp

#include "baddude.h"
#include <iostream>
using std::string;
using std::cout;
using std::endl;

Person::Person(string f, string l)
	: first_name(f), last_name(l)
{
}

void Person::Show() const
{
	cout << "이름 : " << first_name << " " << last_name << endl;
}

Gunslinger::Gunslinger(string f, string l, int n, double d)
	: Person(f, l), notch(n), drawtime(d)
{
}

void Gunslinger::Show() const
{
	cout << "Gunslinger!\n";
	Person::Show();
	cout << "notch : " << notch << endl;
	cout << "drawtime : " << Draw() << endl;
}

PokerPlayer::PokerPlayer(string f, string l)
	: Person(f, l)
{
}

void PokerPlayer::Show() const
{
	cout << "PokerPlayer!\n";
	Person::Show();
}

BadDude::BadDude(string f, string l, int n, double d)
	: Person(f, l), Gunslinger(f, l, n, d), PokerPlayer(f, l)
{
}

void BadDude::Show() const
{
	cout << "BadDude!\n";
	Person::Show();
	cout << "notch : " << Gunslinger::shownotch() << endl;
	cout << "dratime : " << Gunslinger::showdrawtime() << endl;
}
// usebaddude.cpp

#include "baddude.h"
#include <iostream>

int main()
{
	using std::cin;
	using std::cout;
	using std::endl;

	Person one("Per", "son");
	one.Show();
	
	Gunslinger two("Gun", "slinger", 10, 2.2);
	two.Show();
	
	PokerPlayer three("Poker", "Player");
	three.Show();
	
	BadDude four("Bad", "Dude", 100, 3.3);
	four.Show();

	cout << "프로그램을 종료합니다.\n";
	return 0;
}

05

// emp.h

#ifndef EMP_H_
#define EMP_H_
#include <iostream>
#include <string>

class abstr_emp
{
	private:
		std::string fname;
		std::string lname;
		std::string job;
	public:
		abstr_emp();
		abstr_emp(const std::string & fn, const std::string & ln, const std::string & j);
		virtual void ShowAll() const;
		virtual void SetAll();
		friend std::ostream & operator<<(std::ostream & os, const abstr_emp & e);
		virtual ~abstr_emp() = 0;
};

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();
};

class manager : virtual public abstr_emp
{
	private:
		int inchargeof;
	protected:
		int InChargeOf() const { return inchargeof; }
		int & InChargeOf() { return inchargeof; }
	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();
};

class fink : virtual public abstr_emp
{
	private:
		std::string reportsto;
	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();
};

class highfink : public manager, public 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();
};

#endif
// emp.cpp

#include "emp.h"
using std::cout;
using std::cin;
using std::endl;

abstr_emp::abstr_emp() : fname(""), lname(""), 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 << "이름 : " << fname << " " << lname << endl;
	cout << "직업 : " << job << endl;
}

void abstr_emp::SetAll()
{
	cout << "성을 입력하십시오 : ";
	cin >> fname;
	cout << "이름을 입력하십시오 : ";
	cin >> lname;
	cout << "직업을 입력하십시오 : ";
	cin >> job;
}

abstr_emp::~abstr_emp()
{
}

std::ostream & operator<<(std::ostream & os, const abstr_emp & e)
{
	return os << e.fname << " " << e.lname << endl;
}

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();
}

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 << "관리 수 : " << inchargeof << endl;
}

void manager::SetAll()
{
	abstr_emp::SetAll();
	cout << "관리 수를 입력하십시오 : ";
	cin >> inchargeof;
}

fink::fink() : abstr_emp(), reportsto("")
{
}

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 << "보고 대상 : " << reportsto << endl;
}

void fink::SetAll()
{
	abstr_emp::SetAll();
	cout << "보고 대상을 입력하십시오 : ";
	cin >> reportsto;
}

highfink::highfink() : abstr_emp(), manager(), fink()
{
}

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), manager(e, ico), fink(e, rpo)
{
}

highfink::highfink(const fink & f, int ico)
	: abstr_emp(f), manager(f, ico), fink()
{
}

highfink::highfink(const manager & m, const std::string & rpo)
	: abstr_emp(m), manager(m), fink(m, rpo)
{
}

highfink::highfink(const highfink & h)
	: abstr_emp(h), manager(h), fink(h)
{
}

void highfink::ShowAll() const
{
	abstr_emp::ShowAll();
	cout << "관리 수 : " << InChargeOf() << endl;
	cout << "보고 대상 : " << ReportsTo() << endl;
}

void highfink::SetAll()
{
	abstr_emp::SetAll();
	cout << "관리 수를 입력하십시오 : ";
	cin >> InChargeOf();
	cout << "보고 대상을 입력하십시오 : ";
	cin >> ReportsTo();
}
// useemp.cpp

#include "emp.h"
#include <iostream>
using namespace std;

int main()
{
	employee em("Trip", "Harris", "Thumper");
	cout << em << endl;
	em.ShowAll();

	manager ma("Amorphia", "Spindragon", "Nuancer", 5);
	cout << ma << endl;
	ma.ShowAll();

	fink fi("Matt", "Oggs", "Oiler", "Juno Barr");
	cout << fi << endl;
	fi.ShowAll();

	highfink hf(ma, "Curly Kew");
	hf.ShowAll();
	cout << "다음 출력을 위해 아무 키나 누르십시오 : \n";
	cin.get();
	highfink hf2;
	hf2.SetAll();

	cout << "abstr_emp * 포인터의 사용 : \n";
	abstr_emp * tri[4] = { &em, &fi, &hf, &hf2 };
	for (int i = 0; i < 4; i++)
	{
		tri[i]->ShowAll();
		cout << endl;
	}

	return 0;
}
  • 대입 연산자를 정의하지 않은 이유
    : 깊은 복사가 요구되지 않기 때문에 디폴트 대입 연산자로 충분하기 때문
  • ShowAll()SetAll()이 가상인 이유
    : 자식 클래스에서 재정의되어 사용되기 때문
  • abstr_emp가 가상 기초 클래스인 이유
    : highfink 클래스가 abstr_emp 클래스로부터 상속받은 manager, fink 클래스로부터 각각 상속받아 abstr_emp가 중복되어 발생하는 문제를 해결하기 위함
  • highfink 클래스에 데이터 부분이 없는 이유
    : 상속되는 클래스들에서 필요한 데이터 멤버를 제공하기 때문
  • operator<<()의 한가지 버전만 필요한 이유
    : 파생 클래스에서 함수가 재정의되지 않은 경우 해당 파생 클래스는 그 함수의 기초 클래스 버전을 사용하기 때문
  • 프로그램의 끝 부분 코드를 다음으로 대체할 경우
    : 추상 클래스의 인스턴스는 생성할 수 없기 때문에 에러가 발생
abstr_emp tri[4] = {em, fi, hf, hf2};
for (int i = 0; i < 4; i++)
	tri[i].ShowAll();

'개인공부 > C++ 기초플러스' 카테고리의 다른 글

C++ Primer 15 Exercise  (0) 2023.02.21
C++ Primer 15  (0) 2023.02.21
C++ Primer 14  (0) 2023.02.21
C++ Primer 13 Exercise  (0) 2023.02.19
C++ Primer 13  (0) 2023.02.19

댓글