U E D R , A S I H C RSS

Vending Machine/세연/1002


1. �칙

다�과 같� 2개� �칙만 �용해서 수정해봤습니다.
  1. 명확하지 않는 변수/함수&메소드 ì�´ë¦„ì—� 대해 - ì�´ë¦„ì�„ 다르게 바꿔준다. ë˜�는 무엇ì�„ 하기 위한 것ì�¸ê°€ì—� ìž…ê°�, 함수/메소드 로 ì¶”ìœí•œë‹¤.

  2. 소위 magic number (ex : 배열� 범위를 설정하는 숫�들) � 불리는 것들� 대해 - const 변수 선언

  3. 긴 메소드 - 함수 & 메소드를 따로 ì¶”ìœ. 즉, 하나ì�˜ 함수 ë‚´ì—�서 하는 ì�¼ë“¤ì�´ 많다고 ìƒ�ê°�ë�  때.

  4. 중복 - 중복ë�˜ëŠ” 부분ì—� 대해 함수 & 메소드로 ì¶”ìœ.


여기서는 저 위� 1-4번 �칙만 ��해 보겠습니다. �단 � 코드가 제대로 �아간다는 가정하�서 수정합니다. (문제는 제대로 고�졌는지 확�할 길� �다는. -_-;)

2. menu ì¶”ìœ : 3번 ì›�ì¹™

~cpp 
void printMenu () {
	cout << "\n��기 입니다\n";
	cout << "1.�� 넣는다\n";
	cout << "2.물건� 산다\n";
	cout << "3.�� 거술러 받는다\n";
	cout << "4.�료수를 채운다\n";
	cout << "0.종료한다\n"; 
	cout << "메뉴를 선�하세요 : ";
}

3. while loop �서� 조건� - 1번

~cpp 
bool isEndMenu (int choice) {
	return choice != 0;
}

~cpp 
	while(isEndMenu (choice))
	{
		printMenu ();
		cin >> choice;
		.
		.

4. choice != 0 : 2번

~cpp 
enum {
	MENU_END = 0,
};

~cpp 
bool isEndMenu (int choice) {
	return choice != MENU_END;
}

5. MENU 부분� 대해서 : 2번

~cpp 
enum {
	MENU_END = 0,
	MENU_GET_MONEY,
	MENU_BUY,
	MENU_TAKEBACK_MONEY,
	MENU_INSERT_DRINK
};
~cpp 
			switch(choice)
			{
			case MENU_GET_MONEY:
				VendingMachine.GetMoney();
				break;
			case MENU_BUY:
				VendingMachine.Buy();
				break;
			case MENU_TAKEBACK_MONEY:
				VendingMachine.TakeBackMoney();
				break;
			case MENU_INSERT_DRINK:
				VendingMachine.InsertDrink();
				break;
			case MENU_END:
				cout << "��기를 종료합니다!!\n\n"; 
				break;
			}

6. MENU 선� 부분과 관련(choice >= 0 && choice <= 4), 잘못� 메뉴 선� 골�주기 : 1, 2번

~cpp 
bool isValidMenu (int choice) {
	return choice >= 0 && choice <= 4;
}
여기� 2번� 다시 �용해주면
~cpp 
bool isValidMenu (int choice) {
	return choice >= MENU_END && choice <= MENU_INSERT_DRINK;
}
근�.. 좀 명확해 보�진 않는군요. enum �서 설정� 것� 재정�해주면
~cpp 
enum {
	MENU_ENDCODE = 0,
	MENU_START = 0,
	MENU_GET_MONEY,
	MENU_BUY,
	MENU_TAKEBACK_MONEY,
	MENU_INSERT_DRINK,
	MENU_END = MENU_INSERT_DRINK
};
MENU_END 뜻� 달�졌으므로, 앞�서 MENU_END를 �었� 다른 것들� 고칩니다.
~cpp 
			case MENU_ENDCODE:
				cout << "��기를 종료합니다!!\n\n"; 
				break;
			}
~cpp 
bool isEndMenu (int choice) {
	return choice != MENU_ENDCODE;
}
그러면, ~cpp isValidMenu 를 다�과 같� 고칠 수 있습니다. (�놓고 보니 그리 맘� 들진 않지만, �단 �정�만 해�겠습니다. -_-;)
~cpp 
bool isValidMenu (int choice) {
	return choice >= MENU_START && choice <= MENU_END;
}

7. Menu � 부분 - 1번 �칙

~cpp 
			case MENU_ENDCODE:
				VendingMachine.EndMachine();
				break;
			}
		}
		else 
			VendingMachine.PrintErrorMessage ();
	}
