Programeer opdrachtenOpdracht : opdr1_marvin.txt

Terug naar de inzendingen
Opdracht 1,Marvin Raaijmakers
13 Jan 2005
 1 
***** COMPILING *****
  
 2HOWTO COMPILE VENDING_MACHINE
 3=============================
 4Compiling vending_machine is very easy. Just run:
 5$ make 
 1 
***** Makefile *****
  
 2TARGET = vending_machine
 3SOURCES =\
 4 main.c \
 5 sweets.c \
 6 tubes.c \
 7 user.c
 8
 9CFLAGS=-I. -O2 -Wall
 10CC=gcc
 11
 12include makefile.default
 1 
***** makefile.default *****
  
 2OBJECTS=$(SOURCES:.c=.o)
 3
 4all: $(TARGET)
 5
 6cc:
 7 $(MAKE) CC=cc \
 8  all
 9
 10$(TARGET): $(OBJECTS)
 11 $(CC) -o  $@ $(OBJECTS)
 12
 13clean:
 14 $(RM) $(TARGET) $(OBJECTS)
 1 
***** vending_machine.h *****
  
 2/*-------------------------------------------------------------------------------
 3Name               : vending_machine.h
 4Author             : Marvin Raaijmakers
 5Description        : The main header file of the vending machine
 6Date of last change: 10-January-2005
 7
 8    Copyright (C) 2005 Marvin Raaijmakers
 9
 10    This program is free software; you can redistribute it and/or modify
 11    it under the terms of the GNU General Public License as published by
 12    the Free Software Foundation; either version 2 of the License, or
 13    any later version.
 14
 15    This program is distributed in the hope that it will be useful,
 16    but WITHOUT ANY WARRANTY; without even the implied warranty of
 17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18    GNU General Public License for more details.
 19
 20    You should have received a copy of the GNU General Public License
 21    along with this program; if not, write to the Free Software
 22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 23
 24    You can contact me at: marvin_raaijmakers(at)linux-box(dot)nl
 25    (replace (at) by @ and (dot) by .)
 26---------------------------------------------------------------------------------*/
 27#define TRUE (1)
 28#define FALSE (0)
 29
 30#define NUM_TUBES  (6)
 31#define NUM_SWEETS  (5)
 32#define SWEET_REFILL_NUMBER (10)
 33#define TUBE_REFILL_NUM_COINS (15)
 34
 35typedef int Boolean;
 36typedef int MONEY;
 37
 38typedef enum {
 39 CHOICE_READY,
 40 CHOICE_ADD_COINS,
 41 CHOICE_CANCEL,
 42 CHOICE_INVALID
 43} CHOICE;
 1 
***** user.h *****
  
 2/*-------------------------------------------------------------------------------
 3Name               : user.h
 4Author             : Marvin Raaijmakers
 5Description        : Header file for providing interaction with the user
 6Date of last change: 10-January-2005
 7
 8    Copyright (C) 2005 Marvin Raaijmakers
 9
 10    This program is free software; you can redistribute it and/or modify
 11    it under the terms of the GNU General Public License as published by
 12    the Free Software Foundation; either version 2 of the License, or
 13    any later version.
 14
 15    This program is distributed in the hope that it will be useful,
 16    but WITHOUT ANY WARRANTY; without even the implied warranty of
 17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18    GNU General Public License for more details.
 19
 20    You should have received a copy of the GNU General Public License
 21    along with this program; if not, write to the Free Software
 22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 23
 24    You can contact me at: marvin_raaijmakers(at)linux-box(dot)nl
 25    (replace (at) by @ and (dot) by .)
 26---------------------------------------------------------------------------------*/
 27#define MAX_MSG_SIZE (300)
 28#define MAX_LINE_SIZE (20)
 29
 30/* NOTE: This type is related to the variable 'msg_message' in user.c " */
 31typedef enum {
 32 MSG_PAY_EXACT_AMOUNT = 0,
 33 MSG_INSERT_COIN,
 34 MSG_INVALID_COIN,
 35 MSG_CHOOSE_SWEET,
 36 MSG_INVALID_SWEET,
 37 MSG_SWEET_NOT_AVAILABLE,
 38 MSG_NOT_ENOUGH_MONEY,
 39 MSG_TAKE_SWEET,
 40 MSG_REFILL_SWEETS,
 41 MSG_REFILL_TUBES,
 42 MSG_MENU_INVALID_CHOICE,
 43 MSG_MENU,
 44 MSG_SWEETS_REFILLED,
 45 MSG_TUBES_REFILLED,
 46 NUM_MSG
 47} MSG; 
 48
 49typedef enum {
 50 GET_COIN_STOP,
 51 GET_COIN_INSERTED_COIN,
 52 GET_COIN_CANCEL
 53} GET_COIN_RETURN;
 54
 55typedef enum {
 56 CANCEL,
 57 ADD_COINS,
 58 INVALID,
 59 OK
 60} CHOOSE_SWEET_RETURN;
 61
 62typedef enum {
 63 MENU_BUY = 1,
 64 MENU_REFILL_SWEETS,
 65 MENU_REFILL_TUBES,
 66 MENU_SHUTDOWN
 67} MENU_CHOICE;
 68
 69extern void user_show_message (MSG message);
 70extern GET_COIN_RETURN user_get_coin (MONEY *coin);
 71extern void user_list_sweets (SWEETS *sweets);
 72extern CHOOSE_SWEET_RETURN user_choose_sweet (SWEETS *sweets, SWEET **choosen_sweet);
 73extern void user_return_coins (MONEY coin_value, int n);
 74extern MENU_CHOICE user_menu_choose (void);
 1 
