您现在的位置是:亿华云 > IT科技类资讯

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

亿华云2025-10-03 06:42:24【IT科技类资讯】7人已围观

简介之前写过一篇状态机的实用文章,很多朋友说有几个地方有点难度不易理解,今天给大家换种简单写法,使用函数指针的方法实现状态机。状态机简介有限状态机FSM是有限个状态及在这些状态之间的转移和动作等行为的数学

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

状态机简介

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

函数指针实现FSM

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

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

代码实现步骤

定义状态数据的枚举类型

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 f121\n"); } void f221() {      printf("this is f221\n"); } void f321() {      printf("this is f321\n"); } void f122() {      printf("this is f122\n"); } 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 }; 

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

/*状态机类型*/ 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 match\n");     } } 

附代码

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

测试程序

//编译器: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 f121\n"); } void f221() {      printf("this is f221\n"); } void f321() {      printf("this is f321\n"); } void f122() {      printf("this is f122\n"); } 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 }; /*状态机类型*/ 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 match\n");     } } int main() {      fsmType pType;     fsmRegist(&pType,fTable);     pType.curState = state_1;     pType.size = sizeof(fTable)/sizeof(StateTable);     printf("init state:%d\n\n",pType.curState);     fsmEventHandle(&pType,event_1);     printf("state:%d\n\n",pType.curState);     fsmEventHandle(&pType,event_2);     printf("state:%d\n\n",pType.curState);     fsmEventHandle(&pType,event_3);     printf("state:%d\n\n",pType.curState);     fsmEventHandle(&pType,event_4);     printf("state:%d\n\n",pType.curState);     fsmEventHandle(&pType,event_2);     printf("state:%d\n\n",pType.curState);     return 0; } 

编译结果

总结

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

网站模板

很赞哦!(58)