솔ì§�히 ì�´ë¶€ë¶„ì�´ 좋지 않ì�€ 것ì�´.. Vending Machine ë‚´ì—�서 UI 부분ì�´ 확실하게 ì¶”ìœë�˜ì§€ 않았다는 ì �입니다. (ë§Œì�¼ Requirement ê°€ 변경ë�˜ì–´ì„œ, MFC 그래픽 버전으로 만든다면? ë””ìž�ì�¸ì�´ 잘 ë�œë‹¤ë©´, Vending Machine 쪽ì�˜ 코드ì�˜ 수정ì�´ ê±°ì�˜ ì—†ì�´ UI 코드만 '추가' ë�  ê²�니다. ì�´ëŠ” 기존 Vending Machine 코드쪽ì�˜ '변경'ì�„ ì�˜ë¯¸í•˜ì§€ 않습니다.)

하지만 ì�´ê±´ 추후ì—� Vending Machine ì—�서 메소드를 다른 í�´ëž˜ìФì—�게로 ì�´ì–‘시켜주면서 UI 부분과 관련한 í�´ëž˜ìŠ¤ë¥¼ ì¶”ìœí•´ 낼 수 있ì�„ 것 같다고 ìƒ�ê°�합니다. 여기서는 추후ì—� 진행하ë�„ë¡� 하겠습니다.

디��� 할때� 보통 Input / Output � 요구사항� �주 바뀌므로 �단 메� Vending Machine 코드가 작성�고 난 뒤, Vending Machine � �터페�스� 맞춰서 Input / Output 코드를 나중� 작성하는 것� 좋습니다.

8. Vending Machine � 초기화 부분 - 4번 �칙

~cpp 
const int DRINKNAME_MAXLENGTH = 255;
const int TOTAL_DRINK_TYPE = 5;
~cpp 
vending_machine::vending_machine()
{
	money = temp_money = 0;
	select_money = 1;
	max_num = TOTAL_DRINK_TYPE;

	char drinkNames[TOTAL_DRINK_TYPE][DRINKNAME_MAXLENGTH] = {"coke", "juice", "tea", "cofee", "milk"};
	int price[TOTAL_DRINK_TYPE] = {400, 600, 500, 450, 350};

	for (int i=0; i<max_num; i++) {
		strcpy(s_drink[i].name , drinkNames[i]);
		s_drink[i].price = price[i];
		s_drink[i].amount = 10;
	}
}


�단 여기까지� 소스는 대강 �러합니다. 아�� � 그리 � 변화는 �껴지지 않습니다. ^^ (나머진 있다가 학� �착한 뒤 마저;)

~cpp 
#include <iostream>
using namespace std;

enum {
	MENU_ENDCODE = 0,
	MENU_START = 0,
	MENU_GET_MONEY,
	MENU_BUY,
	MENU_TAKEBACK_MONEY,
	MENU_INSERT_DRINK,
	MENU_END = MENU_INSERT_DRINK
};

const int DRINKNAME_MAXLENGTH = 255;
const int TOTAL_DRINK_TYPE = 5;

class vending_machine
{
private:
	int money;
	int temp_money;
	int select_money, select_drink, insert_amount;
	struct drink
	{
		char name[DRINKNAME_MAXLENGTH];
		int price, amount;
	};
	drink s_drink[5];
	int max_num;
	
public:

	vending_machine();
	void GetMoney();
	void Buy();
	void TakeBackMoney();
	void InsertDrink();
	void EndMachine();
	void PrintErrorMessage ();
};

vending_machine::vending_machine()
{
	money = temp_money = 0;
	select_money = 1;
	max_num = TOTAL_DRINK_TYPE;

	char drinkNames[TOTAL_DRINK_TYPE][DRINKNAME_MAXLENGTH] = {"coke", "juice", "tea", "cofee", "milk"};
	int price[TOTAL_DRINK_TYPE] = {400, 600, 500, 450, 350};

	for (int i=0; i<max_num; i++) {
		strcpy(s_drink[i].name , drinkNames[i]);
		s_drink[i].price = price[i];
		s_drink[i].amount = 10;
	}
}
	
void vending_machine::GetMoney()
{
	cout << "�� 넣으세요. 10, 50, 100, 500, 1000만 가능 : ";
	cin >> temp_money;
	if(temp_money == 10 || temp_money == 50 || temp_money == 100 || temp_money == 500 || temp_money == 1000)
		money = money + temp_money;
	else
		cout << "10, 50, 100, 500, 1000만 가능합니다. 다시 시작해주세요\n";
			
	cout << money << "�� 넣었습니다\n";
}