***** tubes.h *****
  
 2/*-------------------------------------------------------------------------------
 3Name               : tubes.h
 4Author             : Marvin Raaijmakers
 5Description        : Header file for handling the tubes mechanism
 6Date of last change: 10-January-2005
 7
 8    Copyright (C) 2005 Marvin Raaijmakers
 9
 10    This program is free software; you can redistribute it and/or modify
 11    it under the terms of the GNU General Public License as published by
 12    the Free Software Foundation; either version 2 of the License, or
 13    any later version.
 14
 15    This program is distributed in the hope that it will be useful,
 16    but WITHOUT ANY WARRANTY; without even the implied warranty of
 17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18    GNU General Public License for more details.
 19
 20    You should have received a copy of the GNU General Public License
 21    along with this program; if not, write to the Free Software
 22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 23
 24    You can contact me at: marvin_raaijmakers(at)linux-box(dot)nl
 25    (replace (at) by @ and (dot) by .)
 26---------------------------------------------------------------------------------*/
 27typedef struct _tube {
 28 MONEY  value;
 29 int  num_coins;
 30 struct _tube *next;
 31} TUBE;
 32
 33typedef struct {
 34 TUBE *head,
 35  *tail;
 36} TUBES;
 37
 38#define tubes_get_first_tube(_tubes)  ( (_tubes)->head )
 39#define tube_add_coin(_tube)   ( ((_tube)->num_coins)++ )
 40#define tube_return_coin(_tube)   ( ((_tube)->num_coins)-- )
 41#define tube_get_value(_tube)   ( (_tube)->value )
 42#define tube_sensor_less_than_five(_tube) ( (_tube)->num_coins < 5 )
 43#define tube_sensor_more_than_ten(_tube) ( (_tube)->num_coins > 10 )
 44#define tube_set_num_coins(_tube, _num_coins) ( (_tube)->num_coins = (_num_coins) )
 45extern TUBE *tube_new (MONEY value);
 46extern void tubes_init (TUBES *tubes);
 47extern TUBE *find_tube (TUBES *tubes, MONEY value);
 48extern void tubes_add (TUBES *tubes, TUBE *new_tube);
 1 
***** sweets.h *****
  
 2/*-------------------------------------------------------------------------------
 3Name               : sweets.h
 4Author             : Marvin Raaijmakers
 5Description        : Header file for handling the sweets mechanism
 6Date of last change: 10-January-2005
 7
 8    Copyright (C) 2005 Marvin Raaijmakers
 9
 10    This program is free software; you can redistribute it and/or modify
 11    it under the terms of the GNU General Public License as published by
 12    the Free Software Foundation; either version 2 of the License, or
 13    any later version.
 14
 15    This program is distributed in the hope that it will be useful,
 16    but WITHOUT ANY WARRANTY; without even the implied warranty of
 17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18    GNU General Public License for more details.
 19
 20    You should have received a copy of the GNU General Public License
 21    along with this program; if not, write to the Free Software
 22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 23
 24    You can contact me at: marvin_raaijmakers(at)linux-box(dot)nl
 25    (replace (at) by @ and (dot) by .)
 26---------------------------------------------------------------------------------*/
 27#define MAX_SWEET_NAME_SIZE (30)
 28
 29typedef struct _sweet {
 30 char  name [MAX_SWEET_NAME_SIZE];
 31 MONEY  costs;
 32 int  num_sweets;
 33 struct _sweet *next;
 34} SWEET;
 35
 36typedef struct {
 37 SWEET *head,
 38  *tail;
 39} SWEETS;
 40
 41#define sweets_get_first_sweet(_sweets)   ( (_sweets)->head )
 42#define sweet_get_number(_sweet)   ( (_sweet)->num_sweets )
 43#define sweet_get_costs(_sweet)    ( (_sweet)->costs )
 44#define sweet_pop(_sweet)    ( ((_sweet)->num_sweets)-- )
 45#define sweet_sensor_is_empty(_sweet)   ( (_sweet)->num_sweets == 0 )
 46#define sweet_set_number(_sweet, _number)  ( (_sweet)->num_sweets = (_number) )
 47extern void sweets_init (SWEETS *sweets);
 48extern SWEET *sweet_new (char name[MAX_SWEET_NAME_SIZE], MONEY costs);
 49extern void sweets_add (SWEETS *sweets, SWEET *sweet);
 1 
