// vendingmachine.cc written by Andreas Bauer #include #include #include "vendingmachine.hh" using namespace std; void (Vendingmachine :: *cur_state) (void); // Current state of the state machine. void (Vendingmachine :: *transition) (void); // Pointer to a transition function. Vendingmachine :: Vendingmachine (void) { manual = true; } void Vendingmachine :: automatic (void) { manual = false; } // This function returns a pointer to a transition function depending // on the user's input/action. fn_ptr Vendingmachine :: action (void) { int money; if (manual) { cout << "Insert either 5 or 10 cents: " << endl; cin >> money; } else { // Generate random money insertions. money = (1 + (int)(2.0 * rand () / (RAND_MAX + 1.0))) * 5; PRINTLN(money); } switch (money) { case 5: return &Vendingmachine :: t_5_cents; break; case 10: return &Vendingmachine :: t_10_cents; break; default: PRINTLN("Only 5 or 10 cents allowed."); exit (-1); break; } } // These functions tail call into the new state of the state machine, // depending on the current state the machine's in. void Vendingmachine :: t_5_cents (void) { if (cur_state == &Vendingmachine :: s_zero) s_nickel (); else if (cur_state == &Vendingmachine :: s_nickel) s_dime (); else if (cur_state == &Vendingmachine :: s_dime) s_15_cents (); else if (cur_state == &Vendingmachine :: s_15_cents) s_20_cents (); else { PRINTLN("Insert only the correct amount of 5 and 10 cent coins."); exit (-1); } } void Vendingmachine :: t_10_cents (void) { if (cur_state == &Vendingmachine :: s_zero) s_dime (); else if (cur_state == &Vendingmachine :: s_dime) s_20_cents (); else if (cur_state == &Vendingmachine :: s_nickel) s_15_cents (); else if (cur_state == &Vendingmachine :: s_15_cents) { PRINTLN("I don't give change. Here's your entire money back."); s_zero (); } else { PRINTLN("Insert only the correct amount of 5 and 10 cent coins."); exit (-1); } } // The state functions of the state machine ask for user input and // then call a transition function which does the mapping of state x // input symbol x state. void Vendingmachine :: s_zero (void) { cur_state = &Vendingmachine :: s_zero; PRINTLN("You have not yet inserted any money."); transition = action (); (this->*transition) (); } void Vendingmachine :: s_nickel (void) { cur_state = &Vendingmachine :: s_nickel; PRINTLN("You have inserted 5 cents."); transition = action (); (this->*transition) (); } void Vendingmachine :: s_dime (void) { cur_state = &Vendingmachine :: s_dime; PRINTLN("You have inserted 10 cents."); transition = action (); (this->*transition) (); } void Vendingmachine :: s_15_cents (void) { cur_state = &Vendingmachine :: s_15_cents; PRINTLN("You have inserted 15 cents."); transition = action (); (this->*transition) (); } void Vendingmachine :: s_20_cents (void) { cur_state = &Vendingmachine :: s_20_cents; PRINTLN("You have inserted 20 cents. Here's your candy."); s_zero (); } // This is a simple, public start function. void Vendingmachine :: start (void) { PRINTLN("Hello! I'm your friendly candy machine."); s_zero (); }