有限状态机

#if 0
【状态机】
1、什么是状态机
2、有限状态机
3、状态机的2中类型
4、状态机的主要用途
5、状态机解决了什么问题
6、C语言实现状态机实例

1、什么是状态机
    状态机最初应用在数字电路设计领域,适合描述有先后顺序或者有逻辑规律的事情;
    状态机的本质:对有逻辑顺序,或时序规律事件的一种描述方法;
        状态机通过响应一系列事件而运行;当到达终态,状态机停止运行。
    即:事务的状态在某事件的触发下,从其中的一个状态切换到另一个状态,直到到达终态。
2、有限状态机
    有限个状态值,这个机器同时能够从外部接收事件和信息输入,机器在接收到外部输入的事件后,综合考虑当前自己的状态和用户输入的信息,然后机器做出动作:跳转到另一个状态。
    状态机的关键点:当前状态、外部输入、下一状态。
    比如:水、水蒸气、冰三态之间转换。
3、状态机的2种类型
    moore型状态机:输出只与当前状态有关(与输入信号无关);
    mealy型状态机:输出不只和当前态有关,海域输入信号有关。
    (注:输出即跳转到下一状态)
4、状态机的主要用途
    数字电路设计中
    软件设计:(框架类型的设计:如消息机制,操作系统的GUI机制)
5、状态机解决了什么问题
    传统应用程序的控制流程都是基于顺序的,即遵循事先设置好逻辑,从头到尾执行,很少有事件(异常事件或者终端)能够改变标准执行流程;
    状态机能够解决:应用程序是由外部发生的事件来驱动;即:事件在应用程序之外生成,无法由应用程序或程序员来控制,具体需要执行代码取决于接受到的事件,或者它相对于其他事件的抵达时间。
6、C语言实现状态机实例
    1)软件实现一个序列检测器电路,功能是检测出串行输入数据中的4位二进制是0101时,输出为1,某则输出为0;注意:考虑序列重叠的可能性,比如:010101,相当于出现2个0101
    2)开锁状态机:用户连续输入正确的密码则会开锁,否则退回到初始状态,要求用户重新输入密码。
    
#endif


#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define EVENT_COUNT 15

// 状态机的状态枚举如下:
typedef enum {
    state_1 = 1,
    state_2,
    state_3
} State;

// 事件ID枚举如下:
typedef enum{
    event_1 = 1,
    event_2,
    event_3,
    event_4,
    event_5
} EventID;

// 定义一个某状态下,处理某事件的函数指针
typedef void (*EVENT_HANDLE)(EventID *evt);

// 状态迁移结构体如下:
typedef struct {
    State curState;        //当前状态
    EventID eventId;    //事件ID
    State nextState;    //下个状态
    EVENT_HANDLE action;//具体表现
} StateTransform;

// 将“状态迁移结构体”封装在StateMachine中:
typedef struct{
    State state;
    int transNum;
    StateTransform *transform;
} StateMachine;

// 当前状态 + 有事件触发 ==> 跳到下个状态,同时执行回到函数;
// 此处是获取 状态迁移结构信息,若未找到,则返回NULL
StateTransform* FindStateRunInfo(StateMachine* pSM,  const EventID evt)
{
    int i;
    for (i = 0; i < pSM->transNum; i++) {
        if ((pSM->transform[i].curState == pSM->state) &&
            (pSM->transform[i].eventId == evt)) {
            return &pSM->transform[i];
        }
    }
    return NULL;
}

// 状态机实现如下:
void RunStateMachine(StateMachine *pSM, EventID evt)
{
    StateTransform *stateInfo;
    stateInfo = FindStateRunInfo(pSM, evt);
    if (stateInfo == NULL) {
        printf("CurState= %d, Do not process enent: %d\r\n", pSM->state, evt);
        return;
    }
    pSM->state = stateInfo->nextState;
    EVENT_HANDLE action = stateInfo->action;
    if (action == NULL) {
        printf("change state to %d. No action\r\n", pSM->state);
        return;
    }
    action(&evt);    // 当前状态 + 有事件触发 ==> 跳到下个状态,同时执行回到函数
}

void f121(EventID *evt)
{
    printf("__func__:%s, event is: %d\n", __func__, *evt);    
}

void f231(EventID *evt)
{
    printf("__func__:%s, event is: %d\n", __func__, *evt);    
}

void f221(EventID *evt)
{
    printf("__func__:%s, event is: %d\n", __func__, *evt);    
}

void f311(EventID *evt)
{
    printf("__func__:%s, event is: %d\n", __func__, *evt);    
}

void f321(EventID *evt)
{
    printf("__func__:%s, event is: %d\n", __func__, *evt);    
}

void f331(EventID *evt)
{
    printf("__func__:%s, event is: %d\n", __func__, *evt);    
}

// 最后模拟一些随机事件,我们只需要弄清楚事件ID,状态切换,具体表现就可以了,
// 在代码中就是填写stateTran[]这个表,一旦有增减事件,状态等等, 其代码如下:
int main(void)
{
    StateMachine stateMachine;
    (void)memset(&stateMachine, 0, sizeof(stateMachine));
    stateMachine.state = state_1;
    stateMachine.transNum = 7;
    StateTransform stateTran[] = {
        { state_1, event_3, state_2, f121 },
        { state_1, event_4, state_2, NULL },
        { state_2, event_1, state_3, f231 },
        { state_2, event_4, state_2, f221 },
        { state_3, event_2, state_1, f311 },
        { state_3, event_3, state_2, f321 },
        { state_3, event_5, state_3, f331 }
    };
    stateMachine.transform = stateTran;
    printf("state machine first state: %d, transNum: %d\n",
           stateMachine.state, stateMachine.transNum);

    EventID inputEvent[EVENT_COUNT] = {
        event_1, event_2, event_3, event_4, event_5,
        event_1, event_2, event_3, event_4, event_5,
        event_1, event_2, event_3, event_4, event_5
    };

    int i;
    for (i = 0; i < EVENT_COUNT; i++) {
        RunStateMachine(&stateMachine, inputEvent[i]);
    }
    return 0;
}


/*
执行结果:
[zll@zll 6_weiXin_Exp]$ ./a.out 
state machine first state: 1, transNum: 7
CurState= 1, Do not process enent: 1
CurState= 1, Do not process enent: 2
__func__:f121, event is: 3
__func__:f221, event is: 4
CurState= 2, Do not process enent: 5
__func__:f231, event is: 1
__func__:f311, event is: 2
__func__:f121, event is: 3
__func__:f221, event is: 4
CurState= 2, Do not process enent: 5
__func__:f231, event is: 1
__func__:f311, event is: 2
__func__:f121, event is: 3
__func__:f221, event is: 4
CurState= 2, Do not process enent: 5
[zll@zll 6_weiXin_Exp]$ 

*/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值