***** sweets.c *****
  
 2/*-------------------------------------------------------------------------------
 3Name               : sweets.c
 4Author             : Marvin Raaijmakers
 5Description        : Handling the sweets mechanism.
 6Date of last change: 10-January-2005
 7
 8    Copyright (C) 2005 Marvin Raaijmakers
 9
 10    This program is free software; you can redistribute it and/or modify
 11    it under the terms of the GNU General Public License as published by
 12    the Free Software Foundation; either version 2 of the License, or
 13    any later version.
 14
 15    This program is distributed in the hope that it will be useful,
 16    but WITHOUT ANY WARRANTY; without even the implied warranty of
 17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18    GNU General Public License for more details.
 19
 20    You should have received a copy of the GNU General Public License
 21    along with this program; if not, write to the Free Software
 22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 23
 24    You can contact me at: marvin_raaijmakers(at)linux-box(dot)nl
 25    (replace (at) by @ and (dot) by .)
 26---------------------------------------------------------------------------------*/
 27#include 
 28#include 
 29
 30#include 
 31#include 
 32
 33
 34void
 35sweets_init (SWEETS *sweets)
 36/*
 37Input:
 38 -
 39Output:
 40 sweets - initialized
 41Returns:
 42 -
 43Description:
 44 This function initializes sweets.
 45*/
 46{
 47 sweets->head = sweets->tail = NULL;
 48}
 49
 50
 51SWEET
 52*sweet_new ( char name[MAX_SWEET_NAME_SIZE],
 53  MONEY costs                        )
 54/*
 55Input:
 56 name - The name of the new SWEET to create.
 57 costs - The costs of the new SWEET to create.
 58Output:
 59 -
 60Returns:
 61 The address of the new SWEET.
 62Description:
 63 This function creates a new, initialized, SWEET. Its name is name (the input
 64 variable) and it costs costs (the input variable).
 65*/
 66{
 67 SWEET *new_sweet;
 68 
 69 new_sweet = malloc(sizeof(SWEET));
 70 if (new_sweet == NULL)
 71 {
 72  exit (1);
 73 }
 74 strcpy (new_sweet->name, name);
 75 new_sweet->costs = costs;
 76 new_sweet->next = NULL;
 77 new_sweet->num_sweets = 0;
 78 
 79 return (new_sweet);
 80}
 81
 82
 83void
 84sweets_add ( SWEETS *sweets,
 85  SWEET *sweet    )
 86/*
 87Input:
 88 sweet - The SWEET to add to sweets.
 89Output:
 90 sweets - The SWEETS to add sweet to.
 91Returns:
 92 -
 93Description:
 94 This function adds sweet add at the end of sweets.
 95*/
 96{
 97 if (sweets->head == NULL) /* If the list is empty */
 98 {
 99  sweets->head = sweets->tail = sweet;
 100 }
 101 else
 102 {
 103  sweets->tail->next = sweet;
 104  sweets->tail = sweet;
 105 }
 106}
 1 
***** tubes.c *****
  
 2/*-------------------------------------------------------------------------------
 3Name               : tubes.c
 4Author             : Marvin Raaijmakers
 5Description        : Handling the tubes mechanism.
 6Date of last change: 10-January-2005
 7
 8    Copyright (C) 2005 Marvin Raaijmakers
 9
 10    This program is free software; you can redistribute it and/or modify
 11    it under the terms of the GNU General Public License as published by
 12    the Free Software Foundation; either version 2 of the License, or
 13    any later version.
 14
 15    This program is distributed in the hope that it will be useful,
 16    but WITHOUT ANY WARRANTY; without even the implied warranty of
 17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18    GNU General Public License for more details.
 19
 20    You should have received a copy of the GNU General Public License
 21    along with this program; if not, write to the Free Software
 22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 23
 24    You can contact me at: marvin_raaijmakers(at)linux-box(dot)nl
 25    (replace (at) by @ and (dot) by .)
 26---------------------------------------------------------------------------------*/
 27#include 
 28
 29#include 
 30#include 
 31
 32
 33TUBE
 34*tube_new (MONEY value)
 35/*
 36Input:
 37 value - The value of the new TUBE to create.
 38Output:
 39 -
 40Returns:
 41 The address of the new TUBE.
 42Description:
 43 This function creates a new, initialized, TUBE. Its value is value (the input
 44 variable).
 45*/
 46{
 47 TUBE *new_tube;
 48 
 49 new_tube = malloc(sizeof(TUBE));
 50 if (new_tube == NULL)
 51 {
 52  exit (1);
 53 }
 54 new_tube->value = value;
 55 new_tube->next = NULL;
 56 new_tube->num_coins = 0;
 57 
 58 return (new_tube);
 59}
 60
 61
 62void
 63tubes_init (TUBES *tubes)
 64/*
 65Input:
 66 -
 67Output:
 68 tubes - initialized
 69Returns:
 70 -
 71Description:
 72 This function initializes tubes.
 73*/
 74{
 75 tubes->head = tubes->tail = NULL;
 76}
 77
 78
 79TUBE
 80*find_tube ( TUBES *tubes,
 81  MONEY value      )
 82/*
 83Input:
 84 tubes - A list of the tubes containing the coins which is in descending order of
 85    value.
 86 value - The value of the coins in the tube to find.
 87Output:
 88 -
 89Returns:
 90 The address of the tube whose coins are value. If no tube was found find_tube()
 91 returns NULL
 92Description:
 93 This function searches for the tube (in tubes) whose coins have the value value (the
 94 input variable).
 95*/
 96{
 97 TUBE *tube;
 98 
 99 tube = tubes_get_first_tube(tubes);
 100 while (tube && (tube->value > value))
 101 {
 102  tube = tube->next;
 103 }
 104 if (tube && (tube->value == value))
 105 {
 106  return (tube);
 107 }
 108 return (NULL);
 109}
 110
 111
 112void
 113tubes_add ( TUBES *tubes,
 114  TUBE *new_tube     )
 115/*
 116Input:
 117 tubes  - A list containing tubes
 118 new_tube - The tube to add to tubes
 119Output:
 120 tubes  - A list containing tubes where new_tube was added to
 121 new_tube - The tube inserted in the list
 122Returns:
 123 -
 124Description:
 125 This function inserts new_tube in the list tubes, so that all entries in tubes
 126 are in descending order of value.
 127*/
 128{
 129 TUBE *tube;
 130 
 131 tube = tubes_get_first_tube(tubes);
 132 
 133 if (tube == NULL) /* If the list is empty */
 134 {
 135  tubes->head = tubes->tail = new_tube;
 136 }
 137 /* If new_tube should be placed at the beginning of the list */
 138 else if (tube->value < new_tube->value)
 139 {
 140  new_tube->next = tube;
 141  tubes->head = new_tube;
 142 }
 143 else
 144 {
 145  /* Find the predecessor of new_tube */
 146  while (tube->next && (tube->next->value > new_tube->value))
 147  {
 148   tube = tube->next;
 149  }
 150  new_tube->next = tube->next;
 151  tube->next = new_tube;
 152  /* If new_tube was added at the end of the list */
 153  if (new_tube->next == NULL)
 154  {
 155   tubes->tail = new_tube;
 156  }
 157 }
 158}
 1 
