服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++有限状态机实现详解

C++有限状态机实现详解

2022-01-19 13:25fenghaze C/C++

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

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

 

有限状态机四大要素

  • 现态:当前所处状态
  • 次态:当条件满足后,即将转移的下一个状态
  • 动作:当满足某个事件时执行的动作;动作执行完毕后可以转移到另一个状态或保持原有状态
  • 条件:转移状态所需的条件,当满足条件时,会触发一个动作或进行状态转移

 

C++函数指针实现

案例:学生的日常生活。

  • 学生的日常生活包含以下几个状态:起床、上学、吃午饭、做作业、睡觉;
  • 每个状态之间进行转移需要执行相应的事件。

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

  • (1)绘制状态转移图
  • (2)创建状态转移的FSMItem类
    • 枚举:所有状态State、所有事件Event;
    • 成员变量:现态_curState、事件_event、次态_nextState
    • 成员函数:动作函数
  • (3)创建有限状态机FSM类
    • 成员变量:状态转移表vector<FSMItem*> _fsmTable
    • 成员函数:初始化状态转移表、状态转移、根据事件执行相应动作
  • (4)测试FSM

(1)绘制状态转移图

C++有限状态机实现详解

(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;
}

执行效果:

C++有限状态机实现详解

 

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注服务器之家的更多内容!

原文链接:https://blog.csdn.net/qq_43067115/article/details/120659445

延伸 · 阅读

精彩推荐
  • C/C++关于C语言中E-R图的详解

    关于C语言中E-R图的详解

    今天小编就为大家分享一篇关于关于C语言中E-R图的详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看...

    Struggler095962021-07-12
  • C/C++深入C++拷贝构造函数的总结详解

    深入C++拷贝构造函数的总结详解

    本篇文章是对C++中拷贝构造函数进行了总结与介绍。需要的朋友参考下...

    C++教程网5182020-11-30
  • C/C++C语言实现双人五子棋游戏

    C语言实现双人五子棋游戏

    这篇文章主要为大家详细介绍了C语言实现双人五子棋游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    两片空白7312021-11-12
  • C/C++C语言main函数的三种形式实例详解

    C语言main函数的三种形式实例详解

    这篇文章主要介绍了 C语言main函数的三种形式实例详解的相关资料,需要的朋友可以参考下...

    ieearth6912021-05-16
  • C/C++c/c++实现获取域名的IP地址

    c/c++实现获取域名的IP地址

    本文给大家汇总介绍了使用c/c++实现获取域名的IP地址的几种方法以及这些方法的核心函数gethostbyname的详细用法,非常的实用,有需要的小伙伴可以参考下...

    C++教程网10262021-03-16
  • C/C++OpenCV实现拼接图像的简单方法

    OpenCV实现拼接图像的简单方法

    这篇文章主要为大家详细介绍了OpenCV实现拼接图像的简单方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    iteye_183805102021-07-29
  • C/C++c/c++内存分配大小实例讲解

    c/c++内存分配大小实例讲解

    在本篇文章里小编给大家整理了一篇关于c/c++内存分配大小实例讲解内容,有需要的朋友们可以跟着学习参考下。...

    jihite5172022-02-22
  • C/C++使用C++制作简单的web服务器(续)

    使用C++制作简单的web服务器(续)

    本文承接上文《使用C++制作简单的web服务器》,把web服务器做的功能稍微强大些,主要增加的功能是从文件中读取网页并返回给客户端,而不是把网页代码...

    C++教程网5492021-02-22