void vending_machine::Buy()
{
	
	cout << "�료수\t\t가격\t수량\n";
	cout << "------------------------------------\n";
	for(int i = 0 ; i < max_num ; i++)
		cout << i + 1 << "."  << s_drink[i].name << "\t\t" << s_drink[i].price << "\t" << s_drink[i].amount << "\n";
	
	cout << "\n현재 " << money << "�� 있어요\n";
	cout << "�하는 �료수를 선�하세요 : ";
	cin >> select_drink;
	switch(select_drink)
	{
	case 1:
		if((money - s_drink[select_drink - 1].price) >= 0 && s_drink[select_drink - 1].amount >= 1)
		{
			s_drink[select_drink - 1].amount--;
			money = money - s_drink[select_drink - 1].price;
		}
		else
			cout << "잔액� 부족하거나 수량� 부족해요\n";
		break;
	case 2:
		if((money - s_drink[select_drink - 1].price) >= 0 && s_drink[select_drink - 1].amount >= 1)
		{
			s_drink[select_drink - 1].amount--;
			money = money - s_drink[select_drink - 1].price;
		}
		else
			cout << "잔액� 부족하거나 수량� 부족해요\n";
		break;
	case 3:
		if((money - s_drink[select_drink - 1].price) >= 0 && s_drink[select_drink - 1].amount >= 1)
		{
			s_drink[select_drink - 1].amount--;
			money = money - s_drink[select_drink - 1].price;
		}
		else
			cout << "잔액� 부족하거나 수량� 부족해요\n";
		break;
	case 4:
		if((money - s_drink[select_drink - 1].price) >= 0 && s_drink[select_drink - 1].amount >= 1)
		{
			s_drink[select_drink - 1].amount--;
			money = money - s_drink[select_drink - 1].price;
		}
		else
			cout << "잔액� 부족하거나 수량� 부족해요\n";
		break;
	case 5:
		if((money - s_drink[select_drink - 1].price) >= 0 && s_drink[select_drink - 1].amount >= 1)
		{
			s_drink[select_drink - 1].amount--;
			money = money - s_drink[select_drink - 1].price;
		}
		else
			cout << "잔액� 부족하거나 수량� 부족해요\n";
		break;
	
	}
	cout << money << "�� 남았어요\n";
}

void vending_machine::TakeBackMoney()
{
	cout << "거스름�" << money << "�� �려드립니다\n";
	money = 0;
}

void vending_machine::InsertDrink()
{
	for(int i = 0 ; i < max_num ; i++)
		cout << i + 1 << "." << s_drink[i].name << "\t" << s_drink[i].amount << "\n";
	cout << "채우길 �하는 �료수를 선�하세요 : ";
	cin >> select_drink;
	cout << "채우길 �하는 �료수 수량� 입력해주세요 : ";
	cin >> insert_amount;

	switch(select_drink)
	{
	case 1:
		s_drink[select_drink - 1].amount += insert_amount;
		break;
	case 2:
		s_drink[select_drink - 1].amount += insert_amount;
		break;
	case 3:
		s_drink[select_drink - 1].amount += insert_amount;
		break;
	case 4:
		s_drink[select_drink - 1].amount += insert_amount;
		break;
	case 5:
		s_drink[select_drink - 1].amount += insert_amount;
		break;
	}
	cout << "�료수를 채웠습니다\n";
	for(i = 0 ; i < max_num ; i++)
		cout << i + 1 << "." << s_drink[i].name << "\t" << s_drink[i].amount << "\n";
}

void vending_machine::EndMachine()
{
	cout << "��기를 종료합니다!!\n\n"; 
}

void vending_machine::PrintErrorMessage ()
{
	cout << "잘못� 메뉴 선�입니다. 메뉴를 다시 입력해주세요\n";
}

void printMenu () {
	cout << "\n��기 입니다\n";
	cout << "1.�� 넣는다\n";
	cout << "2.물건� 산다\n";
	cout << "3.�� 거술러 받는다\n";
	cout << "4.�료수를 채운다\n";
	cout << "0.종료한다\n"; 
	cout << "메뉴를 선�하세요 : ";
}

bool isEndMenu (int choice) {
	return choice != MENU_ENDCODE;
}

bool isValidMenu (int choice) {
	return choice >= MENU_START && choice <= MENU_END;
}

int main()
{
	vending_machine VendingMachine;
	int choice = -1;

	while(isEndMenu (choice))
	{
		printMenu ();
		cin >> choice;
		if(isValidMenu (choice))
		{
			switch(choice)
			{
			case MENU_GET_MONEY:
				VendingMachine.GetMoney();
				break;
			case MENU_BUY:
				VendingMachine.Buy();
				break;
			case MENU_TAKEBACK_MONEY:
				VendingMachine.TakeBackMoney();
				break;
			case MENU_INSERT_DRINK:
				VendingMachine.InsertDrink();
				break;
			case MENU_ENDCODE:
				VendingMachine.EndMachine();
				break;
			}
		}
		else 
			VendingMachine.PrintErrorMessage ();
	}

	return 0;
}

9. vending_machine::GetMoney () - 1, 3, 4번 �칙

