用C语言实现有限状态自动机FSM
摘要:狀態機模式是一種行為模式,在《設計模式》這本書中對其有詳細的描述,通過多態實現不同狀態的調轉行為的確是一種很好的方法,只可惜在嵌入式環境下,有時只能寫純C代碼,并且還需要考慮代碼的重入和多任務請求跳轉等情形,因此實現起來著實需要一番考慮。本文主要為你實現一個簡單的有限狀態機,沒有考慮代碼的重入和多任務跳轉,為以后復雜的狀態機實現,打下基礎。
?本文來源:用C語言實現有限狀態自動機FSM
一、狀態機實現的要素
首先,分析一下一個普通的狀態機究竟要實現哪些內容。
狀態機存儲從開始時刻到現在的變化,并根據當前輸入,決定下一個狀態。這意味著,狀態機要存儲狀態、獲得輸入(我們把它叫做跳轉條件)、做出響應。
如上圖所示,{s1, s2, s3}均為狀態,箭頭c1/a1表示在s1狀態、輸入為c1時,跳轉到s2,并進行a1操作。
最下方為一組輸入,狀態機應做出如下反應:
| 當前狀態 | 輸入 | 下一個狀態 | 動作 |
| s1 | c1 | s2 | a1 |
| s2 | c2 | s3 | a2 |
| s3 | c1 | s2 | a3 |
| s2 | c2 | s3 | a2 |
| s3 | c1 | s2 | a3 |
| s2 | c1 | s_trap | a_trap |
| s_trap | c1 | s_trap | a_trap |
?
當某個狀態遇到不能識別的輸入時,就默認進入陷阱狀態,在陷阱狀態中,不論遇到怎樣的輸入都不能跳出。
為了表達上面這個自動機,我們定義它們的狀態和輸入類型:
| 1 2 3 4 5 6 7 8 9 10 11 12 | typedef?int?s tate; typedef?int?c ondition; #define STATES 4 #define STATE1 0 #define STATE2 1 #define STATE3 2 #define STATETRAP 3 #define CONDITIONS 2 #define CONDITION1 0 #define CONDITION2 1 |
?總結一下,我們需要定義的有狀態、輸入、行為(動作+下一個狀態),其中,行為的個數是“狀態數*輸入數量”(其中有一些是重復的);其中動作一般來說可以用一個函數指針來實現。
二、具體設計
? ? ? ?在嵌入式環境中,由于存儲空間比較小,因此把它們全部定義成宏。此外,為了降低執行時間的不確定性,我們使用O(1)的跳轉表來模擬狀態的跳轉。
首先定義跳轉類型:
| 1 2 3 4 5 6 7 | typedef?void? (*actiontype)(state mystate, condition condition); typedef?struct { ????state next; ????actiontype action; } trasition, * ptrasition; |
?
然后按照上圖中的跳轉關系,把三個跳轉加一個陷阱跳轉先定義出來:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | // (s1, c1, s2, a1) trasition t1 = { ????STATE2, ????action1 }; // (s2, c2, s3, a2) trasition t2 = { ????STATE3, ????action2 }; // (s3, c1, s2, a3) trasition t3 = { ????STATE2, ????action3 }; // (s, c, trap, a1) trasition tt = { ????STATETRAP, ????actiontrap }; |
?
其中的動作,由用戶自己完成,在這里僅定義一條輸出語句。
| 1 2 3 4 | void?action1(State state, Condition condition) { ????printf ( "Action 1 triggered.\n" ); } |
| 1 | 最后定義跳轉表: |
| 1 2 3 4 5 6 7 | ptrasition transition_table[STATES][CONDITIONS] = { /*????? c1,? c2*/ /* s1 */ &t1, &tt, /* s2 */ &tt, &t2, /* s3 */ &t3, &tt, /* st */ &tt, &tt, }; |
?
即可表達上文中的跳轉關系。
最后定義狀態機,如果不考慮多任務請求,那么狀態機僅需要存儲當前狀態便行了。例如:
| 1 2 3 4 5 6 7 8 9 10 11 12 | typedef?struct { ????State current; } StateMachine, * pStateMachine; State step(pStateMachine machine, Condition condition) { ????pTrasition t = transition_table[machine->current][condition]; ????(*(t->action))(machine->current, condition); ????machine->current = t->next; ????return? machine->current; } |
總結:我們現在設計實現好了一個狀態機,然后要給這個狀態機特定的輸入,看看狀態機的運轉情況,以上面圖中的那個狀態機為例,我們輸入的序列是0和1分別代表c1和C2,然后狀態s1,s2分別對應0,1.用程序實現這個內容如下
三、程序實現
程序清單:小型狀態機的實現 #include<stdio.h> #include<unistd.h> #include<stdlib.h> typedef int state; typedef int condition;#define STATENUM 4 #define STATE1 0 #define STATE2 1 #define STATE3 2 #define STATETRAP 3#define CONDITIONS 2 #define CONDITION1 0 #define CONDITION2 1typedef void (* actiontype)(state mystate,condition mycondition); typedef struct{state next;actiontype action; }trasition, *ptrasition;void action1(state mystate,condition myconditon); void action2(state mystate,condition myconditon); void action3(state mystate,condition myconditon); void actiontrap(state mystate,condition myconditon); trasition t1={STATE2,action1 }; trasition t2={STATE3,action2 }; trasition t3={STATE2,action3 }; trasition tt={STATETRAP,actiontrap };void action1(state mystate,condition myconditon){printf("action1 one triggered\n"); } void action2(state mystate,condition myconditon){printf("action2 one triggered\n"); } void action3(state mystate,condition myconditon){printf("action3 one triggered\n"); } void actiontrap(state mystate,condition myconditon){printf("actiontrap one triggered\n"); }ptrasition transition_table[STATENUM][CONDITIONS] = { /* c1, c2*/ /* s1 */&t1, &tt, /* s2 */&tt, &t2, /* s3 */&t3, &tt, /* st */&tt, &tt, }; typedef struct {state current; } StateMachine, * pStateMachine;state step(pStateMachine machine, condition mycondition) {ptrasition t = transition_table[machine->current][mycondition];(*(t->action))(machine->current, mycondition);machine->current = t->next;printf("the current state is %d\n",t->next );return machine->current; } int main(int argc, char *argv[]) {StateMachine mymachine;mymachine.current=STATE1;int mycon;char ch;while(1){scanf("%d",&mycon); step(&mymachine,mycon);}return 0; }
程序輸入與輸出結果示例:
四、外部參考 【1】 嵌入式設計模式:有限狀態自動機的C語言實現? http://www.cnblogs.com/autosar/archive/2012/06/22/2558604.html
總結
以上是生活随笔為你收集整理的用C语言实现有限状态自动机FSM的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Go匿名函数
- 下一篇: GPU视频解码之CUVID