60. State Machine with Enums

We have already declared an enum class State with values: Idle, Busy, Error.
A helper function toString(State s) is also provided.

The system starts in State::Idle.

Your task is to process a sequence of input commands and update the system state based on the following state transition rules:

  • "start"IdleBusy
  • "done"BusyIdle
  • "fail"BusyError

If a command does not match a valid transition for the current state, it is ignored and the state remains unchanged.

Once the system enters the Error state, all further commands are ignored.

After processing all commands, print the final state.

 

Example 1

Input:

3
start done start 

Output:

Busy 

 

Example 2

Input:

2
start fail

Output:

Error 

 

 

 

 

 

 

Need Help? Refer to the Quick Guide below

In C, a standard enum is essentially a set of named integers. These names leak into the global scope (causing naming collisions) and implicitly convert to int (causing logical bugs).

In C++, enum class (also called a Scoped Enum) solves these issues.

  1. Scoped: Enum values are local to the enum (accessed via EnumName::Value).
  2. Strongly Typed: They do not implicitly convert to integer.
  3. Fixed Size: You can explicitly define the underlying integer type (e.g., uint8_t) to save memory.

Syntax & Usage

1. Basic Declaration

// C-Style (Unsafe)
enum Color { RED, GREEN, BLUE }; 
// int x = RED; // ✅ Valid but dangerous

// C++ Style (Safe)
enum class Status { 
    OK, 
    ERROR, 
    BUSY 
};

// Status s = OK;          // ❌ Error: Unknown identifier 'OK'
Status s = Status::OK;     // ✅ Correct

2. Specifying Underlying Type (Crucial for Embedded)

You can force the enum to use a specific integer size instead of the compiler default (usually int / 4 bytes).

// Force use of 8-bit integer (1 byte)
enum class State : uint8_t {
    IDLE = 0,
    RUNNING = 1,
    FAULT = 2
};

// sizeof(State) is now guaranteed to be 1 byte.

Comparison: Old vs New

FeatureC-Style enumC++ enum class
ScopeLeaks names to surrounding scope.Namespaces names (Enum::Value).
Type SafetyImplicitly converts to int.No implicit conversion.
ComparisonCan compare different enums (COLOR_RED == STATE_OFF).Compile Error (Safe).
SizeImplementation defined (usually int).User defined (default int).

Relevance in Embedded/Firmware

1. Saving RAM & Flash

By defining enum class State : uint8_t, you ensure that variables of this type only consume 1 byte. Standard enums often default to 32-bit (4 bytes), wasting memory in struct layouts or arrays.

2. Preventing State Machine Bugs

In C, if you have enum Motor { OFF, ON } and enum LED { OFF, ON }, the compiler errors because OFF is defined twice.

With enum class Motor and enum class LED, Motor::OFF and LED::OFF are distinct. You can never accidentally assign a Motor state to an LED variable.

3. Switch-Case Safety

Modern compilers can warn you if a switch statement on an enum class does not handle all possible cases, ensuring you don't miss a new state added later.

Common Pitfalls (Practical Tips)

PitfallDetails
❌ Implicit Int Casting

int x = State::IDLE; fails. You must use explicit casting:

int x = static_cast<int>(State::IDLE);

❌ Bitwise Flagsenum class does not support `
✅ Usage RuleUse enum class for distinct states (State Machines, Error Codes). Use old enum or namespace constants for bitmasks.
✅ Validating Inputs

Just because it's an enum class doesn't mean the value is valid.

State s = static_cast<State>(99); is valid code but undefined logic. Always validate raw data before casting to an enum.