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函数指针状态机实现的更多相关文章

  1. C/C++用状态转移表联合函数指针数组实现状态机FSM

    状态机在project中使用很的频繁,有例如以下常见的三种实现方法: 1. switch-case 实现.适合简单的状态机. 2. 二维状态表state-event实现.逻辑清晰.可是矩阵通常比較稀疏 ...

  2. C++虚函数和函数指针一起使用

    C++虚函数和函数指针一起使用,写起来有点麻烦. 下面贴出一份示例代码,可作参考.(需要支持C++11编译) #include <stdio.h> #include <list> ...

  3. 为什么 C++ 中成员函数指针是 16 字节?

    当我们讨论指针时,通常假设它是一种可以用 void * 指针来表示的东西,在 x86_64 平台下是 8 个字节大小.例如,下面是来自 维基百科中关于 x86_64 的文章 的摘录: Pushes a ...

  4. C++函数指针总结

    学习c++的过程中,指针是难点,熟悉了指针之后,还有一个让人很蛋疼的难点,那就是函数指针了.本博文详细介绍一下常见的各种坑爹的函数指针. 至于指针的详细学习,推荐这篇博文C++指针详解 与数据一样,函 ...

  5. C与指针(结构体指针,函数指针,数组指针,指针数组)定义与使用

    类型 普通指针 指针数组(非指针类型) 数组指针 结构体指针 函数指针 二重指针 定义方式 int *p; int *p[5]; int (*p)[5]; int a[3][5]; struct{.. ...

  6. 结构体内嵌函数指针实现C语言面向对象

    结构体内嵌函数指针 #include<stdio.h> void say(int age) { printf("我%d岁了\n",age); } struct stud ...

  7. 用typedef定义函数指针的问题

    在学习windows API的时候,遇到下面这段代码   以前见过的typedef的用法都是给一个数据类型取一个别名 typedef oldTypeName newTypeName   这种给数据类型 ...

  8. 你必须知道的指针基础-7.void指针与函数指针

    一.不能动的“地址”—void指针 1.1 void指针初探 void *表示一个“不知道类型”的指针,也就不知道从这个指针地址开始多少字节为一个数据.和用int表示指针异曲同工,只是更明确是“指针” ...

  9. objective-c中的@selector()和 c /c++的函数指针

    先看tomcat里用到的代码: //然后开始动画 //把图片放到animationImages,接受数组参数 self.tom.animationImages = arrayImage; //设置时间 ...

随机推荐

  1. 如何简单易懂地描述REST接口编程

    网上很多关于REST的介绍,看起来都是云里雾里的,就像在看论文一样,晦涩难懂, 这里有一个链接大概可以简单明了地描述:https://www.zhihu.com/question/28557115

  2. 给国内知名大厂提BUG有感:安全是一种意识

    前言 本周一(2019.07.22),给某知名手机“大厂”提了个安全BUG,默默修复了后,周五回复我“已忽略”,此处省略上千字的心理活动..... 做安全的朋友说这都小事,国内氛围本来就不太好,hac ...

  3. springcloud-eureka

    作者:纯洁的微笑出处:http://www.ityouknow.com/ 版权归作者所有,转载请注明出处 Eureka是Netflix开源的一款提供服务注册和发现的产品,它提供了完整的Service ...

  4. 11. Java常用类

    1. Scanner类 1.1 基本语法 java.util.Scanner 是 Java5 的新特征,我们可以通过 Scanner 类来获取用户的输入. Scanner s = new Scanne ...

  5. jdk1.8HashMap底层数据结构:散列表+链表+红黑树,jdk1.8HashMap数据结构图解+源码说明

    一.前言 本文由jdk1.8源码整理而得,附自制jdk1.8底层数据结构图,并截取部分源码加以说明结构关系. 二.jdk1.8 HashMap底层数据结构图 三.源码 1.散列表(Hash table ...

  6. Downgrade extraction on phones running Android 7/8/9

    Now it's more and more difficult for forensic tools to extract evidence from smartphone running Andr ...

  7. linux杂货铺

    vmware虚拟机克隆后网卡不能使用 解决方法如下 cat /etc/udev/rules.d/70-persistent-net.rules1.将eth0这行注释掉或者删除,这里记载的还是克隆系统时 ...

  8. 理解分布式一致性与Raft算法

    理解分布式一致性与Raft算法 永远绕不开的CAP定理 出于可用性及负载方面考虑,一个分布式系统中数据必然不会只存在于一台机器,一致性简单地说就是分布式系统中的各个部分保持数据一致 但让数据保持一致往 ...

  9. 【Java例题】5.4 子串出现的次数

    4. 输入一个字符串s,再输入另一个字符串t,在s中查找t出现的次数. package chapter5; import java.util.Scanner; public class demo4 { ...

  10. 使用阿里云oss

    写这篇博文的原因是公司有个项目需要用到阿里云来存放用户头像文件.后期软件安装版本也可能需要存进去,然后折腾了两天终于摸熟了一点皮毛,在这里给大家简单介绍下. 一.初识对象存储oss 1.进入阿里云控制 ...