欧美在线专区-欧美在线伊人-欧美在线一区二区三区欧美-欧美在线一区二区三区-pornodoxxx中国妞-pornodoldoo欧美另类

position>home>sport

函數指針方法實現簡單狀態機(附代碼)

[導讀]之前寫過一篇狀態機的函數實用文章,很多朋友說有幾個地方有點難度不易理解,指針狀態今天給大家換種簡單寫法,實現使用函數指針的簡單機附方法實現狀態機。


之前寫過一篇狀態機的代碼實用文章,很多朋友說有幾個地方有點難度不易理解,函數今天給大家換種簡單寫法,指針狀態使用函數指針的實現方法實現狀態機。

函數指針方法實現簡單狀態機(附代碼)

狀態機簡介

有限狀態機FSM是簡單機附有限個狀態及在這些狀態之間的轉移和動作等行為的數學模型,是代碼一種邏輯單元內部的高效編程方法,可以根據不同狀態或者消息類型進行相應的函數處理邏輯,使得程序邏輯清晰易懂。指針狀態

函數指針實現FSM

使用函數指針實現FSM可以分為3個步驟

  1. 建立相應的實現狀態表和動作查詢表

  2. 根據狀態表、事件、簡單機附動作表定位相應的代碼動作處理函數

  3. 執行完成后再進行狀態的切換

代碼實現步驟

  1. 定義狀態數據的枚舉類型
typedef?enum?{ 
??state_1=1,
??state_2,
??state_3,
??state_4
}State;
  1. 定義事件的枚舉類型
typedef?enum{ 
??event_1=1,
??event_2,
??event_3,
??event_4,
??event_5
}EventID;
  1. 定義狀態表的數據類型
typedef?struct
{
????int?event;???//事件
????int?CurState;??//當前狀態
????void?(*eventActFun)();??//函數指針
????int?NextState;??//下一個狀態
}StateTable;
  1. 定義處理函數及建立狀態表
void?f121()
{
????printf("this?is?f121\n");
}
void?f221()
{
????printf("this?is?f221\n");
}
void?f321()
{
????printf("this?is?f321\n");
}

void?f122()
{
????printf("this?is?f122\n");
}

StateTable?fTable[]?=
{
????//{ 到來的事件,當前的狀態,將要要執行的函數,下一個狀態}
????{ ?event_1,??state_1,????f121,??event_2?},
????{ ?event_2,??state_2,????f221,??event_3?},
????{ ?event_3,??state_3,????f321,??event_4?},
????{ ?event_4,??state_4,????f122,??event_1?},
????//add?your?code?here
};
  1. 狀態機類型,及狀態機接口函數
/*狀態機類型*/
typedef?struct?{
????int?curState;//當前狀態
????StateTable?*?stateTable;//狀態表
????int?size;//表的項數
}fsmType;

/*狀態機注冊,給它一個狀態表*/
void?fsmRegist(fsmType*?pFsm,?StateTable*?pTable)
{
????pFsm->stateTable?=?pTable;
}

/*狀態遷移*/
void?fsmStateTransfer(fsmType*?pFsm,?int?state)
{
????pFsm->curState?=?state;
}

