语言用加法实现加饭运算_「编程之美」用C语言实现状态机(超实用)
關(guān)于狀態(tài)機,基礎(chǔ)的知識點可以自行理解,講解的很多,這里主要是想寫一個有限狀態(tài)機FSM通用的寫法,目的在于更好理解,移植,節(jié)省代碼閱讀與調(diào)試時間,體現(xiàn)出編程之美。
傳統(tǒng)的實現(xiàn)方案
- if...else : 搞一大堆if else, 一個函數(shù)寫很長很長......
- swich...case : 也搞一大堆一個函數(shù)寫很長很長......
先來看看最近做的一個項目,無線通信協(xié)議實現(xiàn)的狀態(tài)機是什么樣子的:
有三種類型的事件:上層下達的命令事件;下層到達的標志和數(shù)據(jù)傳輸事件;超時定時器超時事件。有10種狀態(tài),關(guān)聯(lián)性很大,復(fù)雜了吧,這要是各種if/else的要寫到什么時候呢。
偷偷放一張討論的圖,亂七八糟形容很恰當(dāng)。
在事件中判斷狀態(tài),在狀態(tài)中判斷事件,橫豎兩種寫法的代碼都比較冗長,看起來呢也不大好,一旦增減,就又要動腦子重新梳理一遍,很累的。
怎么去寫呢?其狀態(tài)機原理:在根據(jù)當(dāng)前狀態(tài)(cur_state) 下,發(fā)生事件(event)后,轉(zhuǎn)移到下一個狀態(tài)號(nxt_state),決定執(zhí)行的動作(action)。盜用一個圖吧
這里我們首先定義一個結(jié)構(gòu)體如下:
typedef struct { State curState;//當(dāng)前狀態(tài) EventID eventId;//事件ID State nextState;//下個狀態(tài) Action action;//具體表現(xiàn)}StateTransform;我們假設(shè)有3種狀態(tài),這里可以隨意增加,狀態(tài)枚舉如下:
typedef enum { state_1=1, state_2, state_3}State;我們假設(shè)有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;具體流程:當(dāng)前狀態(tài)-有事件觸發(fā)-跳到下個狀態(tài)-具體表現(xiàn),重構(gòu)代碼
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;}狀態(tài)機實現(xiàn)如下:
void runStateMachine(StateMachine* pSM, EventID evt) { StateTransform* pTrans; pTrans = findTranss(pSM, evt); if (pTrans == NULL) { xil_printf( "CurState= %s Do not process enent: %s", pSM->state,evt); return; } pSM->state = pTrans->nextState; Action act = pTrans->action; if (act == NULL) { xil_printf( "change state to %s. No action",pSM->state); return; } act(&evt);}最后我模擬一些隨機事件,我們只需要弄清楚事件ID,狀態(tài)切換,具體表現(xiàn)就可以了,在代碼中就是填寫stateTran[] 這個表,一旦有增減事件,狀態(tài)等等,也不需要再去使用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;}最后運行結(jié)果如下
總結(jié):
狀態(tài)機應(yīng)用很廣泛,也可以鍛煉我們寫代碼的邏輯思維,看清問題的本質(zhì),寫的代碼才能賞心悅目,希望大家能夠多多指點,找到編程的樂趣,欣賞到編程之美。https://mp.weixin.qq.com/s/bI8Cjof3eO0_vHbzTwQRHQ
更多干貨內(nèi)容只需要你關(guān)注電子芯吧客微信公眾號
聲明:本文系網(wǎng)絡(luò)轉(zhuǎn)載,版權(quán)歸原作者所有。
總結(jié)
以上是生活随笔為你收集整理的语言用加法实现加饭运算_「编程之美」用C语言实现状态机(超实用)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信小程序点播插件_小程序云直播amp;
- 下一篇: mask rcnn算法原理图_基于MAS