Understanding and Implementing FSMs in C++
A Finite State Machine (FSM) is a computational model that can be in exactly one of a finite number of states at any given time.
Design a system that:
Input: 3, 5, 2, 9, 1, 4, 7, 9, ...
─────────┘ └─────────┘
sum = 10 sum = 12
Output: 10 12
| State | Description | Output/Action |
|---|---|---|
| IDLE | Waiting for first input | sum = input (initialize) |
| ACCUMULATING | Reading and summing numbers | sum += input (if not terminator) |
| OUTPUTTING | Displaying result | print sum, reset sum (output) |
enum State {
STATE_IDLE,
STATE_ACCUMULATING,
STATE_OUTPUTTING
};
State current_state = STATE_IDLE;
State next_state = STATE_IDLE;
int sum = 0;
while (true) {
// Execute current state logic
switch (current_state) {
case STATE_IDLE:
// State action (output based on state)
// Next state logic (based on input)
break;
// ... other states
}
// Update state at end of iteration
current_state = next_state;
}
#include <iostream>
using namespace std;
// Define the states
enum State {
STATE_IDLE,
STATE_ACCUMULATING,
STATE_OUTPUTTING
};
int main() {
// State variables
State current_state = STATE_IDLE;
State next_state = STATE_IDLE;
// Data variables
int sum = 0;
int input;
cout << "Enter numbers (9 to output sum, Ctrl+D to exit):" << endl;
// Main FSM loop
while (true) {
// Read input at top of loop
if (!(cin >> input)) {
break; // Exit on EOF
}
switch (current_state) {
case STATE_IDLE:
// State Action: Initialize with first value (Moore output)
sum = input;
// Next State Logic: Examine input
if (input != 9) {
next_state = STATE_ACCUMULATING;
} else {
// Edge case: first input is the terminator
next_state = STATE_OUTPUTTING;
}
break;
case STATE_ACCUMULATING:
// State Action: Add to sum (Moore output)
if (input != 9) {
sum += input;
// Next State Logic: Stay in ACCUMULATING
next_state = STATE_ACCUMULATING;
} else {
// Don't add the terminator
// Next State Logic: Move to OUTPUTTING
next_state = STATE_OUTPUTTING;
}
break;
case STATE_OUTPUTTING:
// State Action: Display result (Moore output)
cout << "Sum: " << sum << endl;
sum = 0; // Reset for next sequence
// Next State Logic: Always return to IDLE
next_state = STATE_IDLE;
break;
}
// Update state at end of loop iteration
current_state = next_state;
}
return 0;
}
| Input | Current State | State Action | Sum | Next State |
|---|---|---|---|---|
| 3 | IDLE | sum = 3 | 3 | ACCUMULATING |
| 5 | ACCUMULATING | sum += 5 | 8 | ACCUMULATING |
| 2 | ACCUMULATING | sum += 2 | 10 | ACCUMULATING |
| 9 | ACCUMULATING | (skip - terminator) | 10 | OUTPUTTING |
| (awaiting next) | OUTPUTTING | print "Sum: 10", reset | 0 | IDLE |
| 1 | IDLE | sum = 1 | 1 | ACCUMULATING |
| 4 | ACCUMULATING | sum += 4 | 5 | ACCUMULATING |
| 7 | ACCUMULATING | sum += 7 | 12 | ACCUMULATING |
| 9 | ACCUMULATING | (skip - terminator) | 12 | OUTPUTTING |
| (awaiting next) | OUTPUTTING | print "Sum: 12", reset | 0 | IDLE |
enum or enum class for states (type-safe)current_state = next_state at the end of loopnext_state explicitly in every casecurrent_state directly inside the switchbreak statement in switch cases| Type | Moore Machine | Mealy Machine |
|---|---|---|
| Output depends on | Current state only | Current state AND input |
| When actions execute | On entering a state | During transitions |
| Code pattern | Actions at start of case | Actions in transition logic |
enum + switch + state variablescurrent_state = next_state at end of loopenum State { /* define states */ };
State current_state = INITIAL_STATE;
State next_state = INITIAL_STATE;
while (running) {
switch (current_state) {
case STATE_A:
// 1. State action/output (determined by being in STATE_A)
doStateAction();
// 2. Determine next_state based on conditions
if (condition) {
next_state = STATE_B;
}
break;
case STATE_B:
// ...
break;
}
current_state = next_state; // Update at end
}