***** user.c *****
  
 2/*-------------------------------------------------------------------------------
 3Name               : user.c
 4Author             : Marvin Raaijmakers
 5Description        : Providing interaction with the user
 6Date of last change: 10-January-2005
 7
 8    Copyright (C) 2005 Marvin Raaijmakers
 9
 10    This program is free software; you can redistribute it and/or modify
 11    it under the terms of the GNU General Public License as published by
 12    the Free Software Foundation; either version 2 of the License, or
 13    any later version.
 14
 15    This program is distributed in the hope that it will be useful,
 16    but WITHOUT ANY WARRANTY; without even the implied warranty of
 17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18    GNU General Public License for more details.
 19
 20    You should have received a copy of the GNU General Public License
 21    along with this program; if not, write to the Free Software
 22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 23
 24    You can contact me at: marvin_raaijmakers(at)linux-box(dot)nl
 25    (replace (at) by @ and (dot) by .)
 26---------------------------------------------------------------------------------*/
 27#include 
 28
 29#include 
 30#include 
 31#include 
 32
 33static const char msg_message[NUM_MSG][MAX_MSG_SIZE] = {"Please pay the exact amount.",
 34       "Insert a coin (expressed in cents), or:\n"
 35         "- Press return if you are ready inserting coins\n"
 36         "- Press '0' if you want to cancel your buy",
 37       "You inserted an invallid coin!",
 38       "Press the number of the sweet you want.\n"
 39         "Press '0' to cancel or '#' to add some extra coins.\n"
 40         "The following sweets are available:",
 41       "You choosed an invallid sweet!",
 42       "The sweet you choosed is not available!",
 43       "You did not insert enough money to buy the sweet!",
 44       "Take the sweet.",
 45       "WARNING: You should refill the sweets!",
 46       "WARNING: You should refill the coins!",
 47       "Your menu choice was invalid.",
 48       "Please enter the number of the action you want to perform:\n"
 49         "1. Buy a sweet.\n"
 50         "2. Refill the sweets.\n"
 51         "3. Refill the coins.\n"
 52         "4. Shutdown this vending machine.",
 53       "The sweets were succesfully refilled.",
 54       "The coins were succesfully refilled."};
 55static const char input_sign = '$';
 56
 57
 58MENU_CHOICE
 59user_menu_choose (void)
 60{
 61 MENU_CHOICE choice;
 62 char  line [MAX_LINE_SIZE+1];
 63 
 64 printf ("%c ", input_sign);
 65 while (1)
 66 {
 67  fgets (line, MAX_LINE_SIZE, stdin);
 68  if (sscanf(line, "%d", (int *) &choice)) /* If we read an integer */
 69  {
 70   return (choice);
 71  }
 72  printf ("Your input was invalid. Please reenter:\n%c ", input_sign);
 73 }
 74}
 75
 76
 77void
 78user_show_message (MSG message)
 79/*
 80Input:
 81 message - The MSG which is related to the message to show
 82Output:
 83 -
 84Returns:
 85 -
 86Description:
 87 This function shows the message related to message (the input variable) to the
 88 user.
 89*/
 90{
 91 printf ("%s\n", msg_message[message]);
 92}
 93
 94
 95GET_COIN_RETURN
 96user_get_coin (MONEY *coin)
 97/*
 98Input:
 99 -
 100Output:
 101 coin - The by the user inserted coin
 102Returns:
 103 - GET_COIN_STOP: If the user is ready inserting coins (coin will be 0.0).
 104 - GET_COIN_INSERTED_COIN: If the user inserted a coin.
 105 - GET_COIN_CANCEL: If the user canceled the buy (coin will be 0.0).
 106Description:
 107 This function shows the message related to message (the input variable) to the
 108 user.
 109*/
 110{
 111 char line [MAX_LINE_SIZE+1];
 112 
 113 printf ("%c ", input_sign);
 114 while (1)
 115 {
 116  fgets (line, MAX_LINE_SIZE, stdin);
 117  if (line[0] == '\n') /* If the user is ready */
 118  {
 119   *coin = 0;
 120   return (GET_COIN_STOP);
 121  }
 122  if (sscanf(line, "%d", coin)) /* If we read an integer */
 123  {
 124   if (*coin == 0) /* If the user wants to cancel the buy */
 125   {
 126    return (GET_COIN_CANCEL);
 127   }
 128   return (GET_COIN_INSERTED_COIN);
 129  }
 130  printf ("Your input was invalid. Please reenter:\n%c ", input_sign);
 131 }
 132}
 133
 134
 135CHOOSE_SWEET_RETURN
 136user_choose_sweet ( SWEETS *sweets,
 137   SWEET **choosen_sweet )
 138/*
 139Input:
 140 sweets  - A list of all sweets.
 141Output:
 142 choosen_sweet - The choosen by the user sweet (only if the return value is OK)
 143Returns:
 144 - CANCEL: If the user wants to cancel the buy.
 145 - ADD_COINS: If the user wants to insert some extra coins.
 146 - INVALID: If the user made an invalid choice.
 147 - OK:  If the user made a vallid choice.
 148Description:
 149 This function gets the index of the choosen sweet and lets choosen_sweet point to it.
 150 It is also possible the user entered a '0' to cancel the buy, or a '#' to insert some
 151 extra coins.
 152*/
 153{
 154 char line [MAX_LINE_SIZE+1],
 155  c;
 156 int index;
 157 
 158 printf ("%c ", input_sign);
 159 fgets (line, MAX_LINE_SIZE, stdin);
 160 if (sscanf(line, "%d", &index))
 161 {
 162  if (index == 0)
 163  {
 164   return (CANCEL);
 165  }
 166  if (index < 0)
 167  {
 168   return (INVALID);
 169  }
 170  *choosen_sweet = sweets_get_first_sweet(sweets);
 171  while (--index && *choosen_sweet)
 172  {
 173   *choosen_sweet = (*choosen_sweet)->next;
 174  } 
 175  if (*choosen_sweet)
 176  {
 177   return (OK);
 178  }
 179 }
 180 /* If the user wants to insert some extra coins */
 181 if (sscanf(line, "%c", &c) && (c == '#'))
 182 {
 183  return (ADD_COINS);
 184 }
 185 return (INVALID);
 186}
 187
 188
 189void
 190user_list_sweets (SWEETS *sweets)
 191/*
 192Input:
 193 sweets - A list of all sweets
 194Output:
 195 -
 196Returns:
 197 -
 198Description:
 199 This function prints a indexed list of available sweets to the stdout. The index of
 200 a sweet is the number the user should press to choose it.
 201*/
 202{
 203 int index;
 204 SWEET *sweet;
 205 
 206 for ( index = 1, sweet = sweets_get_first_sweet(sweets);
 207  sweet;
 208  index++, sweet = sweet->next  )
 209 {
 210  if (sweet->num_sweets)
 211  {
 212   printf ("%2d. %-*s %5d ct\n", index, MAX_SWEET_NAME_SIZE, sweet->name, sweet->costs);
 213   /* Prints:
 214    *                  
 215    */
 216  }
 217 }
 218}
 219
 220
 221void
 222user_return_coins ( MONEY coin_value,
 223   int n             )
 224/*
 225Input:
 226 coin_value - The value of the coins that will be returned
 227 n  - How many times a coin will be returned
 228Output:
 229 -
 230Returns:
 231 -
 232Description:
 233 This function shows the user that coins with the value coin_value will n times be
 234 returned.
 235*/
 236{
 237 
 238 printf ("> %d time", n);
 239 if (n > 1)
 240 {
 241  printf ("s");
 242 }
 243 printf (" %d ct\n", coin_value);
 244}
 1 
