C函数指针状态机实现
C函数指针状态机实现
有限状态机(finite state machine)简称FSM,表示有限个状态及在这些状态之间的转移和动作等行为的数学模型,在计算机领域有着广泛的应用。FSM是一种逻辑单元内部的一种高效编程方法,在服务器编程中,服务器可以根据不同状态或者消息类型进行相应的处理逻辑,使得程序逻辑清晰易懂。
#include <stdio.h>
//函数指针实现FSM
enum year_state
{
SPRING = ,
SUMMER,
AUTUMN,
WINTER
};
enum year_event
{
EVENT1 = ,
EVENT2,
EVENT3,
EVENT4
};
typedef struct FsmTable_s
{
int event; // 事件
int CurState; // 当前状态
void (*eventActFun)(); //函数指针
int nextState; // 下一个状态
} FsmTable_t;
void spring_thing()
{
printf("this is spring\n");
}
void summer_thing()
{
printf("this is summer\n");
}
void autumn_thing()
{
printf("this is autumn\n");
}
void winter_thing()
{
printf("this is winter\n");
}
FsmTable_t year_table[] =
{
//{到来的事件,当前的状态,将要要执行的函数,下一个状态}
{ EVENT1, SPRING, summer_thing, SUMMER },
{ EVENT2, SUMMER, autumn_thing, AUTUMN },
{ EVENT3, AUTUMN, winter_thing, WINTER },
{ EVENT4, WINTER, spring_thing, SPRING },
//add your codes here
};
typedef struct FSM_s
{
int curState;//当前状态
FsmTable_t * pFsmTable;//状态表
int size;//表的项数
} FSM_t;
/*状态机注册,给它一个状态表*/
void FSM_Regist(FSM_t *pFSM, FsmTable_t *pFsmTable)
{
pFSM->pFsmTable = pFsmTable;
}
/*状态迁移*/
void FSM_StateTransfer(FSM_t* pFsm, int state)
{
pFsm->curState = state;
}
/*事件处理*/
void FSM_EventHandle(FSM_t* pFsm, int event)
{
FsmTable_t* pActTable = pFsm->pFsmTable;
void (*eventActFun)() = NULL; //函数指针初始化为空
int NextState;
int CurState = pFsm->curState;
int g_max_num = pFsm->size;
; //标识是否满足条件
int i;
; i < g_max_num; i++)
{
if (event == pActTable[i].event && CurState == pActTable[i].CurState)
{
flag = ;
eventActFun = pActTable[i].eventActFun;
NextState = pActTable[i].nextState;
break;
}
}
if (flag)
{
if (eventActFun)
{
eventActFun();
}
FSM_StateTransfer(pFsm, NextState);
}
else
{
printf("There is no match\n");
}
}
int main()
{
FSM_t year_fsm;
FSM_Regist(&year_fsm, year_table);
year_fsm.curState = SPRING;
year_fsm.size = sizeof(year_table)/sizeof(FsmTable_t);
printf("\n-------1--init spring------\n");
printf("state:%d\n",year_fsm.curState);
printf("\n-------2--spring->summer------\n");
FSM_EventHandle(&year_fsm,EVENT1);
printf("state:%d\n",year_fsm.curState);
printf("\n-------3--summer->autumn------\n");
FSM_EventHandle(&year_fsm,EVENT2);
printf("state:%d\n",year_fsm.curState);
printf("\n-------4--autumn->winter------\n");
FSM_EventHandle(&year_fsm,EVENT3);
printf("state:%d\n",year_fsm.curState);
printf("\n-------5--winter->spring------\n");
FSM_EventHandle(&year_fsm,EVENT4);
printf("state:%d\n",year_fsm.curState);
printf("\n-------6--receive EVENT2 not EVENT1------\n");
FSM_EventHandle(&year_fsm,EVENT2);
printf("state:%d\n",year_fsm.curState);
}
C函数指针状态机实现的更多相关文章
- C/C++用状态转移表联合函数指针数组实现状态机FSM
状态机在project中使用很的频繁,有例如以下常见的三种实现方法: 1. switch-case 实现.适合简单的状态机. 2. 二维状态表state-event实现.逻辑清晰.可是矩阵通常比較稀疏 ...
- C++虚函数和函数指针一起使用
C++虚函数和函数指针一起使用,写起来有点麻烦. 下面贴出一份示例代码,可作参考.(需要支持C++11编译) #include <stdio.h> #include <list> ...
- 为什么 C++ 中成员函数指针是 16 字节?
当我们讨论指针时,通常假设它是一种可以用 void * 指针来表示的东西,在 x86_64 平台下是 8 个字节大小.例如,下面是来自 维基百科中关于 x86_64 的文章 的摘录: Pushes a ...
- C++函数指针总结
学习c++的过程中,指针是难点,熟悉了指针之后,还有一个让人很蛋疼的难点,那就是函数指针了.本博文详细介绍一下常见的各种坑爹的函数指针. 至于指针的详细学习,推荐这篇博文C++指针详解 与数据一样,函 ...
- C与指针(结构体指针,函数指针,数组指针,指针数组)定义与使用
类型 普通指针 指针数组(非指针类型) 数组指针 结构体指针 函数指针 二重指针 定义方式 int *p; int *p[5]; int (*p)[5]; int a[3][5]; struct{.. ...
- 结构体内嵌函数指针实现C语言面向对象
结构体内嵌函数指针 #include<stdio.h> void say(int age) { printf("我%d岁了\n",age); } struct stud ...
- 用typedef定义函数指针的问题
在学习windows API的时候,遇到下面这段代码 以前见过的typedef的用法都是给一个数据类型取一个别名 typedef oldTypeName newTypeName 这种给数据类型 ...
- 你必须知道的指针基础-7.void指针与函数指针
一.不能动的“地址”—void指针 1.1 void指针初探 void *表示一个“不知道类型”的指针,也就不知道从这个指针地址开始多少字节为一个数据.和用int表示指针异曲同工,只是更明确是“指针” ...
- objective-c中的@selector()和 c /c++的函数指针
先看tomcat里用到的代码: //然后开始动画 //把图片放到animationImages,接受数组参数 self.tom.animationImages = arrayImage; //设置时间 ...
随机推荐
- linux初学者-文件管理篇
linux初学者-文件管理篇 linux系统的所有东西都是以文件的形式存储在计算机中的,所以linux系统中对文件的管理非常重要.以下介绍一些文件管理的常用方法. 1.文件的建立 文件的建立或者修改文 ...
- iOS 类知乎”分页”效果的实现?
我们先看张gif图看一下效果(LICEcap录制的有点卡, 凑合看) 好像还是卡, 怼个视频演示链接吧: https://m.weibo.cn/1990517135/4398431764047996 ...
- TestNG中DataProvider的用法二:简单的数据驱动
@DataProvider标记的方法除了可以返回数组外,还可以返回一个Iterator,这样的好处是不用把所有的测试数据都加载到内存中,而是需要的时候就读一条. 下面的例子就使用了Iterator,然 ...
- git远程服务器回滚
1.git log查找commit hash 2.git reset --hard hash 回滚本地git库 3.git push -f origin(git仓库的url) branch名 强制提交
- FormLayout and FormData
FormLayout通过为小窗口部件创建四边的Form附加值(attachment)来进行工作,并且把这些Form附加值存储在布局数据中.一个附加值让一个小窗口部件指定的一边粘贴(attach)到父C ...
- BeanFactory体系结构
BeanFactory是Spring中非常重要的一个类,搞懂了它,你就知道了bean的初始化和摧毁过程,对于深入理解IOC有很大的帮助. BeanFactory体系结构 首先看一下使用IDEA生成的继 ...
- 小伙子,你真的清楚 JVM GC ?
序 正文 如何确定垃圾? 前面已经提到 JVM 可以采用 引用计数法 与 可达性分析算法 来确定需要回收的垃圾,我们来具体看一下这两种算法: 引用计数法 该方法实现为:给每个对象添加一个引用计数器,每 ...
- 如何在docker下安装elasticsearch(上)
一 环境 VMware® Workstation 15 Pro centos7 (1810) docker19.03.1 二 进入centos7启动dcoker systemctl start doc ...
- CentOS7.6源码编译安装PHP 7.3.8
安装步骤 PHP官网下载链接:https://www.php.net/downloads.php 1. 使用wget命令下载源码安装包 wget https://www.php.net/distrib ...
- 【Java例题】7.3 线程题3-素数线程
3.素数线程.设计一个线程子类,依次随机产生10000个随机整数(100-999):再设计另一个线程子类,依次对每一个随机整数判断是不是素数,是则显示:然后编写主类,在主函数中定义这两个线程类的线程对 ...