用C++来实现有限状态机(附代码)

李肖遥

共 4399字,需浏览 9分钟

 ·

2022-06-27 21:12

    关注、星标公众号,直达精彩内容

来源:网络素材

整理:李肖遥


这篇文章主要为大家详细介绍了C++有限状态机的相关资料,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。


目录
  • 有限状态机四大要素

  • C++函数指针实现

  • 总结


前提:因为最近打算学设计模式的状态模式,但不是很明白有限状态机和状态模式之间的关系,索性用C++实现了一个简单案例复习了一下FSM,如果有更好的实现方法,欢迎留言


有限状态机四大要素

  • 现态:当前所处状态

  • 次态:当条件满足后,即将转移的下一个状态

  • 动作:当满足某个事件时执行的动作;动作执行完毕后可以转移到另一个状态或保持原有状态

  • 条件:转移状态所需的条件,当满足条件时,会触发一个动作或进行状态转移


C++函数指针实现

案例:学生的日常生活。

  • 学生的日常生活包含以下几个状态:起床、上学、吃午饭、做作业、睡觉;

  • 每个状态之间进行转移需要执行相应的事件。

我分为以下几个步骤来实现:

  • (1)绘制状态转移图

  • (2)创建状态转移的FSMItem类

    • 枚举:所有状态State、所有事件Event;

    • 成员变量:现态_curState、事件_event、次态_nextState

    • 成员函数:动作函数

  • (3)创建有限状态机FSM类

    • 成员变量:状态转移表vector<FSMItem*> _fsmTable

    • 成员函数:初始化状态转移表、状态转移、根据事件执行相应动作

  • (4)测试FSM

(1)绘制状态转移图

(2)FSMItem类

//FSM状态项class FSMItem{    friend class FSM;private:     //动作函数    static void getUp(){        cout << "student is getting up!" << endl;    }    static void go2School(){        cout << "student is going to school!" << endl;    }    static void haveLunch(){        cout << "student is having lunch!" << endl;    }    static void doHomework(){        cout << "student is doing homework!" << endl;    }    static void sleeping(){        cout << "student is sleeping!" << endl;    }public:    //枚举所有状态    enum State    {        GETUP = 0,        GOTOSCHOOL,        HAVELUNCH,        DOHOMEWORK,        SLEEP    };    //枚举所有事件    enum Events    {        EVENT1 = 0,        EVENT2,        EVENT3    };public:    //初始化构造函数    FSMItem(State curState, Events event, void(*action)(), State nextState)        :_curState(curState), _event(event), _action(action), _nextState(nextState) {}private:    State   _curState;      //现态    Events  _event;         //条件    void    (*_action)();   //动作    State   _nextState;     //次态};

(3)FSM类

class FSM{public:    //初始化状态机    FSM(FSMItem::State curState= FSMItem::GETUP):_curState(curState)    {        initFSMTable();    }    //状态转移    void transferState(FSMItem::State nextState)    {        _curState = nextState;    }    //根据当前状态和发生的事件,执行相应的动作,并进行状态转移    void handleEvent(FSMItem::Events event)    {        FSMItem::State  curState = _curState;   //现态        void (*action)() = nullptr;//动作        FSMItem::State nextState;  //次态        bool flag = false;        for (int i = 0; i < _fsmTable.size(); i++)        {            if (event == _fsmTable[i]->_event && curState == _fsmTable[i]->_curState)            {                flag = true;                action = _fsmTable[i]->_action;                nextState = _fsmTable[i]->_nextState;                break;            }        }        //找到对应的状态项,执行动作,转移状态        if (flag)        {            if (action)            {                action();            }            transferState(nextState);        }    }private:    //根据画的状态转移图初始化状态转移表    void initFSMTable()    {        _fsmTable.push_back(new FSMItem(FSMItem::GETUP, FSMItem::EVENT1, &FSMItem::getUp, FSMItem::GOTOSCHOOL));        _fsmTable.push_back(new FSMItem(FSMItem::GOTOSCHOOL, FSMItem::EVENT2, &FSMItem::go2School, FSMItem::HAVELUNCH));        _fsmTable.push_back(new FSMItem(FSMItem::HAVELUNCH, FSMItem::EVENT3, &FSMItem::haveLunch, FSMItem::DOHOMEWORK));        _fsmTable.push_back(new FSMItem(FSMItem::DOHOMEWORK, FSMItem::EVENT1, &FSMItem::doHomework, FSMItem::SLEEP));        _fsmTable.push_back(new FSMItem(FSMItem::SLEEP, FSMItem::EVENT2, &FSMItem::sleeping, FSMItem::GETUP));    }public:    FSMItem::State _curState;  //现态private:    vector<FSMItem*> _fsmTable;  //状态转移表};

(4)测试FSM

#include<iostream>#include<vector>using namespace std;//测试事件变换void testEvent(FSMItem::Events& event){    switch (event)    {    case FSMItem::EVENT1:        event = FSMItem::EVENT2;        break;    case FSMItem::EVENT2:        event = FSMItem::EVENT3;        break;    case FSMItem::EVENT3:        event = FSMItem::EVENT1;        break;    }}int main(){    FSM *fsm = new FSM();    auto event = FSMItem::EVENT1;    while (1)    {        cout << "event " << event << " is coming..." << endl;        fsm->handleEvent(event);        cout << "fsm current state is " << fsm->_curState << endl;        testEvent(event);    }    return 0;}

执行效果:


总结

本篇文章就到这里了,希望能够给你带来帮助,后台回复 状态机 查看状态机的更多内容!

‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧  END  ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧

关注我的微信公众号,回复“加群”按规则加入技术交流群。

点击下面图片,有星球具体介绍,新用户有新人优惠券,老用户半价优惠,期待大家一起学习一起进步。


点击“阅读原文”查看更多分享,欢迎点分享、收藏、点赞、在看。

浏览 52
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报