The answers here seem really complex (but accurate, nonetheless.) So here are my thoughts.
First, I like dmckee's (operational) definition of an FSM and how they apply to programming.
A finite state machine consists of a
finite number discrete of states (I
know pedantic, but still), which can
generally be represented as integer
values. In c or c++ using an
enumeration is very common.
The machine responds to a finite
number of inputs which can often be
represented with another integer
valued variable. In more complicated
cases you can use a structure to
represent the input state.
Each combination of internal state and
external input will cause the machine
to:
- possibly transition to another state
- possibly generate some output
So you have a program. It has states, and there is a finite number of them. ("the light bulb is bright" or "the light bulb is dim" or "the light bulb is off." 3 states. finite.) Your program can only be in one state at a time.
So, say you want your program to change states. Usually, you'll want something to happen to trigger a state change. In this example, how about we take user input to determine the state - say, a key press.
You might want logic like this. When the user presses a key:
- If the bulb is "off" then make the bulb "dim".
- If the bulb is "dim", make the bulb "bright".
- If the bulb is "bright", make the bulb "off".
Obviously, instead of "changing a bulb", you might be "changing the text color" or whatever it is you program needs to do. Before you start, you'll want to define your states.
So looking at some pseudoish C code:
/* We have 3 states. We can use constants to represent those states */
#define BULB_OFF 0
#define BULB_DIM 1
#define BULB_BRIGHT 2
/* And now we set the default state */
int currentState = BULB_OFF;
/* now we want to wait for the user's input. While we're waiting, we are "idle" */
while(1) {
waitForUserKeystroke(); /* Waiting for something to happen... */
/* Okay, the user has pressed a key. Now for our state machine */
switch(currentState) {
case BULB_OFF:
currentState = BULB_DIM;
break;
case BULB_DIM:
currentState = BULB_BRIGHT;
doCoolBulbStuff();
break;
case BULB_BRIGHT:
currentState = BULB_OFF;
break;
}
}
And, voila. A simple program which changes the state.
This code executes only a small part of the switch
statement - depending on the current state. Then it updates that state. That's how FSMs work.
Now here are some things you can do:
Obviously, this program just changes the currentState
variable. You'll want your code to do something more interesting on a state change. The doCoolBulbStuff()
function might, i dunno, actually put a picture of a lightbulb on a screen. Or something.
This code only looks for a keypress. But your FSM (and thus your switch statement) can choose state based on what the user inputted (eg, "O" means "go to off" rather than just going to whatever is next in the sequence.)
Part of your question asked for a data structure.
One person suggested using an enum
to keep track of states. This is a good alternative to the #defines
that I used in my example. People have also been suggesting arrays - and these arrays keep track of the transitions between states. This is also a fine structure to use.
Given the above, well, you could use any sort of structure (something tree-like, an array, anything) to keep track of the individual states and define what to do in each state (hence some of the suggestions to use "function pointers" - have a state map to a function pointer which indicates what to do at that state.)
Hope that helps!