// 캬오옷.. 졸라 심심하다 ㅠ.ㅠ 학교 와서 노닥거리다가 걍 해봤음. 파서 만드는데 80프로 이상의 시간을..--;
// 대강의 예외처리도 된거 같고.. 고칠거 있음 말해주길
// DeleteMe 헉 이 미완의 컬러링 비밀 기능을 .. 어떻게 알고..
// 문제의 코드 부분
// 아래로 이어지는 if/else-if는 코드 중복이라고 봅니다. 이걸 어떻게 제거할 수 있을까요? Command Pattern? Polymorphism? 혹은 그냥 Table Lookup? --JuNe
if(command == "help")
{
Helper::showCommand();
}
else if(command == "mymoney")
{
cout << sm.getRestMoney() << endl;
}
else if(command == "inventory")
{
user.showBuyedGoods();
}
else if(command == "ask")
{
string good(&str[token+1], &str[str.size()]);
sm.answerCost(good);
}
else if(command == "deposit")
{
string m(&str[token+1], &str[str.size()]);
int money = StringConvertToInt(m);
user.depositMoney(sm, money);
}
else if(command == "exit")
{
exit(0);
}
else if(command == "menu")
{
sm.showMenu();
}
else if(command == "buy")
{
int token2 = getToken(str,2);
string good(&str[token+1], &str[token2]);
string cnt(&str[token2+1], &str[str.size()]);
int count = StringConvertToInt(cnt);
user.buyGoods(sm, sm.findGoods(good), count);
}
else if(command == "cancel")
{
int token2 = getToken(str,2);
string good(&str[token+1], &str[token2]);
string cnt(&str[token2+1], &str[str.size()]);
int count = StringConvertToInt(cnt);
user.cancleGoods(sm, sm.findGoods(good), count);
}
// 어떻게 하면 if/else if 중복을 없앨수 있을까 고민하다가 폴리모피즘을 이용하기로 했습니다.(근데 이거 폴리모피즘이 맞나?--;)
// map<string, Cmd*> 이런식으로 string에는 커맨드를,Cmd 클래스는 HelpCmd클래스, Deposit클래스 등등의 부모 클래스, 즉 명령 클래스들의
// 조상 클래스를 포인터로 넣어줬습니다. 동적 바인딩을 하기 위해서..--; Parser생성할때 map 테이블에다 명령들을 넣어주면서 그 명령에
// 해당하는 클래스를 동적 할당해주면서 넣었습니다. 소멸자에서는 해제하는 것도 잊지 않았구요. 나름대로 상당히 고민을 했지만..--;
// 이것밖엔 답이 안나오네요.
// 그래서 나름대로 고쳐본 것
#include <iostream>
#include <string>
#include <vector>
#include <cassert>
#include <map>
using namespace std;
class SuperMarket;
class User;
class Parser;
class Helper;
class Goods;
class Packages;
class Cmd;
class Goods
{
private :
string _name;
int _cost;
public :
Goods(const string& name, int cost) : _name(name), _cost(cost) {}
const string& getName() const
{
return _name;
}
int getCost() const
{
return _cost;
}
};
class Packages
{
private :
Goods _good;
int _count;
public :
Packages(const Goods& good, int count) : _good(good), _count(count) {}
const Goods& getGoods() const
{
return _good;
}
int getCount() const
{
return _count;
}
void setCount(int n)
{
_count = n;
}
};
class SuperMarket
{
private :
int _receivedMoney;
vector<Goods> _havingGoods;
public :
SuperMarket()
{
Goods g1("candy",1000);
_havingGoods.push_back(g1);
Goods g2("diskette",1200);
_havingGoods.push_back(g2);
Goods g3("mouse",5000);
_havingGoods.push_back(g3);
_receivedMoney = 0;
}
void receiveMoney(int money)
{
_receivedMoney = money;
cout << "OK" << endl;
}
void showMenu() const
{
cout << " 메뉴 " << endl;
for(int i = 0 ; i < _havingGoods.size() ; ++i)
{
cout << _havingGoods[i].getName() << " " << _havingGoods[i].getCost() << endl;
}
}
void sellGoods(const Goods& goods, int count)
{
_receivedMoney -= goods.getCost() * count;
}
int getRestMoney() const
{
return _receivedMoney;
}
const vector<Goods>& getGoods() const
{
return _havingGoods;
}
void answerCost(const string& goodsName) const
{
bool isFind = false;
for(int i = 0 ; i < _havingGoods.size() ; ++i)
{
if(_havingGoods[i].getName() == goodsName)
{
cout << _havingGoods[i].getCost() << endl;
isFind = true;
break;
}
}
if(!isFind)
{
cout << "그런 물건 없음!" << endl;
}
}
const Goods& findGoods(const string& goodsName) const
{
for(int i = 0 ; i < _havingGoods.size() ; ++i)
{
if(_havingGoods[i].getName() == goodsName)
{
return _havingGoods[i];
}
}
}
};
class User
{
private :
vector<Packages> _buyedGoods;
public :
void depositMoney(SuperMarket& sm, int money) const
{
sm.receiveMoney(money);
}
void showBuyedGoods()
{
if(_buyedGoods.size() == 0)
cout << "None" << endl;
else
{
for(int i = 0 ; i < _buyedGoods.size() ; ++i)
{
cout << _buyedGoods[i].getGoods().getName() << " " << _buyedGoods[i].getCount() << endl;
}
}
}
void buyGoods(SuperMarket& sm, const Goods& goods, int count)
{
if(sm.getRestMoney() < goods.getCost() * count)
cout << "can't buy" << endl;
else
{
sm.sellGoods(goods, count);
Packages p(goods, count);
_buyedGoods.push_back(p);
}
}
void cancleGoods(SuperMarket& sm, const Goods& goods, int count)
{
bool isFind = false;
int nth = 0;
for(int i = 0 ; i < _buyedGoods.size() ; ++i)
{
if(goods.getName() == _buyedGoods[i].getGoods().getName())
{
isFind = true;
nth = i;
}
}
if(!isFind)
cout << "그 물건 안샀어요." << endl;
else
{
if(_buyedGoods[nth].getCount() < count)
{
cout << "산 것보다 더 많이 취소 못합니다." << endl;
}
else if(_buyedGoods[nth].getCount() == count)
{
if(_buyedGoods[nth].getCount() == 0)
{
_buyedGoods.erase(_buyedGoods.begin() + nth);
}
}
else
{
_buyedGoods[nth].setCount( _buyedGoods[nth].getCount() - count );
}
}
}
};
class Helper
{
public :
static void showCommand()
{
cout << "* deposit <money> -- 돈을 money만큼 예금한다. " << endl;
cout << "* mymoney -- 남은 돈을 보여준다." << endl;
cout << "* buy <product> <count> -- product 물건을 count 만큼 산다." << endl;
cout << "* inventory -- 산 물건의 목록을 보여준다 ." << endl;
cout << "* cancel <product> <count> -- 산 product 물건을 count개만큼 취소한다 ." << endl;
cout << "* ask <product> -- procuct 물건의 가격을 묻는다 ." << endl;
cout << "* menu -- 구매 가능한 물건의 목록을 보여준다 ." << endl;
cout << "* exit -- 가게를 나간다 ." << endl;
}
};
class Cmd
{
public :
virtual void executeCommand(SuperMarket& sm, User& user, const string& str) = 0;
static int getToken(const string& str, int nth)
{
int ret = str.size();
int count = 0;
for(int i = 0 ; i < str.size() ; ++i)
{
if(str[i] == ' ')
{
ret = i;
++count;
if(count == nth)
return ret;
}
}
return ret;
}
int StringConvertToInt(string& str)
{
int ret = 0;
for(int i = 0 ; i < str.length() ; ++i)
{
ret += CharToInt(str[i]) * Power(10,(str.length() - i));
}
return ret;
}
int CharToInt(char ch)
{
return ch - 48;
}
int Power(int c, int e)
{
int ret = 1;
for(int i = 0 ; i < e - 1 ; ++i)
{
ret *= c;
}
return ret;
}
};
class HelpCmd : public Cmd
{
public :
void executeCommand(SuperMarket& sm, User& user, const string& str)
{
Helper::showCommand();
}
};
class MyMoneyCmd : public Cmd
{
public :
void executeCommand(SuperMarket& sm, User& user, const string& str)
{
cout << sm.getRestMoney() << endl;
}
};
class InventoryCmd : public Cmd
{
public :
void executeCommand(SuperMarket& sm, User& user, const string& str)
{
user.showBuyedGoods();
}
};
class AskCmd : public Cmd
{
public :
void executeCommand(SuperMarket& sm, User& user, const string& str)
{
int token = getToken(str, 1);
string good(&str[token+1], &str[str.size()]);
sm.answerCost(good);
}
};
class DepositCmd : public Cmd
{
public :
void executeCommand(SuperMarket& sm, User& user, const string& str)
{
int token = getToken(str, 1);
string m(&str[token+1], &str[str.size()]);
int money = StringConvertToInt(m);
user.depositMoney(sm, money);
}
};
class ExitCmd : public Cmd
{
public :
void executeCommand(SuperMarket& sm, User& user, const string& str)
{
exit(0);
}
};
class MenuCmd : public Cmd
{
public :
void executeCommand(SuperMarket& sm, User& user, const string& str)
{
sm.showMenu();
}
};
class BuyCmd : public Cmd
{
public :
void executeCommand(SuperMarket& sm, User& user, const string& str)
{
int token = getToken(str,1);
int token2 = getToken(str,2);
string good(&str[token+1], &str[token2]);
string cnt(&str[token2+1], &str[str.size()]);
int count = StringConvertToInt(cnt);
user.buyGoods(sm, sm.findGoods(good), count);
}
};
class CancleCmd : public Cmd
{
public :
void executeCommand(SuperMarket& sm, User& user, const string& str)
{
int token = getToken(str,1);
int token2 = getToken(str,2);
string good(&str[token+1], &str[token2]);
string cnt(&str[token2+1], &str[str.size()]);
int count = StringConvertToInt(cnt);
user.cancleGoods(sm, sm.findGoods(good), count);
}
};
class Parser
{
private :
map<string, Cmd*> _tableCmd;
public :
Parser()
{
_tableCmd["help"] = new HelpCmd();
_tableCmd["mymoney"] = new MyMoneyCmd();
_tableCmd["inventory"] = new InventoryCmd();
_tableCmd["ask"] = new AskCmd();
_tableCmd["deposit"] = new DepositCmd();
_tableCmd["exit"] = new ExitCmd();
_tableCmd["menu"] = new MenuCmd();
_tableCmd["buy"] = new BuyCmd();
_tableCmd["cancle"] = new CancleCmd();
}
void translateCommand(SuperMarket& sm, User& user, const string& str)
{
int token = Cmd::getToken(str,1);
string command(&str[0], &str[token]);
_tableCmd[command]->executeCommand(sm, user, str);
}
virtual ~Parser()
{
map<string, Cmd*> :: iterator i;
for(i = _tableCmd.begin() ; i != _tableCmd.end() ; ++i)
{
delete &(i->second);
}
}
};
int main()
{
User user;
SuperMarket superMarket;
Parser parser;
char command[30];
while(1)
{
cout << endl << ">>> " ;
cin.getline(command, 30);
parser.translateCommand(superMarket, user, command);
}
return 0;
}