文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

「编程之美」函数指针方法实现简单状态机(附代码)

2024-12-02 11:17

关注

[[442452]]

状态机简介

有限状态机FSM是有限个状态及在这些状态之间的转移和动作等行为的数学模型,是一种逻辑单元内部的高效编程方法,可以根据不同状态或者消息类型进行相应的处理逻辑,使得程序逻辑清晰易懂。

函数指针实现FSM

使用函数指针实现FSM可以分为3个步骤

  1. 建立相应的状态表和动作查询表
  2. 根据状态表、事件、动作表定位相应的动作处理函数
  3. 执行完成后再进行状态的切换

代码实现步骤

定义状态数据的枚举类型

 

  1. typedef enum { 
  2.   state_1=1, 
  3.   state_2, 
  4.   state_3, 
  5.   state_4 
  6. }State; 

定义事件的枚举类型

 

  1. typedef enum{ 
  2.   event_1=1, 
  3.   event_2, 
  4.   event_3, 
  5.   event_4, 
  6.   event_5 
  7. }EventID; 

定义状态表的数据类型

 

  1. typedef struct 
  2.     int event;   //事件 
  3.     int CurState;  //当前状态 
  4.     void (*eventActFun)();  //函数指针 
  5.     int NextState;  //下一个状态 
  6. }StateTable; 

定义处理函数及建立状态表

 

  1. void f121() 
  2.     printf("this is f121\n"); 
  3. void f221() 
  4.     printf("this is f221\n"); 
  5. void f321() 
  6.     printf("this is f321\n"); 
  7.  
  8. void f122() 
  9.     printf("this is f122\n"); 
  10.  
  11. StateTable fTable[] = 
  12.     //{到来的事件,当前的状态,将要要执行的函数,下一个状态} 
  13.     { event_1,  state_1,    f121,  event_2 }, 
  14.     { event_2,  state_2,    f221,  event_3 }, 
  15.     { event_3,  state_3,    f321,  event_4 }, 
  16.     { event_4,  state_4,    f122,  event_1 }, 
  17.     //add your code here 
  18. }; 

