C/C++用狀態跳躍表聯合函數指標數組實現狀態機器FSM

來源:互聯網
上載者:User

標籤:狀態機器   函數指標   c++   c   枚舉   

狀態機器在工程中使用非常的頻繁,有如下常見的三種實現方法:
1. switch-case 實現,適合簡單的狀態機器;
2. 二維狀態表state-event實現,邏輯清晰,但是矩陣通常比較稀疏,而且維護麻煩;
3. 用狀態跳躍表stateTransfer Table實現,數組大小等於狀體轉移邊個數,易擴充;
下面用一個例子來進行詳細說明,描述的如下情境:

描述對象:門
狀態:開著、關著、鎖著 (這裡的關著指關了但未鎖的狀態)
事件:開門、關門、上鎖、解鎖

代碼實現用枚舉來定義狀態和事件,操作資料節點轉移到目的狀態用函數實現。枚舉本身預設是從0開始的int類型,利用這個特點將狀態轉移函數放到函數指標數組中與狀態對應起來,方便操作。
核心資料結構如下:

狀態:枚舉類型
事件:枚舉類型
狀態轉移結構體:{目前狀態、事件、下個狀態},定義一個全域數組來使用
狀態變更函數:到下個狀態(放到數組中與狀態枚舉對應起來)

此種實現方法容易擴充,增加狀態和事件都比較容易。如果存在一個狀態通過對應事件可以轉移到多個狀態的情形,則可以擴充狀態轉移函數,或者在狀態轉移結構中增加一個判斷函數欄位。
代碼實現如下:

#include <iostream>using namespace std;typedef enum{    OPENED,    CLOSED,    LOCKED,}  State;typedef enum{    OPEN,    CLOSE,    LOCK,    UNLOCK} Event;typedef struct{    State currentState;    Event event;    State NextState;} StateTransfer;typedef struct{    State state;    int transferTimes;}Door;StateTransfer g_stateTransferTable[]{    {OPENED, CLOSE,  CLOSED},    {CLOSED, OPEN,   OPENED},    {CLOSED, LOCK,   LOCKED},    {LOCKED, UNLOCK, CLOSED},};void toOpen(Door& door);void toClose(Door& door);void toLock(Door& door);typedef void (*pfToState)(Door& door);pfToState g_pFun[] = {toOpen, toClose, toLock}; //狀態枚舉值對應下標void toOpen(Door& door){    door.state = OPENED;    cout << "open the door!\n";}void toClose(Door& door){    door.state = CLOSED;    cout << "close the door!\n";}void toLock(Door& door){    door.state = LOCKED;    cout << "lock the door!\n";}void transfer(Door& door,const Event event){    for (int i = 0; i < sizeof(g_stateTransferTable)/sizeof(StateTransfer); ++i) {        if(door.state == g_stateTransferTable[i].currentState &&           event == g_stateTransferTable[i].event){            g_pFun[g_stateTransferTable[i].NextState](door);            door.transferTimes++;            cout << "transfer ok!\n";            return;        }    }    cout << "This event cannot transfer current state!!\n";    return;}void printDoor(const Door& door){    string stateNote[] = {"opened","closed","locked"}; // 下標正好對應狀態枚舉值    cout << "the door‘s state is: " << stateNote[door.state] << endl;    cout << "the door transfer times is: " << door.transferTimes << endl;}int main(){    Door door = {CLOSED, 0};    printDoor(door);    transfer(door, OPEN);    printDoor(door);    transfer(door, LOCK);    printDoor(door);    transfer(door, CLOSE);    printDoor(door);    return 0;}

運行結果如下:

the door’s state is: closed
the door transfer times is: 0
open the door!
transfer ok!
the door’s state is: opened
the door transfer times is: 1
This event cannot transfer current state!!
the door’s state is: opened
the door transfer times is: 1
close the door!
transfer ok!
the door’s state is: closed
the door transfer times is: 2

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。[http://blog.csdn.net/thisinnocence]

C/C++用狀態跳躍表聯合函數指標數組實現狀態機器FSM

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.