C語言狀態機器模板

來源:互聯網
上載者:User

標籤:

轉載聲明:如果轉載本部落格內容,請聯絡[email protected],獲得作者書面授權。

前言

上一篇我的部落格中探討了一種非swtich-case結構的狀態機器寫法,但是個人感覺寫起來比較麻煩,如果增加一個狀態,需要手動地在函數指標數組中添加相應的功能函數,而且狀態函數的也必須寫在函數指標數組前面導致代碼結構較差,如果寫在後面,又要在前面聲明,就更麻煩了,總之,不易維護,想到Adam Dunkels在LwIP中逆天的宏定義用法,使得代碼有自動更新的功能,於是也嘗試著套用下其寫法,現在這段代碼更易維護,可做模板使用。

實現

還是上一篇部落格的例子,只是多了些宏定義,這次先定義個狀態列表:

#define STATE_LIST(_) _(init)_(count)_(done)_(dft)

可能你覺得奇怪,那麼先別急,看下一段定義:

#define DEFINE_STATE(state) State##_##state,enum States {    STATE_LIST(DEFINE_STATE)    State_Nums};#undef DEFINE_STATE

對於初學者可能已經暈了,其實你只需記住宏就是替換,就能理解,下面我先展開States中第一層(注意逗號不可少):

enum States {    DEFINE_STATE(init),    DEFINE_STATE(count),    DEFINE_STATE(done),    DEFINE_STATE(dft),    State_Nums};

接下來根據DEFINE_STATE展開宏(##起串連Token的作用),則有:

enum States {    State_init,    State_count,    State_stop,    State_dft,    State_Nums};

這樣我們得到了一個完整的狀態枚舉,運用此方法可聲明狀態函數,並將聲明的狀態函數存入函數指標數組中,你的狀態函數也不會有位置限制,完整代碼如下:

#include<stdio.h>typedef unsigned char State;typedef State(*Procedure)(void *);//狀態列表,狀態增減只在此處按格式寫入#define STATE_LIST(_) _(init)_(count)_(done)_(dft)#define Step_NULL ((void *)0)//狀態執行函式宣告,你的函數必須遵循如Step_init的格式//並必須返回下一狀態如State_init#define STATEMENT_STEP(state) State Step##_##state(void * arg);STATE_LIST(STATEMENT_STEP)#undef STATEMENT_STEP//狀態枚舉#define DEFINE_STATE(state) State##_##state,enum States {    STATE_LIST(DEFINE_STATE)    State_Nums};#undef DEFINE_STATE//狀態執行函數尋找表#define STATE_PROCEDURE(State) Step##_##State,Procedure Steps[] = {    STATE_LIST(STATE_PROCEDURE)    Step_NULL};#undef STATE_PROCEDUREtypedef struct _SM_VAR  //對狀態機器參數封裝{    int cnt;}SM_VAR;void BestStateMachine(void * invar){    static State NS = State_init; //定義下一狀態    NS = Steps[NS](invar);}int main(void){    SM_VAR var;    int i;    for (i = 0; i <= 8; i++){        BestStateMachine(&var);    }    return 0;}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 State_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 State_count;    }    else{        printf("CS:count;cnt=%d;NS:done\n", p->cnt);        return State_done;    }}State Step_done(void * arg)//計數完成{    SM_VAR *p = (SM_VAR *)arg;    printf("CS:done ;cnt=%d;NS:init\n", p->cnt);    return State_init;}State Step_dft(void * arg)//錯誤過程{    SM_VAR *p = (SM_VAR *)arg;    printf("Wrong State\n");    return State_init;}

在VS2013調試,輸出結果和上一篇部落格一樣,你現在一定會發現代碼修改變得異常簡單,你只需在STATE_LIST定中增減狀態,宏就會幫你完成後面一切,而且你的狀態函數可以放在任意位置,唯一需要注意的是函數名必須遵循定義個格式,且狀態引用名也必須遵循定義個格式,不過既然是模板就有相應格式,遵循即可。

總結

不多說了,由此模板,狀態機器編寫變得異常簡單,你可以將注意完全轉移到狀態機器的運行,而不必考慮其他的事。郵箱:[email protected] 唐童鞋^_^

C語言狀態機器模板

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.