![狀態(tài)機(jī)c語(yǔ)言實(shí)現(xiàn)_第1頁(yè)](http://file3.renrendoc.com/fileroot_temp3/2022-3/13/8d1a3c3b-db1d-43c3-bad2-6bfe5829df14/8d1a3c3b-db1d-43c3-bad2-6bfe5829df141.gif)
![狀態(tài)機(jī)c語(yǔ)言實(shí)現(xiàn)_第2頁(yè)](http://file3.renrendoc.com/fileroot_temp3/2022-3/13/8d1a3c3b-db1d-43c3-bad2-6bfe5829df14/8d1a3c3b-db1d-43c3-bad2-6bfe5829df142.gif)
![狀態(tài)機(jī)c語(yǔ)言實(shí)現(xiàn)_第3頁(yè)](http://file3.renrendoc.com/fileroot_temp3/2022-3/13/8d1a3c3b-db1d-43c3-bad2-6bfe5829df14/8d1a3c3b-db1d-43c3-bad2-6bfe5829df143.gif)
![狀態(tài)機(jī)c語(yǔ)言實(shí)現(xiàn)_第4頁(yè)](http://file3.renrendoc.com/fileroot_temp3/2022-3/13/8d1a3c3b-db1d-43c3-bad2-6bfe5829df14/8d1a3c3b-db1d-43c3-bad2-6bfe5829df144.gif)
![狀態(tài)機(jī)c語(yǔ)言實(shí)現(xiàn)_第5頁(yè)](http://file3.renrendoc.com/fileroot_temp3/2022-3/13/8d1a3c3b-db1d-43c3-bad2-6bfe5829df14/8d1a3c3b-db1d-43c3-bad2-6bfe5829df145.gif)
版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、您還未登錄!|登錄|注冊(cè)|幫助CSDN首頁(yè)資訊論壇博客下載搜索更多CTO俱樂(lè)部學(xué)生大本營(yíng)培訓(xùn)充電移動(dòng)開(kāi)發(fā)軟件研發(fā)云計(jì)算程序員TUPguocai_yao的專欄條新通知登錄注冊(cè)歡迎退出我的博客配置寫文章文章管理博客首頁(yè)全站當(dāng)前博客空間博客好友相冊(cè)留言用戶操作留言發(fā)消息加為好友姚國(guó)才ID:guocai_yao共19660次訪問(wèn),排名9473,好友29人,關(guān)注者35人。態(tài)度決定一切姚國(guó)才的文章原創(chuàng)47篇翻譯0篇轉(zhuǎn)載13篇評(píng)論25篇訂閱我的博客編輯guocai_yao的公告編輯文章分類APUE(AdvancedProgrammingInTheUnixEnvironmentCC+ProgrammingTi
2、psskillsTheCProgrammingLanguageUnix環(huán)境高級(jí)編程)讀書筆記VC及其IDE單片機(jī)數(shù)據(jù)結(jié)構(gòu)瑣碎他山之玉小想法硬件電路的那些事兒編輯EmbeddedSystemAquarius(其中還有英文網(wǎng)站)編輯高手&大師ammana_babiRichardStallmanRolandMcGrathsteedhorsetaodm侯捷周立功徐藝波個(gè)人網(wǎng)站藝術(shù)編程陳莉君編輯好書推薦C+學(xué)習(xí)推薦書目c語(yǔ)言的提高編輯好友袁東存檔2010年05月(8)2010年04月(2)2010年01月(5)2009年08月2009年06月2009年05月(4)2009年04月2009年03月
3、(8)2009年02月2009年01月2008年05月(21)2008年04月公告:CSDN產(chǎn)品事業(yè)部開(kāi)設(shè)官方博客了!來(lái)關(guān)注我們的一舉一動(dòng)吧!意見(jiàn)反饋官方博客C語(yǔ)言實(shí)現(xiàn)有限狀態(tài)機(jī)收藏以下是轉(zhuǎn)載內(nèi)容:傳說(shuō)中的分隔符來(lái)源1:有限狀態(tài)機(jī)(FiniteStateMachine或者FiniteStateAutomata)是軟件領(lǐng)域中一種重要的工具,很多東西的模型實(shí)際上就是有限狀態(tài)機(jī)。最近看了一些游戲編程AI的材料,感覺(jué)游戲中的AI,第一要說(shuō)的就是有限狀態(tài)機(jī)來(lái)實(shí)現(xiàn)精靈的AI,然后才是A*尋路,其他學(xué)術(shù)界討論比較多的神經(jīng)網(wǎng)絡(luò)、模糊控制等問(wèn)題還不是很熱。FSM的實(shí)現(xiàn)方式:1) switch/case或者if/
4、else這無(wú)意是最直觀的方式,使用一堆條件判斷,會(huì)編程的人都可以做到,對(duì)簡(jiǎn)單小巧的狀態(tài)機(jī)來(lái)說(shuō)最合適,但是毫無(wú)疑問(wèn),這樣的方式比較原始,對(duì)龐大的狀態(tài)機(jī)難以維護(hù)。2) 狀態(tài)表維護(hù)一個(gè)二維狀態(tài)表,橫坐標(biāo)表示當(dāng)前狀態(tài),縱坐標(biāo)表示輸入,表中一個(gè)元素存儲(chǔ)下一個(gè)狀態(tài)和對(duì)應(yīng)的操作。這一招易于維護(hù),但是運(yùn)行時(shí)間和存儲(chǔ)空間的代價(jià)較大。3)使用StatePattern使用StatePattern使得代碼的維護(hù)比switch/case方式稍好,性能上也不會(huì)有很多的影響,但是也不是100%完美。不過(guò)RobertC.Martin做了兩個(gè)自動(dòng)產(chǎn)生FSM代碼的工具,forjava和forC+各個(gè),在需要維護(hù)狀態(tài)機(jī)的文本描述,
5、每必要冒引入bug的風(fēng)險(xiǎn)去維護(hù)code。4)使用宏定義描述狀態(tài)機(jī)一般來(lái)說(shuō),C+編程中應(yīng)該避免使用#define,但是這主要是因?yàn)槿绻煤陙?lái)定義函數(shù)的話,很容易產(chǎn)生這樣那樣的問(wèn)題,但是巧妙的使用,還是能夠產(chǎn)生奇妙的效果。MFC就是使用宏定義來(lái)實(shí)現(xiàn)大的架構(gòu)的。在實(shí)現(xiàn)FSM的時(shí)候,可以把一些繁瑣無(wú)比的if/else還有花括號(hào)的組合放在宏中,這樣,在代碼中可以3)中狀態(tài)機(jī)描述文本一樣寫,通過(guò)編譯器的預(yù)編譯處理產(chǎn)生1)一樣的效果,我見(jiàn)過(guò)產(chǎn)生C代碼的宏,如果要產(chǎn)生C+代碼,己軟MFC可以,那么理論上也是可行的?!驹u(píng)】:狀態(tài)表的實(shí)現(xiàn)方法,C專家編程第8章有具體說(shuō)明,轉(zhuǎn)載【6】傳說(shuō)中的分隔符來(lái)源2:2007-
6、05-1115:12區(qū)罔格上可以搜索到很多有限狀熊檄的代礁和理分析,道完彳堇彳堇是做一彳固曾罩的例子,彳堇供入咒參考。這兒以四位密碼校驗(yàn)作為狀態(tài)機(jī)的例子,連續(xù)輸入2479就可以通過(guò)密碼測(cè)試。一個(gè)非常簡(jiǎn)單的例子,在實(shí)際的狀態(tài)機(jī)實(shí)例中,狀態(tài)轉(zhuǎn)移表要更彳復(fù)東隹一些,不謾方式非常I®似。在狀魅查前的地方可以做僵化,同疇封于本俞入量也可以做有效性僵化。具ft代礁如下:viewplaincopytoclipboardprint?c.htypedefenumSTATE1=1,STATE2,STATE3,STATE4,STATE5,passwordpass/.ADDhereSTATE;typedef
7、enumINPUT1='2',INPUT2='4',INPUT3='7',INPUT4='9',INPUT;typedefstructSTATEcur_state;INPUTinput;STATEnext_state;STATE_TRANS;c.htypedefenumSTATE1=1,STATE2,STATE3,STATE4,STATE5,passwordpass/.ADDhereSTATE;typedefenumINPUT1='2',INPUT2='4',INPUT3='7',I
8、NPUT4='9',INPUT;typedefstructSTATEcur_state;INPUTinput;STATEnext_state;STATE_TRANS;c.c#include<stdio.h>#include"c.h"STATE_TRANSstate_trans_arry=STATE1,INPUT1,STATE2,STATE2,INPUT2,STATE3,STATE3,INPUT3,STATE4,STATE4,INPUT4,STATE5,;#defineSTATE_TRANS_CNT(sizeof(state_trans_arry)
9、/sizeof(state_trans_arry0)intmain()inti;charch;STATEstate_machine=STATE1;while(ch!='e')ch=getchar();if(ch>='0')&&(ch<='9')/fordigitpasswordinputonlyfor(i=0;i<STATE_TRANS_CNT;i+)(if(ch=state_trans_arryi.input)&&(state_machine=state_trans_arryi.cur_stat
10、e)(state_machine=state_trans_arryi.next_state;continue;elseif(i=(STATE_TRANS_CNT-1)/notransfermatch,resetstate(state_machine=STATE1;if(state_machine=STATE5)printf("Passwordcorrect,statetransfermachinepass!n");return0;c.c#include<stdio.h>#include"c.h"STATE_TRANSstate_trans_a
11、rry=(STATE1,INPUT1,STATE2,STATE2,INPUT2,STATE3,STATE3,INPUT3,STATE4,STATE4,INPUT4,STATE5,;#defineSTATE_TRANS_CNT(sizeof(state_trans_arry)/sizeof(state_trans_arry0)intmain()inti;charch;STATEstate_machine=STATE1;while(ch!='e')ch=getchar();if(ch>='0')&&(ch<='9')/fo
12、rdigitpasswordinputonlyfor(i=0;i<STATE_TRANS_CNT;i+)(if(ch=state_trans_arryi.input)&&(state_machine=state_trans_arryi.cur_state)(state_machine=state_trans_arryi.next_state;continue;elseif(i=(STATE_TRANS_CNT-1)/notransfermatch,resetstate(state_machine=STATE1;if(state_machine=STATE5)printf(
13、"Passwordcorrect,statetransfermachinepass!n");return0;【評(píng)】:在VC6下運(yùn)行該程序并沒(méi)有達(dá)到目的,即連續(xù)輸入字符2479也沒(méi)有任何輸出信息,個(gè)人根據(jù)轉(zhuǎn)載第一遍文章的FSM的實(shí)現(xiàn)的第一種方法,見(jiàn)【原創(chuàng)之源程序】傳說(shuō)中的分隔符來(lái)源3:【轉(zhuǎn)載3】有限狀態(tài)機(jī)自動(dòng)機(jī)狀態(tài)圖一一一個(gè)圖的數(shù)據(jù)結(jié)構(gòu)!1 .while+switch;2 .狀態(tài)機(jī):就是指定系統(tǒng)的所有可能的狀態(tài)及狀態(tài)間跳轉(zhuǎn)的條件,然后設(shè)一個(gè)初始狀態(tài)輸入給這臺(tái)機(jī)器,機(jī)器就會(huì)自動(dòng)運(yùn)轉(zhuǎn),或最后處于終止?fàn)顟B(tài),或在某一個(gè)狀態(tài)不斷循環(huán)。游戲中狀態(tài)切換是很頻繁的??赡芤郧耙袚Q狀態(tài)就是if
14、else,或者設(shè)標(biāo)志,但這些都不太結(jié)構(gòu)化,如果把它嚴(yán)格的設(shè)為一種標(biāo)準(zhǔn)的狀態(tài)機(jī),會(huì)清楚的多。比如控制一扇門的運(yùn)動(dòng),初始時(shí)門是關(guān)的,當(dāng)有力作用在門上時(shí),門開(kāi)始慢慢打開(kāi),力的作用完后,門漸漸停止不動(dòng),當(dāng)有反向的力時(shí),門又漸漸關(guān)上,知道回到初始關(guān)的狀態(tài)。這個(gè)你會(huì)怎么來(lái)編程實(shí)現(xiàn)呢。似乎很麻煩,的確,沒(méi)有狀態(tài)機(jī)的思想時(shí)會(huì)很煩,設(shè)很多標(biāo)志,一堆if條件。用狀態(tài)機(jī)的話,不只是代碼更清晰,關(guān)鍵是更符合邏輯和自然規(guī)律,不同狀態(tài)不同處理,滿足條件則跳轉(zhuǎn)到相關(guān)狀態(tài)。偽碼如下:enum(CLOSED,/關(guān)上狀態(tài)CLOSING,/正在關(guān)狀態(tài)OPENED,/打開(kāi)狀態(tài)OPENING,/正在開(kāi)的狀態(tài)doorState=CLOS
15、ED;/初始為關(guān)Update()(switch(doorState)caseCLOSED:if(有人推門)doorState=OPENING;/跳轉(zhuǎn)到正在開(kāi)狀態(tài)break;caseOPENING:door.Rotation+=DeltaAngle;/門的旋轉(zhuǎn)量遞增if(門的速度為零)/力的作用已去doorState=OPENED;/跳轉(zhuǎn)到開(kāi)狀態(tài)break;caseOPENED:if(有人關(guān)門)doorState=CLOSING;break;caseCLOSING:door.Rotation-=DeltaAngle;/門的旋轉(zhuǎn)量遞減if(門的旋轉(zhuǎn)角度減為零)doorState=CLOSED;/門
16、已關(guān)上break;該停就會(huì)停/而繪制代碼幾乎不用怎么變,門就是會(huì)嚴(yán)格按照狀態(tài)機(jī)的指示去運(yùn)動(dòng),Render()(RotateView(door.Rotation);DrawDoor(door.Position);enumCLOSED,/關(guān)上狀態(tài)CLOSING,/正在關(guān)狀態(tài)OPENED,/打開(kāi)狀態(tài)OPENING,/正在開(kāi)的狀態(tài)doorState=CLOSED;/初始為關(guān)Update()(switch(doorState)caseCLOSED:if(有人推門)doorState=OPENING;/跳轉(zhuǎn)到正在開(kāi)狀態(tài)break;caseOPENING:door.Rotation+=DeltaAngle;
17、/門的旋轉(zhuǎn)量遞增if(門的速度為零)/力的作用已去doorState=OPENED;/跳轉(zhuǎn)到開(kāi)狀態(tài)break;caseOPENED:if(有人關(guān)門)doorState=CLOSING;break;caseCLOSING:door.Rotation-=DeltaAngle;/門的旋轉(zhuǎn)量遞減if(門的旋轉(zhuǎn)角度減為零)doorState=CLOSED;/門已關(guān)上break;該停就會(huì)停/而繪制代碼幾乎不用怎么變,門就是會(huì)嚴(yán)格按照狀態(tài)機(jī)的指示去運(yùn)動(dòng),Render()(RotateView(door.Rotation);DrawDoor(door.Position);這是一個(gè)簡(jiǎn)單但很典型的例子,狀態(tài)機(jī)的應(yīng)
18、用太多了。就說(shuō)一個(gè)基本游戲的運(yùn)轉(zhuǎn):(用到了一個(gè)狀態(tài)然后還有子狀態(tài))UpdateGame()BEGIN;switch(gameState)case等待選擇菜單:它有三個(gè)子狀態(tài)。if(選擇菜單項(xiàng)=開(kāi)始)(游戲初始;gameState=開(kāi)始游戲)if(選擇菜單項(xiàng)=選項(xiàng))gameState=設(shè)置if(選擇菜單項(xiàng)=退出)gameState=退出case開(kāi)始:游戲運(yùn)行;if(用戶按退出鍵)gameState=等待選擇菜單;.其他的狀態(tài)跳轉(zhuǎn)處理;case退出:釋放資源;退出;case設(shè)置:分別處理不同的選項(xiàng),跳轉(zhuǎn)不同的子狀態(tài);case./其他狀態(tài)的處理END;UpdateGame()BEGIN;switch
19、(gameState)case等待選擇菜單:它有三個(gè)子狀態(tài)。if(選擇菜單項(xiàng)=開(kāi)始)(游戲初始;gameState=開(kāi)始游戲)if(選擇菜單項(xiàng)=選項(xiàng))gameState=設(shè)置if(選擇菜單項(xiàng)=退出)gameState=退出case開(kāi)始:游戲運(yùn)行;if(用戶按退出鍵)gameState=等待選擇菜單;.其他的狀態(tài)跳轉(zhuǎn)處理;case退出:釋放資源;退出;case設(shè)置:分別處理不同的選項(xiàng),跳轉(zhuǎn)不同的子狀態(tài);case./其他狀態(tài)的處理END;某一個(gè)狀態(tài)可以包含更多的子狀態(tài),這樣最好是同一層次的狀態(tài)設(shè)為一個(gè)枚舉,并分到另一個(gè)switch處理如enumSTATESstate1,state2,state3;
20、state2又包含若干狀態(tài)貝U再定義enumSUB_STATE2sub_state2_1,sub_state2_2,sub_state2_3,;想很多基本的渲染效果,如淡入淡出,閃爍等等,用狀態(tài)的思想會(huì)事半功倍,思路也更清晰。其實(shí)像Opengl,Direct3D這樣的渲染引擎本身就是狀態(tài)機(jī),當(dāng)你設(shè)置渲染的狀態(tài),這臺(tái)機(jī)器就保持這個(gè)狀態(tài)進(jìn)行渲染工作,如保持光照位置,保持片元顏色,直到你再次改變它的狀態(tài)。狀態(tài)機(jī)的應(yīng)用實(shí)在太廣,相關(guān)理論也很多,最近上課學(xué)的隨機(jī)過(guò)程里也講到一些,數(shù)字電路里的時(shí)序邏輯器件也是用狀態(tài)機(jī)來(lái)描述。這些不必多說(shuō)了??傊?,用狀態(tài)機(jī)的角度去看待問(wèn)題,往往能把比較復(fù)雜的系統(tǒng)分解為能單獨(dú)
21、處理的眾多子狀態(tài),處理也會(huì)得心應(yīng)手。希望大家多用它,很好的東西。推薦這個(gè):程序員雜志2004.8月刊_state模式和composite模式實(shí)現(xiàn)的狀態(tài)機(jī)引擎?zhèn)€人感覺(jué)狀態(tài)機(jī)的幾個(gè)不同實(shí)現(xiàn)階段:1、switch/case最原始的實(shí)現(xiàn)方式,是很多的c程序員習(xí)慣采用的方式。2、查找表狀態(tài)、事件、動(dòng)作,稍微做了一點(diǎn)改進(jìn)。有點(diǎn)類似MFC的雛形。3、在以上基礎(chǔ)上做的一些改進(jìn)或者變體。比如用一個(gè)棧結(jié)構(gòu),激活的狀態(tài)位于棧頂,自動(dòng)的映射事件和動(dòng)作的對(duì)應(yīng),再或者通過(guò)一些巧妙的宏等手段進(jìn)行包裝。但是線性結(jié)構(gòu)在實(shí)際中使用比較受限、過(guò)于技巧性的宏比較難于理解.4、面向?qū)ο蟮脑O(shè)計(jì)下、靈活運(yùn)用模式。如上面給出的鏈接。重用性和
22、靈活性方面都有不錯(cuò)的表現(xiàn)。沿襲類似的設(shè)計(jì)思路、根據(jù)實(shí)際開(kāi)發(fā)內(nèi)容進(jìn)行改造后利用?!驹u(píng)】:偽代碼部分,可以幫助很好的理解【轉(zhuǎn)載1】文章中敘述的FSM的實(shí)現(xiàn)方法1;查找表狀態(tài)、事彳動(dòng)作,稍微做了一點(diǎn)改進(jìn)。有點(diǎn)類似MFC的雛形類似于【轉(zhuǎn)載1】文章中敘述的FSM的實(shí)現(xiàn)方法2(狀態(tài)表)傳說(shuō)中的分隔符來(lái)源4:【轉(zhuǎn)載4】fsmimplementedinCcode(FSM狀態(tài)機(jī)用C實(shí)現(xiàn))用C語(yǔ)言實(shí)現(xiàn)一個(gè)狀態(tài)機(jī),很簡(jiǎn)單,和大家分享這是我做畢業(yè)設(shè)計(jì)時(shí),用nRF24L01組建了一個(gè)簡(jiǎn)單的網(wǎng)絡(luò),做的一個(gè)小的狀態(tài)機(jī),網(wǎng)絡(luò)中三個(gè)節(jié)點(diǎn),開(kāi)始拓?fù)錇榫W(wǎng)狀,后來(lái)為星型。#include<stdio.h>#include
23、<stdlib.h>#include<string.h>/Finitestatemachinedeclaration/statedeclaration#defineIDLE0/idlestateinrxmode#defineM_BROADCAST1/broadcaststateintxmode,broadcasttobeamasterpoint#defineM_WAIT_BROADCAST_ACK2/waitforbroadcastackstateinrxmode,waitforthepointackinaspecifictimewindow#defineM_WAIT_
24、COMMAND3/waitforcommandstate,waitforPCcommandviaUART#defineM_BROADCAST_CANCEL4/broadcastcancelstate,broadcasttocancelmasterpoint#defineS_BROADCAST_ACK5/slavemode,sendbackselfphysicaladdress#defineS_WAIT_COMMAND6/slavemode,waitforcommandfromthemasterpoint/statetransitiontrig/usedinmastermodeintisReqB
25、eMaster=0;/IsPCrequestthepointtobemaster?intisTimeout=0;/Istimeout?intisReqCancelMaster=0;/Isrequesttocancelmaster?/usedinslavemodeintisRxBroadcast=0;/Isthereapointbroadcasttobemaster?intisRxBroadcastCancel=0;/Isreceivebroadcastcancelmaster?typedefstructfsmtagintstate;/stateinttimeouttime;/timeoutti
26、meinmillisecondsfsm;/functionprototypeintmain()fsmf;f.state=IDLE;f.timeouttime=0;while(1)switch(f.state)caseIDLE:puts("IDLEnWaitforisReqBeMaster(1/0)isRxBroadcast(1/0):");scanf("%d%d",&isReqBeMaster,&isRxBroadcast);if(isReqBeMaster)f.state=M_BROADCAST;break;elseif(isRxBro
27、adcast)f.state=S_BROADCAST_ACK;break;elsebreak;caseM_BROADCAST:puts("M_BROADCASTnBroadcastingn");f.state=M_WAIT_BROADCAST_ACK;caseM_WAIT_BROADCAST_ACK:puts("M_WAIT_BROADCAST_ACKnWaitingforisTimeout(1/0):");scanf("%d",&isTimeout);if(isTimeout)f.state=M_WAIT_COMMAND;b
28、reak;)elsebreak;caseM_WAIT_COMMAND:puts("M_WAIT_COMMANDnWaitingforisReqCancelMaster(1/0):");scanf("%d",&isReqCancelMaster);if(isReqCancelMaster)(f.state=IDLE;break;)elsebreak;/SlavemoderoutinecaseS_BROADCAST_ACK:puts("S_BROADCAST_ACKnAcking.n");f.state=S_WAIT_COMMAN
29、D;break;caseS_WAIT_COMMAND:puts("S_WAIT_COMMANDnWaitingforisRxBroadcastCancel(1/0):");scanf("%d",&isRxBroadcastCancel);if(isRxBroadcastCancel)(f.state=IDLE;break;)elsebreak;default:puts("default");printf("%dn",rand();f.state=IDLE;)return0;)#include<stdi
30、o.h>#include<stdlib.h>#include<string.h>/Finitestatemachinedeclaration/statedeclaration#defineIDLE0/idlestateinrxmode#defineM_BROADCAST1/broadcaststateintxmode,broadcasttobeamasterpoint#defineM_WAIT_BROADCAST_ACK2/waitforbroadcastackstateinrxmode,waitforthepointackinaspecifictimewindo
31、w#defineM_WAIT_COMMAND3/waitforcommandstate,waitforPCcommandviaUART#defineM_BROADCAST_CANCEL4/broadcastcancelstate,broadcasttocancelmasterpoint#defineS_BROADCAST_ACK5/slavemode,sendbackselfphysicaladdress#defineS_WAIT_COMMAND6/slavemode,waitforcommandfromthemasterpoint/statetransitiontrig/usedinmast
32、ermodeintisReqBeMaster=0;/IsPCrequestthepointtobemaster?intisTimeout=0;/Istimeout?intisReqCancelMaster=0;/Isrequesttocancelmaster?/usedinslavemodeintisRxBroadcast=0;/Isthereapointbroadcasttobemaster?intisRxBroadcastCancel=0;/Isreceivebroadcastcancelmaster?typedefstructfsmtagintstate;/stateinttimeout
33、time;/timeouttimeinmillisecondsfsm;/functionprototypeintmain()fsmf;f.state=IDLE;f.timeouttime=0;while(1)switch(f.state)caseIDLE:puts("IDLEnWaitforisReqBeMaster(1/0)isRxBroadcast(1/0):");scanf("%d%d",&isReqBeMaster,&isRxBroadcast);if(isReqBeMaster)(f.state=M_BROADCAST;brea
34、k;)elseif(isRxBroadcast)(f.state=S_BROADCAST_ACK;break;)elsebreak;caseM_BROADCAST:puts("M_BROADCASTnBroadcasting.n");f.state=M_WAIT_BROADCAST_ACK;caseM_WAIT_BROADCAST_ACK:puts("M_WAIT_BROADCAST_ACKnWaitingforisTimeout(1/0):");scanf("%d",&isTimeout);if(isTimeout)(f.s
35、tate=M_WAIT_COMMAND;break;)elsebreak;caseM_WAIT_COMMAND:puts("M_WAIT_COMMANDnWaitingforisReqCancelMaster(1/0):");scanf("%d",&isReqCancelMaster);if(isReqCancelMaster)(f.state=IDLE;break;)elsebreak;/SlavemoderoutinecaseS_BROADCAST_ACK:puts("S_BROADCAST_ACKnAcking.n");
36、f.state=S_WAIT_COMMAND;break;caseS_WAIT_COMMAND:puts("S_WAIT_COMMANDnWaitingforisRxBroadcastCancel(1/0):");scanf("%d",&isRxBroadcastCancel);if(isRxBroadcastCancel)(f.state=IDLE;break;)elsebreak;default:puts("default");printf("%dn",rand();f.state=IDLE;)retu
37、rn0;)【評(píng)】:很實(shí)用的一個(gè)狀態(tài)機(jī)程序傳說(shuō)中的分隔符來(lái)源5:/user1/349/archives/2007/44609.html【轉(zhuǎn)載5】狀態(tài)機(jī)的兩種寫法2004/12/asdjfyy20041226-1v1有限狀態(tài)機(jī)FSM思想廣泛應(yīng)用于硬件控制電路設(shè)計(jì),也是軟件上常用的一種處理方法(軟件上稱為FMM-有限消息機(jī))。它把復(fù)雜的控制邏輯分解成有限個(gè)穩(wěn)定狀態(tài),在每個(gè)狀態(tài)上判斷事件,變連續(xù)處理為離散數(shù)字處理,符合計(jì)算機(jī)的工作特點(diǎn)。同時(shí),因?yàn)橛邢逘顟B(tài)機(jī)具有有限個(gè)狀態(tài),所以可以在實(shí)際的工程上實(shí)現(xiàn)。但這并不意味著其只能進(jìn)行有限次的處理,相反,有限狀態(tài)機(jī)是閉環(huán)系
38、統(tǒng),有限無(wú)窮,可以用有限的狀態(tài),處理無(wú)窮的事務(wù)。有限狀態(tài)機(jī)的工作原理如圖1所示,發(fā)生事件(event)后,根據(jù)當(dāng)前狀態(tài)(cur_state),決定執(zhí)行的動(dòng)作(action),并設(shè)置下一個(gè)狀態(tài)號(hào)(nxt_state)。|發(fā)生事件event>|cur_state|執(zhí)行動(dòng)作action|設(shè)置下一狀態(tài)號(hào)nxt_state當(dāng)前狀態(tài)圖1有限狀態(tài)機(jī)工作原理e0/a0|>e0/a0|S0|-<|e1/a1|e2/a2V|S2|<|S1|e2/a2圖2一個(gè)有限狀態(tài)機(jī)實(shí)例當(dāng)前狀態(tài)s0s1-s2|事件a0/s0-a0/s0|e0a1/s1-|e1a2/s2a2/s2-|e2表1圖2狀態(tài)機(jī)實(shí)例
39、的二維表格表示(動(dòng)作/下一狀態(tài))圖2為一個(gè)狀態(tài)機(jī)實(shí)例的狀態(tài)轉(zhuǎn)移圖,它的含義是:在s0狀態(tài),如果發(fā)生e0事件,那么就執(zhí)行a0動(dòng)作,并保持狀態(tài)不變;如果發(fā)生e1事件,那么就執(zhí)行a1動(dòng)作,并將狀態(tài)轉(zhuǎn)移到s1態(tài);如果發(fā)生e2事件,那么就執(zhí)行a2動(dòng)作,并將狀態(tài)轉(zhuǎn)移到s2態(tài);在s1狀態(tài),如果發(fā)生e2事件,那么就執(zhí)行a2動(dòng)作,并將狀態(tài)轉(zhuǎn)移到s2態(tài);在s2狀態(tài),如果發(fā)生e0事件,那么就執(zhí)行a0動(dòng)作,并將狀態(tài)轉(zhuǎn)移到s0態(tài);有限狀態(tài)機(jī)不僅能夠用狀態(tài)轉(zhuǎn)移圖表示,還可以用二維的表格代表。一般將當(dāng)前狀態(tài)號(hào)寫在橫行上,將事件寫在縱列上,如表1所示。其中“-”表示空(不執(zhí)行動(dòng)作,也不進(jìn)行狀態(tài)轉(zhuǎn)移),“an/sn”表示執(zhí)行動(dòng)
40、作an,同時(shí)將下一狀態(tài)設(shè)置為sn。表1和圖2表示的含義是完全相同的。觀察表1可知,狀態(tài)機(jī)可以用兩種方法實(shí)現(xiàn):豎著寫(在狀態(tài)中判斷事件)和橫著寫(在事件中判斷狀態(tài))。這兩種實(shí)現(xiàn)在本質(zhì)上是完全等效的,但在實(shí)際操作中,效果卻截然不同。豎著寫(在狀態(tài)中判斷事件)C代碼片段cur_state=nxt_state;switch(cur_state)case 50:if(e0_event)持狀態(tài)不變;執(zhí)行a0動(dòng)作;/nxt_state=s0;運(yùn)行速度。elseif(e1_event)態(tài)轉(zhuǎn)移到s1態(tài);執(zhí)行a1動(dòng)作;nxt_state=s1;elseif(e2_event)態(tài)轉(zhuǎn)移到s2態(tài);執(zhí)行a2動(dòng)作;nxt_
41、state=s2;break;case 51:if(e2_event)狀態(tài)轉(zhuǎn)移到s2態(tài);執(zhí)行a2動(dòng)作;nxt_state=s2;break;case 52:if(e0_event)狀態(tài)轉(zhuǎn)移到s0態(tài);執(zhí)行a0動(dòng)作;nxt_state=s0;/在當(dāng)前狀態(tài)中判斷事件/在s0狀態(tài)如果發(fā)生e0事件,那么就執(zhí)行a0動(dòng)作,并保因?yàn)闋顟B(tài)號(hào)是自身,所以可以刪除此句,以提高如果發(fā)生e1事件,那么就執(zhí)行a1動(dòng)作,并將狀如果發(fā)生e2事件,那么就執(zhí)行a2動(dòng)作,并將狀/在s1狀態(tài)如果發(fā)生e2事件,那么就執(zhí)行a2動(dòng)作,并將/在s2狀態(tài)如果發(fā)生e0事件,那么就執(zhí)行a0動(dòng)作,并將橫著寫(在事件中判斷狀態(tài))C代碼片段/e0事件發(fā)
42、生時(shí),執(zhí)行的函數(shù)voide0_event_function(int*nxt_state)intcur_state;cur_state=*nxt_state;switch(cur_state)cases0:cases2:執(zhí)行a0動(dòng)作;*nxt_state=s0;)/e1事件發(fā)生時(shí),執(zhí)行的函數(shù)voide1_event_function(int*nxt_state)intcur_state;cur_state=*nxt_state;switch(cur_state)cases0:執(zhí)行a1動(dòng)作;*nxt_state=s1;)/e2事件發(fā)生時(shí),執(zhí)行的函數(shù)voide2_event_function(int
43、*nxt_state)intcur_state;cur_state=*nxt_state;switch(cur_state)case 50:case 51:執(zhí)行a2動(dòng)作;*nxt_state=s2;)/觀察表1,在e0事件發(fā)生時(shí),s1處為空/觀察表1,在e1事件發(fā)生時(shí),s1和s2處為空/觀察表1,在e2事件發(fā)生時(shí),s2處為空上面橫豎兩種寫法的代碼片段,實(shí)現(xiàn)的功能完全相同,但是,橫著寫的效果明顯好于豎著寫的效果。理由如下:1、豎著寫隱含了優(yōu)先級(jí)排序(其實(shí)各個(gè)事件是同優(yōu)先級(jí)的),排在前面的事件判斷將毫無(wú)疑問(wèn)地優(yōu)先于排在后面的事件判斷。這種if/elseif寫法上的限制將破壞事件間原有的關(guān)系。而橫著
44、寫不存在此問(wèn)題。2、由于處在每個(gè)狀態(tài)時(shí)的事件數(shù)目不一致,而且事件發(fā)生的時(shí)間是隨機(jī)的,無(wú)法預(yù)先確定,導(dǎo)致豎著寫淪落為順序查詢方式,結(jié)構(gòu)上的缺陷使得大量時(shí)間被浪費(fèi)。對(duì)于橫著寫,在某個(gè)時(shí)間點(diǎn),狀態(tài)是唯一確定的,在事件里查找狀態(tài)只要使用switch語(yǔ)句,就能一步定位到相應(yīng)的狀態(tài),延遲時(shí)間可以預(yù)先準(zhǔn)確估算。而且在事件發(fā)生時(shí),調(diào)用事件函數(shù),在函數(shù)里查找唯一確定的狀態(tài),并根據(jù)其執(zhí)行動(dòng)作和狀態(tài)轉(zhuǎn)移的思路清晰簡(jiǎn)潔,效率高,富有美感??傊覀€(gè)人認(rèn)為,在軟件里寫狀態(tài)機(jī),使用橫著寫的方法比較妥帖。豎著寫的方法也不是完全不能使用,在一些小項(xiàng)目里,邏輯不太復(fù)雜,功能精簡(jiǎn),同時(shí)為了節(jié)約內(nèi)存耗費(fèi),豎著寫的方法也不失為一種合
45、適的選擇。在FPGA類硬件設(shè)計(jì)中,以狀態(tài)為中心實(shí)現(xiàn)控制電路狀態(tài)機(jī)(豎著寫)似乎是唯一的選擇,因?yàn)橛布惶赡芸渴录?qū)動(dòng)(橫著寫)。不過(guò),在FPGA里有一個(gè)全局時(shí)鐘,在每次上升沿時(shí)進(jìn)行狀態(tài)切換,使得豎著寫的效率并不低。雖然在硬件里豎著寫也要使用IF/ELSIF這類查詢語(yǔ)句(用VHDL開(kāi)發(fā)),但他們映射到硬件上是組合邏輯,查詢只會(huì)引起門級(jí)延遲(ns量級(jí)),而且硬件是真正并行工作的,這樣豎著寫在硬件里就沒(méi)有負(fù)面影響。因此,在硬件設(shè)計(jì)里,使用豎著寫的方式成為必然的選擇。這也是為什么很多搞硬件的工程師在設(shè)計(jì)軟件狀態(tài)機(jī)時(shí)下意識(shí)地只使用豎著寫方式的原因,蓋思維定勢(shì)使然也。TCP和PPP框架協(xié)議里都使用了有限
46、狀態(tài)機(jī),這類軟件狀態(tài)機(jī)最好使用橫著寫的方式實(shí)現(xiàn)。以某TCP協(xié)議為例,見(jiàn)圖3,有三種類型的事件:上層下達(dá)的命令事件;下層到達(dá)的標(biāo)志和數(shù)據(jù)的收包事件;超時(shí)定時(shí)器超時(shí)事件。上層命令(open,close)事件|TCP|<超時(shí)事件timeoutRST/SYN/FIN/ACK/DATA等收包事件圖3三大類TCP狀態(tài)機(jī)事件由圖3可知,此TCP協(xié)議棧采用橫著寫方式實(shí)現(xiàn),有3種事件處理函數(shù),上層命令處理函數(shù)(如tcp_close);超時(shí)事件處理函數(shù)(tmr_slow);下層收包事件處理函數(shù)(tcp_process)。值得一提的是,在收包事件函數(shù)里,在各個(gè)狀態(tài)里判斷RST/SYN/FIN/ACK/DATA
47、等標(biāo)志(這些標(biāo)志類似于事件),看起來(lái)象豎著寫方式,其實(shí),如果把包頭和數(shù)據(jù)看成一個(gè)整體,那么,RST/SYN/FIN/ACK/DATA等標(biāo)志就不必被看成獨(dú)立的事件,而是屬于同一個(gè)收包事件里的細(xì)節(jié),這樣,就不會(huì)認(rèn)為在狀態(tài)里查找事件,而是總體上看,是在收包事件里查找狀態(tài)(橫著寫)。在PPP里更是到處都能見(jiàn)到橫著寫的現(xiàn)象,有時(shí)間的話再細(xì)說(shuō)。我個(gè)人感覺(jué)在實(shí)現(xiàn)PPP框架協(xié)議前必須了解橫豎兩種寫法,而且只有使用橫著寫的方式才能比較完美地實(shí)現(xiàn)PPP?!驹u(píng)】:看不大懂,先留著,有備無(wú)患傳說(shuō)中的分隔符來(lái)源6:【轉(zhuǎn)載6】用C語(yǔ)言實(shí)現(xiàn)有限狀態(tài)機(jī)-讀C專家編程有限狀態(tài)機(jī)(finitestatemachine)是一個(gè)數(shù)學(xué)
48、概念,如果把它運(yùn)用于程序中,可以發(fā)揮很大的作用。它是一種協(xié)議,用于有限數(shù)量的子程序("狀態(tài)")的發(fā)展變化。每個(gè)子程序進(jìn)行一些處理并選擇下一種狀態(tài)(通常取決于下一段輸入)。有限狀態(tài)機(jī)(FSM)可以用作程序白控制結(jié)構(gòu)。FSM對(duì)于那些基于輸入的在幾個(gè)不同的可選動(dòng)作中進(jìn)行循環(huán)的程序尤其合適。投幣售貨機(jī)就是FSM的一個(gè)好例子。另外一個(gè)你可以想到的復(fù)雜的例子就是你正在用的東西,想到了嗎?沒(méi)錯(cuò),就是操作系統(tǒng)。在投幣售貨機(jī)的例子中,輸入是硬幣,輸出是待售商品,售貨機(jī)有"接受硬幣","選擇商品","發(fā)送商品"和"找零錢”等
49、幾種狀態(tài)。它的基本思路是用一張表保存所有可能的狀態(tài),并列出進(jìn)入每個(gè)狀態(tài)時(shí)可能執(zhí)行的所有動(dòng)作,其中最后一個(gè)動(dòng)作就是計(jì)算(通常在當(dāng)前狀態(tài)和下一次輸入字符的基礎(chǔ)上,另外再經(jīng)過(guò)一次表查詢)下一個(gè)應(yīng)該進(jìn)入的狀態(tài)。你從一個(gè)"初始狀態(tài)"開(kāi)始。在這一過(guò)程中,翻譯表可能告訴你進(jìn)入了一個(gè)錯(cuò)誤狀態(tài),直到到達(dá)結(jié)束狀態(tài)。在C語(yǔ)言中,有好幾種方法可以用來(lái)表達(dá)FSM,但它們絕大多數(shù)都是基于函數(shù)指針數(shù)組。一個(gè)函數(shù)指針數(shù)組可以像下面這樣聲明:void(*stateMAX_STATES)();如果知道了函數(shù)名,就可以像下面這樣對(duì)數(shù)組進(jìn)行初始化。externinta(),b(),c(),d();int(*sta
50、te口)()=a,b,c,c;可以通過(guò)數(shù)組中的指針來(lái)調(diào)用函數(shù):(*statei)();所有函數(shù)必須接受同樣的參數(shù),并返回同種類型的返回值(除非你把數(shù)組元素做成一個(gè)聯(lián)合)。函數(shù)指針是很有趣的。注意,我們可以去掉指針形式,把上面的調(diào)用寫成:statei();甚至(*statei)();這是一個(gè)在ANSIC中流行的不良方法:調(diào)用函數(shù)和通過(guò)指針調(diào)用函數(shù)(或任意層次的指針間接引用)可以使用同一種語(yǔ)法。如果你想干得漂亮一點(diǎn),可以讓狀態(tài)函數(shù)返回一個(gè)指向通用后續(xù)函數(shù)的指針,并把它轉(zhuǎn)換為適當(dāng)?shù)念愋?。這樣,就不需要全局變量了。如果你不想搞得太花哨,可以使用一個(gè)switch語(yǔ)句作為一種簡(jiǎn)樸的狀態(tài)機(jī),方法是賦值給控制
51、變量并把switch語(yǔ)句放在循環(huán)內(nèi)部。關(guān)于FSM還有最后一點(diǎn)需要說(shuō)明:如果你的狀態(tài)函數(shù)看上去需要多個(gè)不同的參數(shù),可以考慮使用一個(gè)參數(shù)計(jì)數(shù)器和一個(gè)字符串指針數(shù)組,就像main函數(shù)的參數(shù)一樣。我們熟悉的intargc,char*argv機(jī)制是非常普遍的,可以成功地應(yīng)用在你所定義的函數(shù)中。傳說(shuō)中的分隔符【原創(chuàng)之源程序】密碼鎖(最簡(jiǎn)單的實(shí)現(xiàn)switch/if-else形的)#include<stdio.h>#include<stdlib.h>#include<string.h>typedefenumSTATE0=0,STATE1,STATE2,STATE3,STAT
52、E4,passwordpass/.ADDhereSTATE;typedefenumINPUT1='2',INPUT2='4',INPUT3='7',INPUT4='9',INPUT;intmain()(charch;STATEcurrent_state=STATE0;while(1)printf("請(qǐng)輸入數(shù)字進(jìn)行解碼:");while(ch=getchar()!='n')if(ch<'0')|(ch>'9')!n");printf("
53、;非數(shù)字,請(qǐng)重新輸入break;switch(current_state)caseSTATE0:if(ch='2')current_state=STATE1;break;caseSTATE1:if(ch='4')current_state=STATE2;break;caseSTATE2:if(ch='7')current_state=STATE3;break;caseSTATE3:if(ch='9')current_state=STATE4;break;default:current_state=STATE0;break;if(current_state=STATE4)printf("Correct,lockisopen!n");break;elseprintf("Wrong,unlocked!n");return0;)#include<stdio.h>#include<stdlib.h>#include<string.h>typedefenumSTATE0=0,STATE1,STATE2,STATE3,STATE4,passwo
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 部編版道德與法治九年級(jí)下冊(cè)第二單元第三課《與世界緊相連第2框與世界深度互動(dòng)》聽(tīng)課評(píng)課記錄
- 2022版新課標(biāo)七年級(jí)上冊(cè)道德與法治第五課交友的智慧2課時(shí)聽(tīng)課評(píng)課記錄
- 人教版數(shù)學(xué)九年級(jí)上冊(cè)《直接開(kāi)平方法解方程》聽(tīng)評(píng)課記錄3
- 人教版地理八年級(jí)下冊(cè)7.1《自然特征與農(nóng)業(yè)》聽(tīng)課評(píng)課記錄
- 環(huán)境評(píng)估服務(wù)合同(2篇)
- 湘教版數(shù)學(xué)八年級(jí)上冊(cè)2.2《命題的證明》聽(tīng)評(píng)課記錄2
- 北師大版道德與法治九年級(jí)上冊(cè)6.2《弘揚(yáng)法治精神》聽(tīng)課評(píng)課記錄
- 北京課改版歷史八年級(jí)上冊(cè)第10課《辛亥革命與中華民國(guó)建立》聽(tīng)課評(píng)課記錄
- 湘教版數(shù)學(xué)七年級(jí)上冊(cè)《2.5整式的加法和減法(1)》聽(tīng)評(píng)課記錄2
- 部編版八年級(jí)歷史上冊(cè)《第1課 鴉片戰(zhàn)爭(zhēng)》聽(tīng)課評(píng)課記錄
- 2024年臨床醫(yī)師定期考核試題中醫(yī)知識(shí)題庫(kù)及答案(共330題) (二)
- 2025-2030年中國(guó)反滲透膜行業(yè)市場(chǎng)發(fā)展趨勢(shì)展望與投資策略分析報(bào)告
- 湖北省十堰市城區(qū)2024-2025學(xué)年九年級(jí)上學(xué)期期末質(zhì)量檢測(cè)道德與法治試題 (含答案)
- 山東省濰坊市2024-2025學(xué)年高三上學(xué)期1月期末 英語(yǔ)試題
- 春節(jié)節(jié)后收心會(huì)
- 《榜樣9》觀后感心得體會(huì)四
- 七年級(jí)下冊(cè)英語(yǔ)單詞表(人教版)-418個(gè)
- 2025年山東省濟(jì)寧高新區(qū)管委會(huì)“優(yōu)才”招聘20人歷年高頻重點(diǎn)提升(共500題)附帶答案詳解
- 2025年中國(guó)社會(huì)科學(xué)評(píng)價(jià)研究院第一批專業(yè)技術(shù)人員招聘2人歷年高頻重點(diǎn)提升(共500題)附帶答案詳解
- 交警安全進(jìn)校園課件
- (2024年高考真題)2024年普通高等學(xué)校招生全國(guó)統(tǒng)一考試數(shù)學(xué)試卷-新課標(biāo)Ⅰ卷(含部分解析)
評(píng)論
0/150
提交評(píng)論