'무엇ì�„ 하는가' ë�¼ê³  할때 InsertMoney ë˜�는 InsertCoin ì�´ ë�” 정확한 표현ì�´ë�¼ ìƒ�ê°�ë�˜ì–´ì§‘니다. 그리고, 역시 하는 ì�¼ì—� 대해서 메소드로 ì¶”ìœí•¨ìœ¼ë¡œì„œ comment 를 대신 í•  수 있습니다.
~cpp 
bool vending_machine::isValidMoney (int money) {
	return (temp_money == 10 || temp_money == 50 || temp_money == 100 || temp_money == 500 || temp_money == 1000);
}

void vending_machine::InsertMoney() 
{ 
        cout << "�� 넣으세요. 10, 50, 100, 500, 1000만 가능 : "; 
        cin >> temp_money; 
	if (isValidMoney (temp_money)) {
	        money = money + temp_money; 
	}
        else 
                cout << "10, 50, 100, 500, 1000만 가능합니다. 다시 시작해주세요\n"; 
                         
        cout << money << "�� 넣었습니다\n"; 
} 

그리고, 메소드로 ì¶”ìœí•˜ë©´ 좋ì�€ì �ì�´, 코드를 ê³ ì¹  부분ì�„ 메소드 내로 시야ì�˜ í�­ì�„ 줄ì�¼ 수 있습니다. ìž‘ì�€ 메소드ë�¼ë�„ ì¶”ìœí•´ë‘�ë©´ 나중ì—� 다시 메소드를 모으거나, 중복ì�„ 없애기가 편리합니다.
~cpp 
bool vending_machine::isValidMoney (int money) {
	int validMoneys[5] = {10, 50, 100, 500, 1000};

	for (int i=0;i<5;i++) {
		if (money == validMoney[i]) return true;
	}
	return false;
}

단, �러한 중복줄�기 & �반화는 중복� 발��었�때 (2 or 3 strike) 해주는 것� 쉽습니다. 처�부터 모든 중복� 부분� 다 예측해 낼 수는 없습니다.

� �부터 시작, � 극단�� 예를 든다면 다�과 같�� 할 수 있지만, 꼭 할 필요는 없습니다. (그대신 시�해보면 재미있습니다) �단 넓게 넓게 보는 것� � 좋기 때문�.

~cpp 
const int validMoney[5] = {10, 50, 100, 500, 1000};

void vending_machine::printInsertCoinMenu () {
        cout << "�� 넣으세요. 10, 50, 100, 500, 1000만 가능 : "; 
}

void vending_machine::printErrorInvalidCoinMessage () {
        cout << "10, 50, 100, 500, 1000만 가능합니다. 다시 시작해주세요\n"; 
}
void vending_machine::printCurrentMoney () {
        cout << money << "�� 넣었습니다\n"; 
}

bool vending_machine::isValidMoney (int money) {

	for (int i=0;i<5;i++) {
		if (money == validMoney[i]) return true;
	}
	return false;
}


void vending_machine::InsertMoney() 
{ 
	printInsertCoinMenu ();
        cin >> temp_money; 
	if (isValidMoney (temp_money)) {
	        money = money + temp_money; 
	        printCurrentMoney ();
	}
        else 
		printErrorInvalidCoinMessage ();
                         
} 
�것� 한번 � 중복� 줄�면
~cpp 
void vending_machine::printInsertCoinMenu () {
        cout << "�� 넣으세요. ";
	for (int i=0;i<4;i++) {
		cout << validMoneys[i] << ","
	}
	cout << valiMoneys[4] << "만 가능 : ";
}

10. temp_money - 4번

temp_money 가 하는 �� 보면 한가지 �만 합니다.
~cpp 
void vending_machine::InsertMoney()  
{  
	printInsertCoinMenu (); 
	cin >> temp_money;  
	if (isValidMoney (temp_money)) { 
		money = money + temp_money;  
		printCurrentMoney (); 
	} 
	else  
		printErrorInvalidCoinMessage (); 
	
}  
� �외엔 쓰�지 않지만, private 멤버로 있습니다. �러한 입력� 받기 위한 임시변수는 그냥 멤버�서 없애주면 �니다.
~cpp 
void vending_machine::InsertMoney()  
{  
	int temp_money = 0;

	printInsertCoinMenu (); 
	cin >> temp_money;  
	
	if (isValidMoney (temp_money)) { 
		money = money + temp_money;  
		printCurrentMoney (); 
	} 
	else  
		printErrorInvalidCoinMessage (); 
}  

11. vending_machine::Buy () - 1,3,4

