C語言最優狀態機規范


 

 

 

typedef unsigned char State; typedef State(*Procedure)(void *);

這樣就可以方便地定義一個函數指針數組:

Procedure Steps[] = { step_init, step_count, step_done, step_default };

step_init,step_count等是函數名,再定義狀態:

enum states{ s_init, s_count, s_done, s_default };

枚舉定義對應着{0,1,2,3},有了這些再狀態機聯系那么可以想到,數組的索引就是狀態定義,上核心代碼,兩行(簡單吧!關鍵是想到):

void BestStateMachine(void * invar) {

static State NS = s_init; //定義下一狀態

NS = Steps[NS](invar);

}

static的變量NS在每次BestStateMachine調用會得到維護,我們只需再每Steps返回下一個狀態並保存到NS中可以實現狀態的保存和切換。再說說為什么要加個void*的參數,狀態機一般有很多自身變量的維護,而且對於mealy狀態機還需根據輸入判斷,因為函數調用返回是不保留局部變量的,那么就需要將變量傳遞來實現更改和保存,之所以只用了一個void*參數是因為,如果需要保存和傳遞的變量很多,直接傳遞會在調用函數是浪費大量的棧空間,且效率低下,采用這種模式,你可以將變量用一個結構體封裝,然后將結構體指針傳遞給void *的形參,再函數內部再強制轉換即可使用結構體內部的變量。現在你已經在嘀咕這作者真啰嗦,好上實例代碼,就是一個簡單的計數器(以前學狀態機都從計數器開始),在計數完成打印信息:

#include<stdio.h> typedef unsigned char State; typedef State(*Procedure)(void *); enum states{ s_init, s_count, s_done, s_default };//狀態定義 typedef struct _SM_VAR //對狀態機參數封裝 { int cnt; }SM_VAR; State step_init(void * arg)//初始化 { SM_VAR *p = (SM_VAR *)arg; p->cnt = 0; printf("CS:init ;cnt=%d;NS:count\n", p->cnt); return s_count; } State step_count(void * arg)//計數 { SM_VAR *p = (SM_VAR *)arg; if (p->cnt < 3){ p->cnt+=1; printf("CS:count;cnt=%d;NS:count\n", p->cnt); return s_count; } else{ printf("CS:count;cnt=%d;NS:done\n", p->cnt); return s_done; } } State step_done(void * arg)//計數完成 { SM_VAR *p = (SM_VAR *)arg; printf("CS:done ;cnt=%d;NS:init\n", p->cnt); return s_init; } State step_default(void * arg)//錯誤過程 { SM_VAR *p = (SM_VAR *)arg; printf("Wrong State\n"); return s_init; } Procedure Steps[] = { step_init, step_count, step_done, step_default }; void BestStateMachine(void * invar) { static State NS = s_init; //定義下一狀態 NS = Steps[NS](invar); } int main(void) { SM_VAR var; int i; for (i = 0; i <8; i++){//給狀態機8個周期的時鍾驅動 BestStateMachine(&var); } return 0; }

最后在VS2013上調試如下:

CS:init ;cnt=0;NS:count CS:count;cnt=1;NS:count CS:count;cnt=2;NS:count CS:count;cnt=3;NS:count CS:count;cnt=3;NS:done CS:done ;cnt=3;NS:init CS:init ;cnt=0;NS:count CS:count;cnt=1;NS:count 請按任意鍵繼續. . .

總結

以這種模式不僅可以實現上面的Moore型狀態機,還可根據實際實現Mealy型狀態機,結構清晰易懂,在這里我敢說最優,是因為這是C函數式編程的極限了,如果你有更好的想法聯系我,郵箱:869119842@qq.com,唐童鞋。如果你對嵌入式GUI感興趣,我們可以一起探討寫出我們自己的GUI。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM