Finite state machine: Difference between revisions
Content added Content deleted
m (→{{header|C}}) |
|||
Line 72: | Line 72: | ||
=={{header|C}}== |
=={{header|C}}== |
||
Here is a manually-constructed table-driven finite state machine that |
Here is a manually-constructed table-driven finite state machine that is fairly general and could be adapted to different applications. |
||
<lang C> |
<lang C> |
||
#include <stdio.h> |
#include <stdio.h> |
||
#include <ctype.h> |
#include <ctype.h> |
||
#include <stdlib.h> |
|||
int main(int argc, char **argv) |
int main(int argc, char **argv) |
||
{ |
{ |
||
typedef enum State { READY, WAITING, REFUND, DISPENSE, COLLECT, QUIT |
typedef enum State { READY, WAITING, REFUND, DISPENSE, COLLECT, QUIT } State; |
||
typedef struct statechange { |
typedef struct statechange { |
||
Line 86: | Line 87: | ||
} statechange; |
} statechange; |
||
#define MAXINPUTS 3 |
|||
typedef struct FSM { |
typedef struct FSM { |
||
const State state; |
const State state; |
||
void (*Action)(void); |
|||
⚫ | |||
const int inputs; |
|||
⚫ | |||
} FSM; |
} FSM; |
||
char str[10]; |
|||
void Ready(void) { fprintf(stderr, "\nMachine is READY. (D)eposit or (Q)uit :"); scanf("%s", str); } |
|||
{ |
void Waiting(void) { fprintf(stderr, "(S)elect product or choose to (R)efund :"); scanf("%s", str); } |
||
{ |
void Refund(void) { fprintf(stderr, "Please collect refund.\n"); } |
||
{ |
void Dispense(void) { fprintf(stderr, "Dispensing product...\n"); } |
||
{ |
void Collect(void) { fprintf(stderr, "Please (C)ollect product. :"); scanf("%s", str); } |
||
void Quit(void) { fprintf(stderr, "Thank you, shutting down now.\n"); exit(0); } |
|||
const FSM fsm[] = { |
|||
{ READY, &Ready, {{'D', WAITING}, {'Q', QUIT }, {-1, READY} }}, |
|||
{ WAITING, &Waiting, {{'S', DISPENSE}, {'R', REFUND}, {-1, WAITING} }}, |
|||
{ REFUND, &Refund, {{ -1, READY} }}, |
|||
{ DISPENSE, &Dispense, {{ -1, COLLECT} }}, |
|||
{ COLLECT, &Collect, {{'C', READY}, { -1, COLLECT } }}, |
|||
{ QUIT, &Quit, {{ -1, QUIT} }}, |
|||
}; |
}; |
||
char str[10]; // hacky. from prev Rosetta Code example before rewriting. |
|||
int each; |
int each; |
||
State state = READY; |
State state = READY; |
||
for (;;) { |
|||
fsm[state].Action(); |
|||
each = 0; |
|||
if (fsm[state].table[0].in < 0 && fsm[state].table[0].out == EXIT) break; else scanf("%s", str); |
|||
while (!( ((fsm[state].table[each].in == -1) |
|||
// -1 comes last and is catchall: exit, or loop to self, on no valid input. |
|||
⚫ | |||
|| (isalpha(str[0]) && fsm[state].table[each].in == toupper(str[0]) )))) each++; |
|||
⚫ | |||
} |
|||
} while (state != EXIT); |
|||
return 0; |
return 0; |
||
} |
} |