C++ Assignment: Constructing a State Machine. A State Machine is a powerful prog
ID: 3681475 • Letter: C
Question
C++ Assignment: Constructing a State Machine. A State Machine is a powerful programming tool that lets you control the flow of information based on different states. By keeping track of what state the system is in, and limiting what actions it can take in each state, it makes it easier to keep track of what’s happening in your system, especially if something goes wrong.
In the attached image, you’ll see a State Machine comprised of three different states, Cat, Noise, and Food, and a number of transitions between each state, arrows labeled with 1 or 2. In addition to the transitions, there are actions in each state, various words with A or B next to them.
For this program, each state has the ability to print one of two messages. For example, Cat can either print “Meow” or it can print “Ignore”. But it will only do this based on what information it’s given. In addition to printing one of those two messages, it can also change into a different state, such as Noise or Food, if it’s given another piece of information.
YOUR ASSIGNMENT, build a code that, given a string for input, can start at the “Cat” state, and perform actions until you run out of information. You’ll be turning in your code as well as the output your program states.
As an example, you start in the state “Cat” and get the following string as input: “1A1B21B”
So step by step it will follow the instructions. First is a “1” which tells it to go to the “Food” state. The second instruction is an “A” which tells it to print the word “Lemons”. The third instruction is “1” which makes it go to the “Noise” state. While in the “Noise” state it reads the fourth instruction, “B”, and prints “Thud”. The fifth instruction, “2”, causes it to change states back to the “Food” state, where it reads the sixth instruction “1”, which causes it to immediately return to the “Noise” state, and then the final instruction, “B”, makes it print “Thud” again. At this point you’re out of instructions, so the program is done reading. Thus the output of that set of instructions would read as follows:
“Lemons”
“Thud”
“Thud”
You’ll be using the following five strings as input, which should each yield output similar to as seen above. You can use the example string above to test your State Machine.
( 1 ) – “BB2AAB1A”
( 2 ) – “11B2A2B1B”
( 3 ) – “A1BB1222A”
( 4 ) – “122A22AA1A”
( 5 ) – “AA2AA2A22B”
My suggestion is that you use an enumeration declaration to make the names for your classes, so it will be easier for you (and me) to read. Also, you’ll find a ‘switch’ statement to be particularly useful when building a State Machine.
Explanation / Answer
Hey heres the code :
#include <iostream>
#include <utility>
#include <map>
#include<string>
using namespace std;
typedef enum {
Cat,
Food,
Noise
}State;
class FSM
{
public:
typedef enum {
One,
Two
}Action;
typedef void (FSM::*DoAction)(void);
FSM() {
}
void one() {
}
void two() {
}
};
struct ActionCallback
{
FSM::Action action;
FSM::DoAction callback;
ActionCallback(FSM::Action a, FSM::DoAction c) :action(a), callback(c){}
};
struct StateAction {
State state_;
FSM::Action action_;
StateAction(State state, FSM::Action action) :state_(state), action_(action){}
friend bool operator<(const StateAction& sta1, const StateAction& sta2) {
return (sta1.state_ < sta2.state_) ||
(sta1.state_ == sta2.state_ &&
sta1.action_ < sta2.action_);
}
};
class StateMachine {
public:
typedef std::map<StateAction, State> StateDiagram;
StateMachine(FSM &fsm) :fsm_(fsm) {
stateDiag_[StateAction(Cat, FSM::One)] = Food;
stateDiag_[StateAction(Cat, FSM::Two)] = Noise;
stateDiag_[StateAction(Noise, FSM::One)] = Cat;
stateDiag_[StateAction(Noise, FSM::Two)] = Food;
stateDiag_[StateAction(Food, FSM::One)] = Noise;
stateDiag_[StateAction(Food, FSM::Two)] = Cat;
//
// current state is initialized to Cat
//
currentState_ = Cat;
std::cout << "State machine initial state: " << currentState_ << std::endl;
}
void performAction(ActionCallback actionCallback) {
//
// The state machine "state" is: currentState
//
StateAction stateAction(currentState_, actionCallback.action);
if (stateDiag_.find(stateAction) == stateDiag_.end()) {
//
// Invalid state transition
//
std::cout << "You cannot perform action: "
<< actionCallback.action
<< " from state: "
<< currentState_
<< ", invalid transition!!!"
<< std::endl;
return;
}
State oldState = currentState_;
//
// Execute the action and update the state machine
//
(fsm_.*actionCallback.callback)();
currentState_ = stateDiag_[stateAction];
}
State getCurrentState(){
return currentState_;
}
State getInitialState() {
return Cat;
}
private:
StateDiagram stateDiag_;
State currentState_;
FSM fsm_;
};
int main()
{
FSM fsm;
StateMachine stateMachine(fsm);
string str;
int i = 0;
State l;
cout << "Enter string: ";
cin >> str;
while (str[i] != '')
{
if (isdigit(str[i]))
{
if (str[i] == '1')
{
stateMachine.performAction(ActionCallback(FSM::One, &FSM::one));
}
if (str[i] == '2')
{
stateMachine.performAction(ActionCallback(FSM::Two, &FSM::two));
}
}
else
{
if (str[i] == 'A')
{
l = stateMachine.getCurrentState();
if (l == 0)
{
cout << "Meow"<<endl;
}
if (l == 1)
{
cout << "Lemons"<<endl;
}
if (l == 2)
{
cout << "Boing"<<endl;
}
}
if (str[i] == 'B')
{
l = stateMachine.getCurrentState();
if (l == 0)
{
cout << "Ignore";
}
if (l == 1)
{
cout << "Cinnamon";
}
if (l == 2)
{
cout << "Thud";
}
}
}
i++;
}
getchar();
return 0;
}
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.