c状态机

https://www.jianshu.com/p/917c0fb8778b?utm_campaign=maleskine&utm_content=note&utm_medium=reader_share&utm_source=weixin&from=timeline

有限状态机(finite state machine)简称FSM,表示有限个状态及在这些状态之间的转移和动作等行为的数学模型,在计算机领域有着广泛的应用。FSM是一种逻辑单元内部的一种高效编程方法,在服务器编程中,服务器可以根据不同状态或者消息类型进行相应的处理逻辑,使得程序逻辑清晰易懂。
状态机实现的方式有多种,下面讲述三种.
1.使用if/else if语句实现的FSM
使用if/else if语句是实现的FSM最简单最易懂的方法,我们只需要通过大量的if /else if语句来判断状态值来执行相应的逻辑处理。
看看下面的例子:

include <stdio.h>

enum year_state
{
SPRING,
SUMMER,
AUTUMN,
WINTER
};

void spring_thing()
{
printf("hello spring ");
}
void summer_thing()
{
printf("hello summer ");
}
void autumn_thing()
{
printf("hello autumn ");
}
void winter_thing()
{
printf("hello winter ");
}

int main()
{
int state = SPRING;
while (1)
{
if (state == SPRING)
{
spring_thing();//相应的处理
state = SUMMER;//状态改变
}
else if (state == SUMMER)
{
summer_thing();
state = AUTUMN;
}
else if (state == AUTUMN)
{
autumn_thing();
state = WINTER;
}
else if (state == WINTER)
{
winter_thing();
state = SPRING;
}
sleep(1);
}

return 0;

}

简单易懂,这里实现了四季的更替,因为只有四种状态,所以逻辑清楚,试想如果有个几十种状态,我们的if else将会变得十分之长,维护起来很麻烦,删减和添加状态变得不方便.但是通过这个例子我们认识到状态机的内涵.
如下图:

在状态1时,遇到一个事件,此刻发生状态转换,一般在状态转换前,先要进行事件的处理,然后改变状态位.然后进入状态2,以此类推.
2.使用switch case
这种做法和if else类似,结构上更清楚一些,代码如下:

int main()
{
int state = SPRING;
while (1)
{
switch(state){
case SPRING:
spring_thing();
state = SUMMER;
break;
case SUMMER:
summer_thing();
state = AUTUMN;
break;
case AUTUMN:
autumn_thing();
state = WINTER;
break;
case WINTER:
winter_thing();
state = SPRING;
break;
default:
break;

    }
    sleep(1);
}

return 0;

}

3.函数指针实现FSM
使用函数指针实现FSM的思路:建立相应的状态表和动作查询表,根据状态表、事件、动作表定位相应的动作处理函数,执行完成后再进行状态的切换。
当然使用函数指针实现的FSM的过程还是比较费时费力,但是这一切都是值得的,因为当你的程序规模大时候,基于这种表结构的状态机,维护程序起来也是得心应手。
首先我们画出这个表

代码关键部分:

1.定义状态数据的枚举类型
enum year_state
{
SPRING = 1,
SUMMER,
AUTUMN,
WINTER
};

2.定义事件的枚举类型
enum year_event
{
EVENT1 = 1,
EVENT2,
EVENT3,
EVENT4,
};

3.定义状态表的数据类型
typedef struct FsmTable_s
{
int event; //事件
int CurState; //当前状态
void (*eventActFun)(); //函数指针
int NextState; //下一个状态
}FsmTable_t;

4.定义处理函数及建立状态表
void spring_thing()
{
printf("this is spring ");
}
void summer_thing()
{
printf("this is summer ");
}
void autumn_thing()
{
printf("this is autumn ");
}
void winter_thing()
{
printf("this is winter ");
}

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
};

5.状态机类型,及状态机接口函数
/状态机类型/
typedef struct FSM_s{
int curState;//当前状态
FsmTable_t * pFsmTable;//状态表
int size;//表的项数
}FSM_t;

/状态机注册,给它一个状态表/
void FSM_Regist(FSM_t* pFsm, FsmTable_t* pTable)
{
pFsm->pFsmTable = pTable;
}

/状态迁移/
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 flag = 0; //标识是否满足条件
int i;

/*获取当前动作函数*/
for (i = 0; i<g_max_num; 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();
    }

    //跳转到下一个状态
    FSM_StateTransfer(pFsm, NextState);
}
else
{
    printf("there is no match
");
}

}

测试程序代码为:
/state.c/

include <stdio.h>

enum year_state{
SPRING = 1,
SUMMER,
AUTUMN,
WINTER
};

enum year_event{
EVENT1 = 1,
EVENT2,
EVENT3,
EVENT4,
};

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

void spring_thing()
{
printf("this is spring ");
}
void summer_thing()
{
printf("this is summer ");
}
void autumn_thing()
{
printf("this is autumn ");
}
void winter_thing()
{
printf("this is winter ");
}

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* pTable)
{
pFsm->pFsmTable = pTable;
}

/状态迁移/
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 flag = 0; //标识是否满足条件
int i;

/*获取当前动作函数*/
for (i = 0; i<g_max_num; 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();
    }

    //跳转到下一个状态
    FSM_StateTransfer(pFsm, NextState);
}
else
{
    printf("there is no match
");
}

}

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("
-------1--init spring------
");
printf("state:%d
",year_fsm.curState);

printf("
-------2--spring->summer------
");
FSM_EventHandle(&year_fsm,EVENT1);
printf("state:%d
",year_fsm.curState);

printf("
-------3--summer->autumn------
");
FSM_EventHandle(&year_fsm,EVENT2);
printf("state:%d
",year_fsm.curState);

printf("
-------4--autumn->winter------
");
FSM_EventHandle(&year_fsm,EVENT3);
printf("state:%d
",year_fsm.curState);

printf("
-------5--winter->spring------
");
FSM_EventHandle(&year_fsm,EVENT4);
printf("state:%d
",year_fsm.curState);

printf("
-------6--receive EVENT2 not EVENT1------
");
FSM_EventHandle(&year_fsm,EVENT2);
printf("state:%d
",year_fsm.curState);

return 0;

}

结果为:
-------1--init spring------
state:1

-------2--spring->summer------
this is summer
state:2

-------3--summer->autumn------
this is autumn
state:3

-------4--autumn->winter------
this is winter
state:4

-------5--winter->spring------
this is spring
state:1

-------6--receive EVENT2 not EVENT1------
there is no match
state:1

原文地址:https://www.cnblogs.com/retry/p/11607776.html