版權聲明:本文爲博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連接和本聲明。html
本文連接:http://www.javashuo.com/article/p-uzjobjbw-gb.html算法
https://mp.weixin.qq.com/s/xDAfaEFY4INHzr7MFnR5dg編程
if...else : 搞一大堆if else, 一個函數寫很長很長......機器學習
swich...case : 也搞一大堆一個函數寫很長很長......函數
先來看看最近作的一個項目,無線通訊協議實現的狀態機是什麼樣子的:工具
有三種類型的事件:上層下達的命令事件;下層到達的標誌和數據傳輸事件;超時定時器超時事件。有10種狀態,關聯性很大,複雜了吧,這要是各類if/else的要寫到何時呢。學習
偷偷放一張討論的圖,亂七八糟形容很恰當。ui
在事件中判斷狀態,在狀態中判斷事件,橫豎兩種寫法的代碼都比較冗長,看起來呢也不大好,一旦增減,就又要動腦子從新梳理一遍,很累的。spa
怎麼去寫呢?其狀態機原理:在根據當前狀態(cur_state) 下,發生事件(event)後,轉移到下一個狀態號(nxt_state),決定執行的動做(action)。盜用一個圖吧3d
這裏咱們首先定義一個結構體以下:
typedef struct { State curState;//當前狀態 EventID eventId;//事件ID State nextState;//下個狀態 Action action;//具體表現} StateTransform;
咱們假設有3種狀態,這裏能夠隨意增長,狀態枚舉以下:
typedef enum { state_1=1, state_2, state_3} State;
咱們假設有5個事件,也能夠隨意增長,事件ID枚舉以下:
typedef enum{ event_1=1, event_2, event_3, event_4, event_5}EventID;
將其封裝起來在StateMachine中:
typedef struct{ State state; int transNum; StateTransform* transform; }StateMachine;
具體流程:當前狀態-有事件觸發-跳到下個狀態-具體表現,重構代碼
StateTransform* findTranss(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; }
狀態機實現以下:
StateTransformm* pTrans; pTrans = findTrans(pSM, evt); if (pTrans == NULL) { xil_printf( "CurState= %s Do not process enent: %s\r\n", pSM->state,evt); return; } pSM->state = pTrans->nextState; Action act = pTrans->action; if (act == NULL) { xil_printf( "change state to %s. No action\r\n",pSM->state); return; } act(&evt);
最後我模擬一些隨機事件,咱們只須要弄清楚事件ID,狀態切換,具體表現就能夠了,在代碼中就是填寫 stateTran[] 這個表,一旦有增減事件,狀態等等,也不須要再去使用switch/case,特費腦,其代碼以下:
int run() { StateMachine 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; EventID inputEvent[15] = { 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 < 15; i++) { runStateMachine(&stateMachine, inputEvent[i]); } return 0; }
最後運行結果以下
總結:
狀態機應用很普遍,也能夠鍛鍊咱們寫代碼的邏輯思惟,看清問題的本質,寫的代碼才能賞心悅目,但願你們可以多多指點,找到編程的樂趣,欣賞到編程之美。
推薦閱讀
關注公衆號【技術讓夢想更偉大】,獲取更多Linux/C/C++/Python/FPGA等原創技術文章。後臺免費獲取經典電子書籍和視頻資源,實時更新,原創不易,請多支持,謝謝!