// design3.cpp: Implements Alistair's 3rd CoffeeMachine Design
// NOTE: This version doesn't use std::string because of
// a problem with the <sstream> header in today's
// compilers (it doesn't eat the newline).
// Member functions are defined in situ to save
// space.
// For simplicity, this implementation zeroes-out the
// credit after each drink is dispensed (see returnCoins()).
#include <stdio.h>
#include <string.h>
#include <assert.h>
// We make Selection a class:
// Provides conversions to and from ints and strings.
class Selection
{
public:
enum {BLACK, WHITE, SWEET, BOTH, BOUILLION, NUM_SELECT};
Selection(int c)
{
assert(0 <= c && c < NUM_SELECT);
choice = c;
}
Selection(const char* s)
{
for (int i = 0; i < NUM_SELECT; ++i)
if (strcmp(text[i], s) == 0)
{
choice = i;
return;
}
throw "Selection: bad action";
}
const char* toString() const {return text[choice];}
int priceOf() const {return price[choice];}
operator int() const {return choice;}
private:
int choice;
static int price[NUM_SELECT];
static const char* text[NUM_SELECT];
};
// Static data for Selection class:
int Selection::price[Selection::NUM_SELECT] = {35,35,35,35,25};
const char* Selection::text[Selection::NUM_SELECT] =
{
"black", "white", "sweet", "both", "boullion"
};
// CashBox class:
// Tracks the amount of credit.
class CashBox
{
public:
CashBox() {credit = 0;}
void deposit(int amount)
{
credit += amount;
printf("\tCashBox: Depositing %d cents.",amount);
printf("\tYou now have %d cents credit.\n",credit);
}
void returnCoins()
{
printf("\tCashBox: Returning %d cents\n",credit);
credit = 0;
}
bool haveYou(int amount) const {return credit >= amount;}
void deduct(int amount)
{
credit -= amount;
returnCoins();
}
private:
int credit;
};
// Mixer class:
// Doesn't do much!
class Mixer
{
public:
void make(const Selection& s)
{
printf("\tMixer: Making %s\n", s.toString());
}
};
// Selector class:
// Checks credit; Dispenses product.
class Selector
{
public:
Selector(CashBox* pC, Mixer* pM)
{
pCashBox = pC;
pMixer = pM;
}
void select(const Selection& s)
{
int amount = s.priceOf();
if (pCashBox->haveYou(amount))
{
pMixer->make(s);
pCashBox->deduct(amount);
}
else
puts("\tSelector: Insufficient funds");
}
private:
CashBox* pCashBox;
Mixer* pMixer;
};
// CoffeeMachine class:
// Owns CashBox, Mixer, and Selector.
class CoffeeMachine
{
public:
CoffeeMachine()
{
pCashBox = new CashBox;
pMixer = new Mixer;
pSelector = new Selector(pCashBox, pMixer);
}
bool doOneAction()
{
// Reads commands and executes them.
char line[16];
if (gets(line))
{
char action[7];
sscanf(line, "%s", action);
if (strcmp(action, "insert") == 0)
{
int value;
sscanf(line, "%*s %d", &value);
pCashBox->deposit(value);
}
else if (strcmp(action,"select") == 0)
{
char choice[9];
sscanf(line, "%*s %s", choice);
pSelector->select(choice);
}
else if (strcmp(action,"quit") == 0)
return false;
return true;
}
else
return false;
}
private:
CashBox* pCashBox;
Mixer* pMixer;
Selector* pSelector;
};
// Test program
main()
{
try
{
CoffeeMachine cm;
while (cm.doOneAction())
;
}
catch (const char* s)
{
puts(s);
}
return 0;
}
/* Input:
insert 25
insert 25
select white
insert 50
select boullion
quit
*/
/* Output:
CashBox: Depositing 25 cents. You now have 25 cents credit.
CashBox: Depositing 25 cents. You now have 50 cents credit.
Mixer: Making white
CashBox: Returning 15 cents
CashBox: Depositing 50 cents. You now have 50 cents credit.
Mixer: Making boullion
CashBox: Returning 25 cents
*/
//End of File