***** main.c *****
  
 2/*-------------------------------------------------------------------------------
 3Name               : main.c
 4Author             : Marvin Raaijmakers
 5Description        : The main algorithm of the vending machine
 6Date of last change: 10-January-2005
 7
 8    Copyright (C) 2005 Marvin Raaijmakers
 9
 10    This program is free software; you can redistribute it and/or modify
 11    it under the terms of the GNU General Public License as published by
 12    the Free Software Foundation; either version 2 of the License, or
 13    any later version.
 14
 15    This program is distributed in the hope that it will be useful,
 16    but WITHOUT ANY WARRANTY; without even the implied warranty of
 17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 18    GNU General Public License for more details.
 19
 20    You should have received a copy of the GNU General Public License
 21    along with this program; if not, write to the Free Software
 22    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 23
 24    You can contact me at: marvin_raaijmakers(at)linux-box(dot)nl
 25    (replace (at) by @ and (dot) by .)
 26---------------------------------------------------------------------------------*/
 27#include 
 28
 29#include 
 30#include 
 31#include 
 32#include 
 33
 34CHOICE
 35choose_sweet ( SWEETS *sweets,
 36  MONEY *costs,
 37  MONEY inserted_money )
 38/*
 39Input:
 40 sweets  - The sweets to choose.
 41 inserted_money - The amount of money inserted by the user.
 42Output:
 43 sweets  - If a sweet has been bought it will be removed from sweets.
 44 costs  - The costs of the choosen sweet.
 45Returns:
 46 - CHOICE_READY:  The user has made a valid choice.
 47 - CHOICE_ADD_COINS: The user wants to insert coins.
 48 - CHOICE_CANCEL: The user wants to cancel the buy.
 49 - CHOICE_INVALID: The user has made a invalid choice.
 50Description:
 51 This function asks the user to choose a sweet from sweets. The user can also choose
 52 to insert extra coins or cancel the buy.
 53*/
 54{
 55 SWEET *choosen_sweet;
 56 
 57 user_show_message (MSG_CHOOSE_SWEET);
 58 user_list_sweets (sweets);
 59 
 60 switch (user_choose_sweet(sweets, &choosen_sweet))
 61 {
 62  case CANCEL:
 63   return (CHOICE_CANCEL);
 64   break;
 65  case ADD_COINS:
 66   return (CHOICE_ADD_COINS);
 67   break;
 68  case INVALID:
 69   user_show_message (MSG_INVALID_SWEET);
 70   return (CHOICE_INVALID);
 71   break;
 72  case OK:
 73   /* Continue this function */
 74   break;
 75 }
 76 /* If the choosen sweet is not available */
 77 if (sweet_get_number(choosen_sweet) == 0)
 78 {
 79  user_show_message (MSG_SWEET_NOT_AVAILABLE);
 80  return (CHOICE_INVALID);
 81 }
 82 
 83 *costs = sweet_get_costs(choosen_sweet);
 84 /* If the user inserted too few money */
 85 if (*costs > inserted_money)
 86 {
 87  user_show_message (MSG_NOT_ENOUGH_MONEY);
 88  return (CHOICE_INVALID);
 89 }
 90 sweet_pop (choosen_sweet);
 91 user_show_message (MSG_TAKE_SWEET);
 92 
 93 return (CHOICE_READY);
 94}
 95
 96
 97Boolean
 98must_pay_exact_amount (TUBES *tubes)
 99/*
 100Input:
 101 tubes - The tubes containing the coins
 102Output:
 103 -
 104Returns:
 105 TRUE if the user must pay the exact amount, otherwise FALSE.
 106Description:
 107 This function checks if it is possible that there are not enough coins in tubes
 108 to change, which means the user should pay the exact amount.
 109*/
 110{
 111 TUBE *tube;
 112 
 113 tube = tubes_get_first_tube (tubes);
 114 while (tube)
 115 {
 116  if ( tube_sensor_less_than_five(tube) )
 117  {
 118   return (TRUE);
 119  }
 120  tube = tube->next;
 121 }
 122 return (FALSE);
 123}
 124
 125
 126void
 127return_money ( TUBES *tubes,
 128  MONEY money   )
 129/*
 130Input:
 131 money - The total amount of money to return
 132Output:
 133 tubes - The tubes containing the money to return.
 134Returns:
 135 -
 136Description:
 137 This function proccess what coins (in tubes) to return. The sum of these coins is
 138 money.
 139*/
 140{
 141 TUBE *tube;
 142 int num_coins;
 143 Boolean ready;
 144 
 145 ready = FALSE;
 146 /* While there is still money to return and it is possible that at least
 147  * one tube contains more than 5 coins.
 148  */
 149 while (!ready && money)
 150 {
 151  ready = TRUE;
 152  tube = tubes_get_first_tube(tubes);
 153  while (tube && money)
 154  {
 155   if (tube_get_value(tube) <= money)
 156   {
 157    if ( tube_sensor_more_than_ten(tube) )
 158    {
 159     num_coins = (int) (money/tube_get_value(tube));
 160     if (num_coins > 10)
 161     {
 162      num_coins = 11;
 163     }
 164    }
 165    else if ( !tube_sensor_less_than_five(tube) )
 166    {
 167     num_coins = (int) (money/tube_get_value(tube));
 168     if (num_coins > 5)
 169     {
 170      num_coins = 5;
 171     }
 172    }
 173    else
 174    {
 175     num_coins = 0;
 176    }
 177    if (num_coins)
 178    {
 179     ready = FALSE;
 180     money -= ((MONEY)num_coins)*tube_get_value(tube);
 181     /* Show the user that we return the coins */
 182     user_return_coins (tube_get_value(tube), num_coins);
 183     /* Return the coins */
 184     while (num_coins--)
 185     {
 186      tube_return_coin (tube);
 187     }
 188    }
 189   }
 190   tube = tube->next;
 191  }
 192 }
 193}
 194
 195
 196Boolean
 197get_coins ( TUBES *tubes,
 198  MONEY *inserted_money  )
 199/*
 200Input:
 201 -
 202Output:
 203 tubes  - The tubes containing coins. Needed for adding coins to.
 204 inserted_money - The total amount of money inserted by the user.
 205Returns:
 206 TRUE if the user inserted money, otherwise (that means: when the user canceled the
 207 by) FALSE
 208Description:
 209 This function asks the user to insert coins and returns TRUE. It is also possible
 210 that the user cancels the buy. If that happends get_coins() will return FALSE.
 211*/
 212{
 213 Boolean ready,
 214  return_value;
 215 MONEY coin;
 216 TUBE *tube;
 217 
 218 ready = FALSE;
 219 *inserted_money = 0;
 220 /* Ask the user to insert coins until the user is ready */
 221 while (ready == FALSE)
 222 {
 223  if (must_pay_exact_amount(tubes))
 224  {
 225   user_show_message (MSG_PAY_EXACT_AMOUNT);
 226  }
 227  user_show_message (MSG_INSERT_COIN);
 228  switch (user_get_coin(&coin))
 229  {
 230   case GET_COIN_STOP: /* The user is ready */
 231    ready = TRUE;
 232    return_value = TRUE; /* The user did not cancel */
 233    break;
 234   case GET_COIN_INSERTED_COIN: /* The user inserted a coin */
 235    tube = find_tube(tubes, coin);
 236    /* If the inserted coin is valid */
 237    if (tube != NULL)
 238    {
 239     tube_add_coin (tube);
 240     *inserted_money += coin;
 241    }
 242    else
 243    {
 244     user_show_message (MSG_INVALID_COIN);
 245    }
 246    break;
 247   case GET_COIN_CANCEL: /* The user wants to cancel */
 248    return_money (tubes, *inserted_money);
 249    *inserted_money = 0;
 250    ready = TRUE;
 251    return_value = FALSE; /* The user did cancel */
 252    break;
 253   default:
 254    break;
 255  }
 256  
 257 }
 258 return (return_value);
 259}
 260
 261
 262void
 263buy ( TUBES *tubes,
 264 SWEETS *sweets  )
 265/*
 266Input:
 267 tubes - The tubes containing coins.
 268 sweets - The sweets to buy.
 269Output:
 270 tubes - The tubes containing coins. Needed for adding and/or removing coins from.
 271 sweets - The sweets to buy. Needed to remove sweet from.
 272Returns:
 273 -
 274Description:
 275 This function asks the user to insert coins and to choice a sweet. It is also
 276 possible that the user cancels the buy.
 277*/
 278{
 279 MONEY inserted_money,
 280  added_money,
 281  costs;
 282 Boolean ready;
 283 
 284 /* If the user inserted money */
 285 if (get_coins(tubes, &inserted_money))
 286 {
 287  ready = FALSE;
 288  /* While the user did not (choose a valid sweet, or cancel the buy) */
 289  while (ready == FALSE)
 290  {
 291   switch (choose_sweet(sweets, &costs, inserted_money))
 292   {
 293    case CHOICE_READY:
 294     return_money (tubes, inserted_money-costs);
 295     ready = TRUE;
 296     break;
 297    case CHOICE_ADD_COINS:
 298     if (get_coins(tubes, &added_money))
 299     {
 300      inserted_money += added_money;
 301     }
 302     else /* The user canceled the buy */
 303     {
 304      ready = TRUE;
 305     }
 306     break;
 307    case CHOICE_CANCEL:
 308     return_money (tubes, inserted_money);
 309     ready = TRUE;
 310    case CHOICE_INVALID:
 311     break;
 312    default:
 313     break;
 314   }
 315  }
 316 }
 317}
 318
 319
 320void
 321refill_sweets (SWEETS *sweets)
 322/*
 323Input:
 324 -
 325Output:
 326 sweets - A list of all (refilled) sweets
 327Returns:
 328 -
 329Description:
 330 This function sets the number of every sweet in sweets to SWEET_REFILL_NUMBER.
 331*/
 332{
 333 SWEET *sweet;
 334 
 335 sweet = sweets_get_first_sweet(sweets);
 336 while (sweet)
 337 {
 338  sweet_set_number (sweet, SWEET_REFILL_NUMBER);
 339  sweet = sweet->next;
 340 }
 341 user_show_message (MSG_SWEETS_REFILLED);
 342}
 343
 344
 345void
 346refill_tubes (TUBES *tubes)
 347/*
 348Input:
 349 -
 350Output:
 351 tubes - A list of all (refilled) tubes
 352Returns:
 353 -
 354Description:
 355 This function sets the number of every tube in tubes to TUBE_REFILL_NUMBER.
 356*/
 357{
 358 TUBE *tube;
 359 
 360 tube = tubes_get_first_tube(tubes);
 361 while (tube)
 362 {
 363  tube_set_num_coins (tube, TUBE_REFILL_NUM_COINS);
 364  tube = tube->next;
 365 }
 366 user_show_message (MSG_TUBES_REFILLED);
 367}
 368
 369
 370Boolean
 371need_to_refill_sweets (SWEETS *sweets)
 372/*
 373Input:
 374 sweets - A list of all sweets
 375Output:
 376 -
 377Returns:
 378 TRUE if one of the sweets in sweets is empty, otherwise FALSE.
 379Description:
 380 This function indicicates if sweets needs to be refilled.
 381*/
 382{
 383 SWEET *sweet;
 384 
 385 sweet = sweets_get_first_sweet(sweets);
 386 while (sweet)
 387 {
 388  if ( sweet_sensor_is_empty(sweet) )
 389  {
 390   return (TRUE);
 391  }
 392  sweet = sweet->next;
 393 }
 394 return (FALSE);
 395}
 396
 397
 398Boolean
 399need_to_refill_tubes (TUBES *tubes)
 400/*
 401Input:
 402 tubes - A list of all tubes
 403Output:
 404 -
 405Returns:
 406 TRUE if one of the tubes in tubes contains less than five coins, otherwise FALSE.
 407Description:
 408 This function indicicates if tubes needs to be refilled.
 409*/
 410{
 411 return ( must_pay_exact_amount(tubes) );
 412}
 413
 414
 415void
 416create_tubes (TUBES *tubes)
 417{
 418 int   count;
 419 const MONEY value[NUM_TUBES] = {5, 10, 20, 50, 100, 200};
 420 TUBE  *tube;
 421 
 422 tubes_init (tubes);
 423 for (count = 0; count < NUM_TUBES; count++)
 424 {
 425  tube = tube_new(value[count]);
 426  tubes_add (tubes, tube);
 427 }
 428}
 429
 430
 431void
 432create_sweets (SWEETS *sweets)
 433{
 434 int   count;
 435 /* NOTE: costs and name are related to each other. That means:
 436  *       A sweet named name[x], costs costs[x].
 437  */
 438 const int costs[NUM_SWEETS] = {75, 125, 150, 75, 100};
 439 const char name[NUM_SWEETS][MAX_SWEET_NAME_SIZE] = { "rolletje drop",
 440         "zakje katjesdrop",
 441         "zakje engelse drop",
 442         "rolletje pepermunt",
 443         "reep chocolade"  }; 
 444 SWEET  *sweet;
 445 
 446 sweets_init (sweets);
 447 for (count = 0; count < NUM_SWEETS; count++)
 448 {
 449  sweet = sweet_new((char *)name[count], costs[count]);
 450  sweets_add (sweets, sweet);
 451 }
 452}
 453
 454
 455int
 456main (void)
 457{
 458 TUBES tubes;
 459 SWEETS sweets;
 460 
 461 create_tubes (&tubes);
 462 create_sweets (&sweets);
 463 
 464 while (1)
 465 {
 466  if ( need_to_refill_sweets(&sweets) )
 467  {
 468   user_show_message (MSG_REFILL_SWEETS);
 469  }
 470  if ( need_to_refill_tubes(&tubes) )
 471  {
 472   user_show_message (MSG_REFILL_TUBES);
 473  }
 474  user_show_message (MSG_MENU);
 475  switch ( user_menu_choose() )
 476  {
 477   case MENU_BUY:
 478    buy (&tubes, &sweets);
 479    break;
 480   case MENU_REFILL_SWEETS:
 481    refill_sweets (&sweets);
 482    break;
 483   case MENU_REFILL_TUBES:
 484    refill_tubes (&tubes);
 485    break;
 486   case MENU_SHUTDOWN:
 487    exit (0);
 488    break;
 489   default:
 490    user_show_message (MSG_MENU_INVALID_CHOICE);
 491    break;
 492  }
 493 }
 494}
 
 
Mijn commentaar
 
 Marvin,
 Ik ben erg onder de indruk !
 Je inzending ziet er zeer compleet en verzorgd uit.
 Ook het feit dat je er compileer instructies bj hebt gevoegd maakt je project af.
 Onduidelijk is mij wel waarom je de kleine Makefile in twee delen hebt gesplitst.
 Erg stoer om met gelinkte lijsten te werken, al vind ik dat voor zo'n klein project erg overdreven.
 Zelf gebruik ik niet graag gelinkte lijsten, dus zeker voor zo'n klein project zou ik niet op het idee komen.
 Hoewel je de meeste functies keurig documenteerd, mis ik echter een algemene geschrijving van je programma.
 Met name een deel waarin je beschrijft welke strategie je hebt bedacht om zo efficient mogelijk met je kleingeld om te springen.
 Ook had ik graag gezien dat er een wat duidelijker onderscheid was tussen het simulatie gedeelte en het besturings gedeelte.
 Het idee is n.l. dat de software daadwerkelijk zo'n automaat moet kunnen besturen.
 Al met al een zeer mooie uitwerking van de opdracht !