Finite state machine: Difference between revisions

m
Line 72:
 
=={{header|C}}==
Here is a manually-constructed table-driven finite state machine that implementsis thefairly samegeneral algorithmand ascould thebe previousadapted spaghettito codedifferent versionapplications.
<lang C>
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
 
int main(int argc, char **argv)
{
typedef enum State { READY, WAITING, REFUND, DISPENSE, COLLECT, QUIT, EXIT } State;
 
typedef struct statechange {
Line 86 ⟶ 87:
} statechange;
 
#define MAXINPUTS 3
typedef struct FSM {
const State state;
const charvoid (*promptAction)(void);
const statechange table[3MAXINPUTS]; // hacky. would be dynamicnice inif acould realbe program[] ...
const int inputs;
const statechange table[3]; // hacky. would be dynamic in a real program.
} FSM;
 
constchar FSM fsmstr[610] = {;
void Ready(void) { READY, { fprintf(stderr, "\nMachine is READY. (D)eposit or (Q)uit :",); 3scanf("%s", {{'D',str); WAITING}, {'Q', QUIT }, {-1, READY}} },
void Waiting(void) { WAITINGfprintf(stderr, "(S)elect product or choose to (R)efund :",); 3scanf("%s", {{'S',str); DISPENSE}, {'R', REFUND}, {-1, WAITING}} },
void Refund(void) { REFUNDfprintf(stderr, "Please collect refund.\nMachine is READY. (Dn")eposit; or (Q)uit :", 3, {{'D', WAITING}, {'Q', QUIT }, {-1, REFUND}} },
void Dispense(void) { DISPENSEfprintf(stderr, "Dispensing product...\nPlease (Cn")ollect; product. :", 3, {{'C', READY}, { -1, COLLECT }, {-1, DISPENSE}} },
void Collect(void) { COLLECTfprintf(stderr, "Please (C)ollect product. :",); 2scanf("%s", {{'C',str); READY}, { -1, COLLECT }, {-1, COLLECT}} },
void Quit(void) { QUIT, { fprintf(stderr, "Thank you, shutting down now.\n",); exit(0); 1, {{ -1, EXIT}, { -1, EXIT }, {-1, EXIT}} },
 
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;
State state = READY;
 
dofor (;;) {
fprintf(stderr, "%s", fsm[state].prompt); fflushAction(stderr);
each = 0;
if (fsm[state].table[0].in < 0 && fsm[state].table[0].out == EXIT) break; else scanf("%s", str);
forwhile (each = 0; each <!( ((fsm[state].inputs; table[each++)].in {== -1)
// -1 comes last and is catchall: exit, or loop to self, on no valid input.
if (fsm[state].table[each].in < 0) { state = fsm[state].table[each].out; break; }
else if || (isalpha(str[0]) && toupper(str[0]) == fsm[state].table[each].in) { state == fsmtoupper(str[state0].table[) )))) each].out++; break; }
if (fsm[state].table[each].in < 0) { state = fsm[state].table[each].out; break; }
}
} while (state != EXIT);
 
return 0;
}
Anonymous user