栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

有限状态机

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

有限状态机

#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
#include
#include
#include

#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: %drn", pSM->state, evt);
        return;
    }
    pSM->state = stateInfo->nextState;
    EVENT_HANDLE action = stateInfo->action;
    if (action == NULL) {
        printf("change state to %d. No actionrn", pSM->state);
        return;
    }
    action(&evt);    // 当前状态 + 有事件触发 ==> 跳到下个状态,同时执行回到函数
}

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

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

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

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

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

void f331(EventID *evt)
{
    printf("__func__:%s, event is: %dn", __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: %dn",
           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;
}


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/676647.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号