状态机类型,及状态机接口函数

 

  1.  
  2. typedef struct { 
  3.     int curState;//当前状态 
  4.     StateTable * stateTable;//状态表 
  5.     int size;//表的项数 
  6. }fsmType; 
  7.  
  8.  
  9. void fsmRegist(fsmType* pFsm, StateTable* pTable) 
  10.     pFsm->stateTable = pTable; 
  11.  
  12.  
  13. void fsmStateTransfer(fsmType* pFsm, int state) 
  14.     pFsm->curState = state; 
  15.  
  16.  
  17. void fsmEventHandle(fsmType* pFsm, int event) 
  18.     StateTable* pActTable = pFsm->stateTable; 
  19.     void (*eventActFun)() = NULL;  //函数指针初始化为空 
  20.     int NextState; 
  21.     int CurState = pFsm->curState; 
  22.     int maxNum = pFsm->size
  23.     int flag = 0; //标识是否满足条件 
  24.  
  25.      
  26.     for (int i = 0; i
  27.     { 
  28.         //当且仅当当前状态下来个指定的事件,我才执行它 
  29.         if (event == pActTable[i].event && CurState == pActTable[i].CurState) 
  30.         { 
  31.             flag = 1; 
  32.             eventActFun = pActTable[i].eventActFun; 
  33.             NextState = pActTable[i].NextState; 
  34.             break; 
  35.         } 
  36.     } 
  37.  
  38.  
  39.     if (flag) //如果满足条件了 
  40.     { 
  41.          
  42.         if (eventActFun) 
  43.         { 
  44.             eventActFun(); 
  45.         } 
  46.  
  47.         //跳转到下一个状态 
  48.         fsmStateTransfer(pFsm, NextState); 
  49.     } 
  50.     else 
  51.     { 
  52.         printf("there is no match\n"); 
  53.     } 

附代码

代码直接复制过去就行啦,本想打包的,太麻烦了。

测试程序

 

  1. //编译器:http://www.dooccn.com/cpp/ 
  2. //来源:技术让梦想更伟大 
  3. //作者:李肖遥 
  4. #include  
  5.  
  6. typedef enum { 
  7.   state_1=1, 
  8.   state_2, 
  9.   state_3, 
  10.   state_4 
  11. }State; 
  12.  
  13. typedef enum{ 
  14.   event_1=1, 
  15.   event_2, 
  16.   event_3, 
  17.   event_4, 
  18.   event_5 
  19. }EventID; 
  20.  
  21. typedef struct { 
  22.     int event;   //事件 
  23.     int CurState;  //当前状态 
  24.     void (*eventActFun)();  //函数指针 
  25.     int NextState;  //下一个状态 
  26. }StateTable; 
  27.  
  28. void f121() 
  29.     printf("this is f121\n"); 
  30. void f221() 
  31.     printf("this is f221\n"); 
  32. void f321() 
  33.     printf("this is f321\n"); 
  34.  
  35. void f122() 
  36.     printf("this is f122\n"); 
  37.  
  38. StateTable fTable[] = 
  39.     //{到来的事件,当前的状态,将要要执行的函数,下一个状态} 
  40.     { event_1,  state_1,    f121,  event_2 }, 
  41.     { event_2,  state_2,    f221,  event_3 }, 
  42.     { event_3,  state_3,    f321,  event_4 }, 
  43.     { event_4,  state_4,    f122,  event_1 }, 
  44.     //add your code here 
  45. }; 
  46.  
  47.  
  48. typedef struct { 
  49.     int curState;//当前状态 
  50.     StateTable * stateTable;//状态表 
  51.     int size;//表的项数 
  52. }fsmType; 
  53.  
  54.  
  55. void fsmRegist(fsmType* pFsm, StateTable* pTable) 
  56.     pFsm->stateTable = pTable; 
  57.  
  58.  
  59. void fsmStateTransfer(fsmType* pFsm, int state) 
  60.     pFsm->curState = state; 
  61.  
  62.  
  63. void fsmEventHandle(fsmType* pFsm, int event) 
  64.     StateTable* pActTable = pFsm->stateTable; 
  65.     void (*eventActFun)() = NULL;  //函数指针初始化为空 
  66.     int NextState; 
  67.     int CurState = pFsm->curState; 
  68.     int maxNum = pFsm->size
  69.     int flag = 0; //标识是否满足条件 
  70.  
  71.      
  72.     for (int i = 0; i
  73.     { 
  74.         //当且仅当当前状态下来个指定的事件,我才执行它 
  75.         if (event == pActTable[i].event && CurState == pActTable[i].CurState) 
  76.         { 
  77.             flag = 1; 
  78.             eventActFun = pActTable[i].eventActFun; 
  79.             NextState = pActTable[i].NextState; 
  80.             break; 
  81.         } 
  82.     } 
  83.  
  84.  
  85.     if (flag) //如果满足条件了 
  86.     { 
  87.          
  88.         if (eventActFun) 
  89.         { 
  90.             eventActFun(); 
  91.         } 
  92.  
  93.         //跳转到下一个状态 
  94.         fsmStateTransfer(pFsm, NextState); 
  95.     } 
  96.     else 
  97.     { 
  98.         printf("there is no match\n"); 
  99.     } 
  100.  
  101. int main() 
  102.     fsmType pType; 
  103.     fsmRegist(&pType,fTable); 
  104.     pType.curState = state_1; 
  105.     pType.size = sizeof(fTable)/sizeof(StateTable); 
  106.  
  107.  
  108.     printf("init state:%d\n\n",pType.curState); 
  109.  
  110.     fsmEventHandle(&pType,event_1); 
  111.     printf("state:%d\n\n",pType.curState); 
  112.  
  113.     fsmEventHandle(&pType,event_2); 
  114.     printf("state:%d\n\n",pType.curState); 
  115.  
  116.     fsmEventHandle(&pType,event_3); 
  117.     printf("state:%d\n\n",pType.curState); 
  118.  
  119.     fsmEventHandle(&pType,event_4); 
  120.     printf("state:%d\n\n",pType.curState); 
  121.  
  122.     fsmEventHandle(&pType,event_2); 
  123.     printf("state:%d\n\n",pType.curState); 
  124.  
  125.     return 0; 

编译结果

总结

使用函数指针实现的FSM的过程还是比较费时费力的,但是这一切相对一大堆的if/else、switch/case来说都是值得的,当你的程序规模变得越来越大的时候,基于这种表结构的状态机,维护程序起来会清晰很多。

来源:今日头条内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