|
포럼 서버가 날아갔을때, 님의 질문과 저의 답글이 지워져버렸네요.
그래서 저도 제 답글을 다시 올립니다.
복소수 처리는 std::complex 클래스를 사용하였으며
디자인 패턴을 써서 if ... else를 제거하고,
STL을 써서 for 루프를 제거했습니다.
//---------------------------------------------------------------------------
#include <iostream>
#pragma hdrstop
#include <list>
#include <map>
#include <iterator>
#include <functional>
#include <algorithm>
#include <complex>
//---------------------------------------------------------------------------
// 디자인 패턴 중 Command 패턴을 이용한 방법
// 여기서는 모두 아규먼트가 없는 간단한 명령이므로
// 명령어 처리 객체 자체를 SimpleCommand 템플릿 클래스의 파라미터로 함.
template <typename Receiver>
class SimpleCommand
{
public:
typedef void (Receiver::*Action)();
SimpleCommand() : _receiver(NULL), _action(NULL) {};
SimpleCommand(Receiver* r, Action a) : _receiver(r), _action(a) {}
virtual void Execute() { (_receiver->*_action)(); };
private:
Receiver *_receiver; // 메시지를 받는 객체의 포인터
Action _action; // 명령을 보낼 멤버함수의 포인터
};
using namespace std;
// 복소수의 대소 관계를 정의
template <typename T>
inline bool operator<(const complex<T>& c1, const complex<T>& c2)
{
return abs(c1) < abs(c2) || // 절대값 순서대로
(abs(c1) == abs(c2) && arg(c1) < arg(c2)); // 절대값이 같으면 위상각 순서
}
template <typename T>
class CommandReceivingList {
private:
list<T> _list; // 복소수들을 저장할 doubly linked list
typedef SimpleCommand<CommandReceivingList<T> > ListCommand;
typedef map<string, ListCommand> CommandMap; // 입력 문자열과 명령어를 저장
CommandMap cmds;
public:
CommandReceivingList()
{ // 입력 문자열을 명령어로 매핑
cmds.insert(make_pair("push",
ListCommand(this, &CommandReceivingList::Push)));
cmds.insert(make_pair("remove",
ListCommand(this, &CommandReceivingList::Remove)));
cmds.insert(make_pair("size",
ListCommand(this, &CommandReceivingList::Size)));
cmds.insert(make_pair("print",
ListCommand(this, &CommandReceivingList::Print)));
cmds.insert(make_pair("sort",
ListCommand(this, &CommandReceivingList::Sort)));
cmds.insert(make_pair("quit",
ListCommand(this, &CommandReceivingList::Quit)));
cmds.insert(make_pair("help",
ListCommand(this, &CommandReceivingList::Help)));
}
void Execute(string aCommand)
{
if (cmds.count(aCommand)) // 입력 문자열을 map에서 검색하여
cmds[aCommand].Execute(); // 있으면 실행
else
cout << "Bad command\n"; // 없으면 에러 메시지
}
void Push()
{
T input;
cin >> input;
_list.push_back(input);
}
void Remove()
{
T input;
cin >> input;
_list.remove(input);
}
void Size() { cout << _list.size() << endl; }
void Print()
{ // 루프를 쓰지 않는 출력 방법
copy(_list.begin(), _list.end(),
ostream_iterator<T>(cout, " "));
cout.put('\n');
}
void Sort() { _list.sort(); }
void Quit() { cin.setstate(ios::failbit); } // Ctrl+Z를 누른 효과를 냄.
void Help()
{
cout << "push: 원소 하나를 추가한다.\n"
"remove: 원소 하나를 입력받아서 있으면 제거한다.\n"
"size: 원소 개수를 출력한다.\n"
"print: 전체 원소를 출력한다.\n"
"sort: 리스트를 정렬한다.\n"
"quit 또는 ctrl+z: 프로그램을 종료한다.\n"
"help: 도움말을 출력한다.\n";
}
};
int main()
{
// complex<float> 대신 임의의 다른 타입을 사용해도 작동됨.
typedef CommandReceivingList<complex<float> > FloatList;
FloatList crfl;
string aCommand;
while (cout << ">> ", cin >> aCommand)
crfl.Execute(aCommand);
return 0;
}
//---------------------------------------------------------------------------
실행 결과는 다음과 같습니다.
>> push (5,3)
>> push (-3,-4)
>> print
(5,3) (-3,-4)
>> sort
>> print
(-3,-4) (5,3)
>> push (-1,2)
>> remove (5,3)
>> push (1,2)
>> sort
>> print
(1,2) (-1,2) (-3,-4)
>> push (1,-5)
>> size
4
>> print
(1,2) (-1,2) (-3,-4) (1,-5)
>> remove (-1,2)
>> sort
>> print
(1,2) (-3,-4) (1,-5)
>> quit
|