1단계 - menu 부분 프린트 ì¶”ìœ & i -> drinkIndex 로 변경.
~cpp 
void vending_machine::printBuyMenu () {
	cout << "�료수\t\t가격\t수량\n"; 
	cout << "------------------------------------\n"; 
	for(int drinkIndex = 0 ; drinkIndex < max_num ; drinkIndex++) 
		cout << drinkIndex + 1 << "."  
			<< s_drink[drinkIndex].name << "\t\t" 
			<< s_drink[drinkIndex].price << "\t" 
			<< s_drink[drinkIndex].amount << "\n"; 
	
	cout << "\n현재 " << money << "�� 있어요\n"; 
	cout << "�하는 �료수를 선�하세요 : "; 
}

void vending_machine::Buy() 
{ 
	printBuyMenu ();
	.
	.
2단계 - switch & case

� 부분� 대해서 �미 �반화 공�� 만들었��� 불구하고 불필요한 switch & case 문� 있습니다. � 부분� 대해서는 많� 코드를 줄� 수 있겠습니다.

~cpp 
void vending_machine::Buy() 
{ 
	printBuyMenu ();

	cin >> select_drink; 

	if((money - s_drink[select_drink-1].price) >= 0 && s_drink[select_drink-1].amount >= 1) { 
		s_drink[select_drink-1].amount--; 
		money = money - s_drink[select_drink-1].price; 
	} 
	else 
		cout << "잔액� 부족하거나 수량� 부족해요\n"; 

	cout << money << "�� 남았어요\n"; 
} 
그리고, select_drink-1 �으로 쓴 것� 많��, � �유는 아마 번호를 1,2,3,4 ... 로 �기 위함� 것입니다. 그리고 select_drink �한 vending_machine � 멤버��, 특별히 하는 �� 없는 한 지역변수로 �는것� 낫습니다.

12. vending_machine::InsertDrink - 3,4

~cpp 
void vending_machine::InsertDrink() 
{ 
	int select_drink;
	int insert_amount;

	printCurrentDrinkStatus ();
	cout << "채우길 �하는 �료수를 선�하세요 : "; 
	cin >> select_drink; 
	cout << "채우길 �하는 �료수 수량� 입력해주세요 : "; 
	cin >> insert_amount; 
	
	if (select_drink-1 > 0 && select_drink-1 <=5) 
		s_drink[select_drink-1].amount += insert_amount; 

	cout << "�료수를 채웠습니다\n"; 
	printCurrentDrinkStatus ();
} 

13. 중간 소스

~cpp 
#include <iostream>  
using namespace std;  

enum {  
	MENU_ENDCODE = 0,  
        MENU_START = 0,  
        MENU_GET_MONEY,  
        MENU_BUY,  
        MENU_TAKEBACK_MONEY,  
        MENU_INSERT_DRINK,  
        MENU_END = MENU_INSERT_DRINK  
};  

const int DRINKNAME_MAXLENGTH = 255;  
const int TOTAL_DRINK_TYPE = 5;  
const int validMoney[5] = {10, 50, 100, 500, 1000};  

class vending_machine  
{  
private:  
	int money;  
	struct drink  
	{  
		char name[DRINKNAME_MAXLENGTH];  
		int price, amount;  
	};  
	drink s_drink[TOTAL_DRINK_TYPE];  
	int max_num;  
	
	public:  
		
        vending_machine();  
        void InsertMoney();  
        void Buy();  
        void TakeBackMoney();  
        void InsertDrink();  
        void EndMachine();  
		
		bool isValidMoney (int money); 
		
        void PrintErrorMessage ();  
		void PrintErrorInvalidCoinMessage (); 
		void PrintInsertCoinMenu(); 
		void PrintCurrentMoney (); 
		void PrintBuyMenu (); 
		void PrintCurrentDrinkStatus (); 
};  

vending_machine::vending_machine()  
{  
	money = 0;  
	max_num = TOTAL_DRINK_TYPE;  
	
	char drinkNames[TOTAL_DRINK_TYPE][DRINKNAME_MAXLENGTH] = {"coke", "juice", "tea", "cofee", "milk"};  
	int price[TOTAL_DRINK_TYPE] = {400, 600, 500, 450, 350};  
	
	for (int i=0; i<max_num; i++) {  
		strcpy(s_drink[i].name , drinkNames[i]);  
		s_drink[i].price = price[i];  
		s_drink[i].amount = 10;  
	}  
}  

void vending_machine::PrintInsertCoinMenu () {  
	cout << "�� 넣으세요. ";  
	for (int i=0;i<4;i++) 
		cout << validMoney[i] << "," ; 
	cout << validMoney[4] << "만 가능 : ";  
}  

void vending_machine::PrintErrorInvalidCoinMessage () {  
	cout << "�� 넣으세요. ";  
	for (int i=0;i<4;i++) 
		cout << validMoney[i] << ","; 
	cout << validMoney[4] << "만 가능합니다. 다시 시작해주세요\n";  
}  

void vending_machine::PrintCurrentMoney () {  
	cout << money << "�� 넣었습니다\n";   
}  

bool vending_machine::isValidMoney (int money) {  
	for (int i=0;i<5;i++) 
		if (money == validMoney[i]) return true;  
	return false;  
}  

void vending_machine::InsertMoney()   
{   
	int temp_money = 0; 
	
	PrintInsertCoinMenu ();  
	cin >> temp_money;   
	
	if (isValidMoney (temp_money)) {  
		money = money + temp_money;   
		PrintCurrentMoney ();  
	}  
	else   
		PrintErrorInvalidCoinMessage ();  
}   

void vending_machine::PrintBuyMenu () { 
	cout << "�료수\t\t가격\t수량\n";  
	cout << "------------------------------------\n";  

	for(int drinkIndex = 0 ; drinkIndex < max_num ; drinkIndex++)  
		cout << drinkIndex + 1 << "."   
		<< s_drink[drinkIndex].name << "\t\t"  
		<< s_drink[drinkIndex].price << "\t"  
		<< s_drink[drinkIndex].amount << "\n";  
	
	cout << "\n현재 " << money << "�� 있어요\n";  
	cout << "�하는 �료수를 선�하세요 : ";  
} 

void vending_machine::Buy()  
{  
	PrintBuyMenu (); 
	
	int select_drink; 
	
	cin >> select_drink;  
	
	if((money - s_drink[select_drink-1].price) >= 0 && s_drink[select_drink-1].amount >= 1) {  
		s_drink[select_drink-1].amount--;  
		money = money - s_drink[select_drink-1].price;  
	}  
	else  
		cout << "잔액� 부족하거나 수량� 부족해요\n";  
	
	cout << money << "�� 남았어요\n";  
}  

void vending_machine::TakeBackMoney()  
{  
	cout << "거스름�" << money << "�� �려드립니다\n";  
	money = 0;  
}  

void vending_machine::PrintCurrentDrinkStatus () { 
	for(int drinkIndex = 0 ; drinkIndex < max_num ; drinkIndex++)  
		cout << drinkIndex + 1 << "." 
		<< s_drink[drinkIndex].name << "\t" 
		<< s_drink[drinkIndex].amount << "\n";  
} 

void vending_machine::InsertDrink()  
{  
	int select_drink; 
	int insert_amount; 
	
	PrintCurrentDrinkStatus (); 
	cout << "채우길 �하는 �료수를 선�하세요 : ";  
	cin >> select_drink;  
	cout << "채우길 �하는 �료수 수량� 입력해주세요 : ";  
	cin >> insert_amount;  
	
	if (select_drink-1 > 0 && select_drink-1 <=5)  
		s_drink[select_drink-1].amount += insert_amount;  
	
	cout << "�료수를 채웠습니다\n";  
	PrintCurrentDrinkStatus (); 
}  

void vending_machine::EndMachine()  
{  
	cout << "��기를 종료합니다!!\n\n";   
}  

void vending_machine::PrintErrorMessage ()  
{  
	cout << "잘못� 메뉴 선�입니다. 메뉴를 다시 입력해주세요\n";  
}  

void PrintMenu () {  
	cout << "\n��기 입니다\n";  
	cout << "1.�� 넣는다\n";  
	cout << "2.물건� 산다\n";  
	cout << "3.�� 거술러 받는다\n";  
	cout << "4.�료수를 채운다\n";  
	cout << "0.종료한다\n";   
	cout << "메뉴를 선�하세요 : ";  
}  

bool isEndMenu (int choice) {  
	return choice != MENU_ENDCODE;  
}  

bool isValidMenu (int choice) {  
	return choice >= MENU_START && choice <= MENU_END;  
}  

void vending_machine::Run () {
	int choice = -1;  
	
	while(isEndMenu (choice))  
	{  
		PrintMenu ();  
		cin >> choice;  
		if(isValidMenu (choice))  
		{  
			switch(choice)  
			{  
			case MENU_GET_MONEY:  
				InsertMoney();  
				break;  
			case MENU_BUY:  
				Buy();  
				break;  
			case MENU_TAKEBACK_MONEY:  
				TakeBackMoney();  
				break;  
			case MENU_INSERT_DRINK:  
				InsertDrink();  
				break;  
			case MENU_ENDCODE:  
				EndMachine();  
				break;  
			}  
		}  
		else   
			PrintErrorMessage ();  
	}  
}


int main()  
{  
	vending_machine VendingMachine;  
	VendingMachine.Run ();
	return 0;  
}  

�쯤�서 문제� - vending_machine � 완전히 God �래스입니다. 완전히 � 프로그램 �체가 vending_machine �체와 �급� �어버리죠.

ìž…ìœë ¥ë¶€ë¶„ê³¼ Vending Machine ìž�ì²´ì�˜ 분리
~cpp 
#ifndef _VENDINGMACHINE_H_
#define _VENDINGMACHINE_H_

#include <iostream>   
#include <string>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;   

class Drink   
{   
public:
	string name;   
	int price;
	int amount;   
	
	Drink (string name, int price, int amount) {
		this->name = name;
		this->price = price;
		this->amount = amount;
	}
};   

class VendingMachine   
{   
public:   
	int money;   
	vector <Drink*> drinks;
	vector <int> validMoney;

	VendingMachine() {
		this->money = 0;   
		
		string drinkNames[] = {"coke", "juice", "tea", "cofee", "milk"};   
		int price[] = {400, 600, 500, 450, 350};   
		int defaultAmount = 10;
		int TOTAL_DRINK_TYPE = 5;

		int validMoneyList[] = {10, 50, 100, 500, 1000};   
		int TOTAL_MONEY_TYPE = 5;

		Drink* drink;
		for (int drinkIndex=0; drinkIndex<TOTAL_DRINK_TYPE; drinkIndex++) {   
			drink = new Drink(drinkNames[drinkIndex], price[drinkIndex], defaultAmount);
			registerDrink (drink);
		}   
		for (int moneyIndex=0; moneyIndex<TOTAL_MONEY_TYPE; moneyIndex++) {
			registerMoneyType (validMoneyList[moneyIndex]);
		}
	}

	~VendingMachine () {
		for (int i=0; i< drinks.size(); i++) {
			delete drinks[i];
		}
		drinks.clear();
	}

	void registerMoneyType (int moneyType) {
		validMoney.push_back(moneyType);	
	}

	bool isValidDrinkIndex (int drinkIndex) {
		return (drinkIndex>=0 && drinkIndex <5);
	}

	void chargeDrink (int drinkIndex, int amount) {
		drinks[drinkIndex]->amount += amount;   
	}

	vector<int> getValidMoneyTypes(void) {
		return this->validMoney;
	}

	bool VendingMachine::isBuyable(int drinkId) {
		return ((getMoney() - drinks[drinkId]->price >= 0) && 
			(drinks[drinkId]->amount >= 1));
	}

	vector<Drink*> getRegisteredDrinks () {
		return this->drinks;
	}

	void VendingMachine::buy (int drinkId) {
		drinks[drinkId]->amount--;   
		chargeMoney (drinks[drinkId]->price);
	}
	
	void registerDrink (Drink* drink) {
		drinks.push_back(drink);
	}

	bool isValidMoneyType (int money) {   
		for (int i=0; i<validMoney.size();i++) {
			if (validMoney[i] == money)
				return true;
		}

		return false;
	}   
	
	int takeBackMoney()   
	{  
		int takeBackMoney = this->money;
		this->money = 0;   
		return takeBackMoney;
	}   
	
	void insertMoney (int money) {
		this->money += money;
	}

	void chargeMoney (int drinkPrice) {
		this->money -= drinkPrice;   
	}
	
	int getMoney () {
		return money;
	}
};   
#endif

main.cpp
#include "VendingMachine.h"
#include <iostream>   
#include <map>
using namespace std;   

enum {   
	MENU_ENDCODE = 0,   
	MENU_START = 0,   
	MENU_GET_MONEY,   
	MENU_BUY,   
	MENU_TAKEBACK_MONEY,   
	MENU_INSERT_DRINK,   
	MENU_END = MENU_INSERT_DRINK   
};   

typedef void(*Func)(VendingMachine&);   

void InsertMoney(VendingMachine& vendingMachine);   
void Buy(VendingMachine& vendingMachine);   
void TakeBackMoneyMenu(VendingMachine& vendingMachine);   
void InsertDrink(VendingMachine& vendingMachine);   
void EndMachine(VendingMachine& vendingMachine);   

void PrintErrorMessage ();   
void PrintErrorInvalidCoinMessage (VendingMachine& vendingMachine);  
void PrintInsertCoinMenu();  
void PrintCurrentMoney (int money);  
void PrintBuyMenu (int money);  
void PrintCurrentDrinkStatus ();  

void PrintErrorInvalidCoinMessage (VendingMachine& vendingMachine) {   
	cout << "�� 넣으세요. ";   
	vector<int> validMoney = vendingMachine.getValidMoneyTypes();

	for (int i=0;i<validMoney.size()-1;i++)  
		cout << validMoney[i] << ",";  
	cout << validMoney[i] << "만 가능합니다. 다시 시작해주세요\n";   
}   

void PrintCurrentMoney (int money) {   
	cout << money << "�� 넣었습니다\n";    
}   

void PrintBuyMenu (VendingMachine& vendingMachine) {  
	cout << "�료수\t\t가격\t수량\n";   
	cout << "------------------------------------\n";   

	vector <Drink*> drinks = vendingMachine.getRegisteredDrinks();
	
	for(int drinkIndex = 0 ; drinkIndex < drinks.size() ; drinkIndex++)   {
		cout << drinkIndex << "."    
		<< drinks[drinkIndex]->name << "\t\t"   
		<< drinks[drinkIndex]->price << "\t"   
		<< drinks[drinkIndex]->amount << "\n";   
	}
	
	PrintCurrentMoney (vendingMachine.getMoney());
	cout << "�하는 �료수를 선�하세요 : ";   
}  

void Buy(VendingMachine& vendingMachine)   
{   
	PrintBuyMenu (vendingMachine);  

	int drinkId;
	cin >> drinkId;   

	if(vendingMachine.isBuyable(drinkId)) {   
		vendingMachine.buy (drinkId);
		cout << vendingMachine.getMoney() << "�� 남았어요\n";   
	}   
	else   
		cout << "잔액� 부족하거나 수량� 부족해요\n";   
}   

void TakeBackMoney (VendingMachine& vendingMachine) {
	int takeBackMoney = vendingMachine.takeBackMoney ();
	cout << "거스름�" << takeBackMoney << "�� �려드립니다\n";   
}

void PrintCurrentDrinkStatus (VendingMachine& vendingMachine) {  
	vector<Drink*> drinks = vendingMachine.getRegisteredDrinks();

	for(int drinkIndex = 0 ; drinkIndex < drinks.size() ; drinkIndex++)   
		cout << drinkIndex << "."  
		<< drinks[drinkIndex]->name << "\t"  
		<< drinks[drinkIndex]->amount << "\n";   
}  

void PrintErrorMessage ()   
{   
	cout << "잘못� 메뉴 선�입니다. 메뉴를 다시 입력해주세요\n";   
}   

void InsertMoney(VendingMachine& vendingMachine)    
{    
	int money = 0;
	cout << "�� 넣으세요. ";   
	vector<int> validMoney = vendingMachine.getValidMoneyTypes();

	for (int i=0;i<validMoney.size()-1;i++)  
		cout << validMoney[i] << "," ;  
	cout << validMoney[i] << "만 가능 : ";   

	cin >> money; 
	
	if (vendingMachine.isValidMoneyType (money)) {
		vendingMachine.insertMoney (money);
		PrintCurrentMoney (vendingMachine.getMoney ());   
	}   
	else    
		PrintErrorInvalidCoinMessage (vendingMachine);   
}    

void InsertDrink(VendingMachine& vendingMachine)   
{   
	int selectDrink;  
	int insertAmount;  
	
	PrintCurrentDrinkStatus (vendingMachine);  
	cout << "채우길 �하는 �료수를 선�하세요 : ";   
	cin >> selectDrink;   
	cout << "채우길 �하는 �료수 수량� 입력해주세요 : ";   
	cin >> insertAmount;   
	
	if (vendingMachine.isValidDrinkIndex (selectDrink)) {
		vendingMachine.chargeDrink (selectDrink, insertAmount);

		cout << "�료수를 채웠습니다\n";   
	}
	PrintCurrentDrinkStatus (vendingMachine);  
}   

void EndMachine(VendingMachine& vendingMachine)   
{   
	cout << "��기를 종료합니다!!\n\n";    
}   

bool isEndMenu (int choice) {   
	return choice != MENU_ENDCODE;   
}   

bool isValidMenu (int choice) {   
	return choice >= MENU_START && choice <= MENU_END;   
}   

int InputMainMenu () {
	int choice = -1;
	cout << "\n��기 입니다\n" 
		 << "1.�� 넣는다\n"
		 << "2.물건� 산다\n"   
		 << "3.�� 거슬러 받는다\n" 
		 << "4.�료수를 채운다\n" 
		 << "0.종료한다\n" 
		 << "메뉴를 선�하세요 : ";   

	cin >> choice;
	return choice;
}

int main()   
{   
	VendingMachine vendingMachine;   
	int choice = -1;

	int  menuList[] = { MENU_GET_MONEY, MENU_BUY, MENU_TAKEBACK_MONEY, MENU_INSERT_DRINK, MENU_ENDCODE};
	Func funcList[] = { InsertMoney, Buy, TakeBackMoney, InsertDrink, EndMachine };

	map<int, Func> menuTable;

	for (int menuIndex=0; menuIndex<5; menuIndex++) {
		menuTable[menuList[menuIndex]] = funcList[menuIndex];
	}

	while (isEndMenu (choice)) {
		choice = InputMainMenu ();
		if (isValidMenu (choice)) {
			(*menuTable[choice])(vendingMachine);
		}
		else    
			PrintErrorMessage ();   
	}   

	return 0;   
}
Valid XHTML 1.0! Valid CSS! powered by MoniWiki
last modified 2021-02-07 05:28:21
Processing time 0.0135 sec