/*事件處理*/
void?fsmEventHandle(fsmType*?pFsm,?int?event)
{
????StateTable*?pActTable?=?pFsm->stateTable;
????void?(*eventActFun)()?=?NULL;??//函數指針初始化為空
????int?NextState;
????int?CurState?=?pFsm->curState;
????int?maxNum?=?pFsm->size;
????int?flag?=?0;?//標識是否滿足條件

????/*獲取當前動作函數*/
????for?(int?i?=?0;?i????{
????????//當且僅當當前狀態下來個指定的事件,我才執行它
????????if?(event?==?pActTable[i].event?&&?CurState?==?pActTable[i].CurState)
????????{
????????????flag?=?1;
????????????eventActFun?=?pActTable[i].eventActFun;
????????????NextState?=?pActTable[i].NextState;
????????????break;
????????}
????}


????if?(flag)?//如果滿足條件了
????{
????????/*動作執行*/
????????if?(eventActFun)
????????{
????????????eventActFun();
????????}

????????//跳轉到下一個狀態
????????fsmStateTransfer(pFsm,?NextState);
????}
????else
????{
????????printf("there?is?no?match\n");
????}
}

附代碼

代碼直接復制過去就行啦,本想打包的,太麻煩了。

測試程序

//編譯器:http://www.dooccn.com/cpp/
//來源:技術讓夢想更偉大
//作者:李肖遙
#include?

typedef?enum?{
??state_1=1,
??state_2,
??state_3,
??state_4
}State;

typedef?enum{
??event_1=1,
??event_2,
??event_3,
??event_4,
??event_5
}EventID;

typedef?struct?{
????int?event;???//事件
????int?CurState;??//當前狀態
????void?(*eventActFun)();??//函數指針
????int?NextState;??//下一個狀態
}StateTable;

void?f121()
{
????printf("this?is?f121\n");
}
void?f221()
{
????printf("this?is?f221\n");
}
void?f321()
{
????printf("this?is?f321\n");
}

void?f122()
{
????printf("this?is?f122\n");
}

StateTable?fTable[]?=
{
????//{ 到來的事件,當前的狀態,將要要執行的函數,下一個狀態}
????{ ?event_1,??state_1,????f121,??event_2?},
????{ ?event_2,??state_2,????f221,??event_3?},
????{ ?event_3,??state_3,????f321,??event_4?},
????{ ?event_4,??state_4,????f122,??event_1?},
????//add?your?code?here
};

/*狀態機類型*/
typedef?struct?{
????int?curState;//當前狀態
????StateTable?*?stateTable;//狀態表
????int?size;//表的項數
}fsmType;

/*狀態機注冊,給它一個狀態表*/
void?fsmRegist(fsmType*?pFsm,?StateTable*?pTable)
{
????pFsm->stateTable?=?pTable;
}

/*狀態遷移*/
void?fsmStateTransfer(fsmType*?pFsm,?int?state)
{
????pFsm->curState?=?state;
}

/*事件處理*/
void?fsmEventHandle(fsmType*?pFsm,?int?event)
{
????StateTable*?pActTable?=?pFsm->stateTable;
????void?(*eventActFun)()?=?NULL;??//函數指針初始化為空
????int?NextState;
????int?CurState?=?pFsm->curState;
????int?maxNum?=?pFsm->size;
????int?flag?=?0;?//標識是否滿足條件

????/*獲取當前動作函數*/
????for?(int?i?=?0;?i????{
????????//當且僅當當前狀態下來個指定的事件,我才執行它
????????if?(event?==?pActTable[i].event?&&?CurState?==?pActTable[i].CurState)
????????{
????????????flag?=?1;
????????????eventActFun?=?pActTable[i].eventActFun;
????????????NextState?=?pActTable[i].NextState;
????????????break;
????????}
????}


????if?(flag)?//如果滿足條件了
????{
????????/*動作執行*/
????????if?(eventActFun)
????????{
????????????eventActFun();
????????}

????????//跳轉到下一個狀態
????????fsmStateTransfer(pFsm,?NextState);
????}
????else
????{
????????printf("there?is?no?match\n");
????}
}

int?main()
{
????fsmType?pType;
????fsmRegist(&pType,fTable);
????pType.curState?=?state_1;
????pType.size?=?sizeof(fTable)/sizeof(StateTable);


????printf("init?state:%d\n\n",pType.curState);

????fsmEventHandle(&pType,event_1);
????printf("state:%d\n\n",pType.curState);

????fsmEventHandle(&pType,event_2);
????printf("state:%d\n\n",pType.curState);

????fsmEventHandle(&pType,event_3);
????printf("state:%d\n\n",pType.curState);

????fsmEventHandle(&pType,event_4);
????printf("state:%d\n\n",pType.curState);

????fsmEventHandle(&pType,event_2);
????printf("state:%d\n\n",pType.curState);

????return?0;
}

編譯結果

總結

使用函數指針實現的FSM的過程還是比較費時費力的,但是這一切相對一大堆的if/else、switch/case來說都是值得的,當你的程序規模變得越來越大的時候,基于這種表結構的狀態機,維護程序起來會清晰很多。


免責聲明:本文內容由21ic獲得授權后發布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯系我們,謝謝!

Popular articles

主站蜘蛛池模板: 性生活大片免费看| 青青草97| 波多野结无码高清中文| 亚洲爱情岛论坛| 大学生一级片| 女人是男人的女未来1分49分| heyzo在线播放| 久草福利资源站| 国产嫩草影院在线观看| 韩国三级电影网| 韩国三级hd中文字幕| 日本成人在线免费| 欧美日本免费| 波多野结衣bt| 黄色一级片日本| 第四色亚洲色图| 最好看的免费观看视频| 日韩日韩日韩日韩日韩| 欧美日韩在线视频专区免费| 好爽好黄的视频| 青青青国产免费线在| 中文字幕在线观看国产| 日本伦理电影网伦理在线电影| 美女张开腿让男人桶爽动漫视频| 一区在线观看| 老师办公室被吃奶好爽在线观看| 老婆bd电影| 欧美zoozzooz在线观看| 开嫩苞破呦处| 欧美性大战久久久久久久蜜桃| 伊人久久精品久久亚洲一区| 国产馆手机在线观看| 日本特黄特色aaa大片免费| 国产呦系列免费| 西西人体44rtwww高清大但| 在线天堂bt种子| 国内国外精品影片无人区| 亚洲日本乱码在线观看| 男人边摸边吃奶边做下面| 日韩美女一级毛片| 丰乳娇妻镇|