函数指针方法实现简单状态机(附代码)

域名2025-11-03 07:39:1527

之前写过一篇状态机的函数实用文章,很多朋友说有几个地方有点难度不易理解,指针状态今天给大家换种简单写法,实现使用函数指针的简单机附方法实现状态机。

状态机简介

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

函数指针实现FSM

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

建立相应的简单机附状态表和动作查询表 根据状态表、事件、代码动作表定位相应的函数动作处理函数 执行完成后再进行状态的切换

代码实现步骤

1.定义状态数据的枚举类型 

typedef enum {   state_1=1,   state_2,   state_3,   state_4 }State; 

2.定义事件的香港云服务器枚举类型 

typedef enum{   event_1=1,   event_2,   event_3,   event_4,   event_5 }EventID; 

3.定义状态表的数据类型 

typedef struct {     int event;   //事件     int CurState;  //当前状态     void (*eventActFun)();  //函数指针     int NextState;  //下一个状态 }StateTable; 

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

void f121() {     printf("this is f121n"); } void f221() {     printf("this is f221n"); } void f321() {     printf("this is f321n"); } void f122() {     printf("this is f122n"); } StateTable fTable[] = {     //{到来的事件,当前的指针状态状态,将要要执行的实现函数,下一个状态}     { event_1,简单机附  state_1,    f121,  event_2 },     { event_2,  state_2,    f221,  event_3 },     { event_3,  state_3,    f321,  event_4 },     { event_4,  state_4,    f122,  event_1 },     //add your code here }; 

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

/*状态机类型*/ typedef struct {     int curState;//当前状态     StateTable * stateTable;//状态表     int size;//表的代码项数 }fsmType; /*状态机注册,给它一个状态表*/ void fsmRegist(fsmType* pFsm, StateTable* pTable) {     pFsm->stateTable = pTable; } /*状态迁移*/ void fsmStateTransfer(fsmType* pFsm, int state) {     pFsm->curState = state; } /*事件处理*/ void fsmEventHandle(fsmType* pFsm, int event) {     StateTable* pActTable = pFsm->stateTable;     void (*eventActFun)() = NULL;  //函数指针初始化为空     int NextState;     int CurState = pFsm->curState;     int maxNum = pFsm->size;     int flag = 0; //标识是否满足条件     /*获取当前动作函数*/     for (int i = 0; i<maxNum; i++)     {         //当且仅当当前状态下来个指定的事件,我才执行它         if (event == pActTable[i].event && CurState == pActTable[i].CurState)         {             flag = 1;             eventActFun = pActTable[i].eventActFun;             NextState = pActTable[i].NextState;             break;         }     }     if (flag) //如果满足条件了     {         /*动作执行*/         if (eventActFun)         {             eventActFun();         }         //跳转到下一个状态         fsmStateTransfer(pFsm, NextState);     }     else     {         printf("there is no matchn");     } } 

附代码

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

测试程序

//编译器:http://www.dooccn.com/cpp/ //来源:技术让梦想更伟大 //作者:李肖遥 #include <stdio.h> typedef enum {   state_1=1,   state_2,   state_3,   state_4 }State; typedef enum{   event_1=1,   event_2,   event_3,   event_4,   event_5 }EventID; typedef struct {     int event;   //事件     int CurState;  //当前状态     void (*eventActFun)();  //函数指针     int NextState;  //下一个状态 }StateTable; void f121() {     printf("this is f121n"); } void f221() {     printf("this is f221n"); } void f321() {     printf("this is f321n"); } void f122() {     printf("this is f122n"); } StateTable fTable[] = {     //{到来的事件,当前的状态,将要要执行的函数,云南idc服务商下一个状态}     { event_1,  state_1,    f121,  event_2 },     { event_2,  state_2,    f221,  event_3 },     { event_3,  state_3,    f321,  event_4 },     { event_4,  state_4,    f122,  event_1 },     //add your code here }; /*状态机类型*/ typedef struct {     int curState;//当前状态     StateTable * stateTable;//状态表     int size;//表的项数 }fsmType; /*状态机注册,给它一个状态表*/ void fsmRegist(fsmType* pFsm, StateTable* pTable) {     pFsm->stateTable = pTable; } /*状态迁移*/ void fsmStateTransfer(fsmType* pFsm, int state) {     pFsm->curState = state; } /*事件处理*/ void fsmEventHandle(fsmType* pFsm, int event) {     StateTable* pActTable = pFsm->stateTable;     void (*eventActFun)() = NULL;  //函数指针初始化为空     int NextState;     int CurState = pFsm->curState;     int maxNum = pFsm->size;     int flag = 0; //标识是否满足条件     /*获取当前动作函数*/     for (int i = 0; i<maxNum; i++)     {         //当且仅当当前状态下来个指定的事件,我才执行它         if (event == pActTable[i].event && CurState == pActTable[i].CurState)         {             flag = 1;             eventActFun = pActTable[i].eventActFun;             NextState = pActTable[i].NextState;             break;         }     }     if (flag) //如果满足条件了     {         /*动作执行*/         if (eventActFun)         {             eventActFun();         }         //跳转到下一个状态         fsmStateTransfer(pFsm, NextState);     }     else     {         printf("there is no matchn");     } } int main() {     fsmType pType;     fsmRegist(&pType,fTable);     pType.curState = state_1;     pType.size = sizeof(fTable)/sizeof(StateTable);     printf("init state:%dnn",pType.curState);     fsmEventHandle(&pType,event_1);     printf("state:%dnn",pType.curState);     fsmEventHandle(&pType,event_2);     printf("state:%dnn",pType.curState);     fsmEventHandle(&pType,event_3);     printf("state:%dnn",pType.curState);     fsmEventHandle(&pType,event_4);     printf("state:%dnn",pType.curState);     fsmEventHandle(&pType,event_2);     printf("state:%dnn",pType.curState);     return 0; } 

编译结果 

总结

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

免费信息发布网
本文地址:http://www.bzve.cn/html/364c66098975.html
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

全站热门

显示器错误导致的电脑故障(故障原因、解决方法及预防措施)

苹果7装机教程(从零开始,让你的苹果7焕然一新)

51单片机最小系统原理图教程(从零开始学习51单片机最小系统原理图)

vivoxplay6如何连接电脑,享受便捷传输(一键连接,实现数据传输和文件管理)

如何关闭AirPlay镜像?(简易指南,告诉你如何正确关闭AirPlay镜像)

华硕飞行堡垒装机教程(华硕飞行堡垒装机教程,让你轻松组建定制游戏电脑)

联想X220的性能及用户体验(一款经典商务笔记本的全面评测与分析)

深入了解chkdsk(解读磁盘检查与修复工具chkdsk,提升计算机性能和稳定性)

友情链接

滇ICP备2023006006号-39