當前位置:首頁 > 技術學院 > 技術前線
[導讀]狀態(tài)機的全稱是有限狀態(tài)自動機,自動兩個字也是包含重要含義的。給定一個狀態(tài)機,同時給定它的當前狀態(tài)以及輸入,那么輸出狀態(tài)是可以明確地運算出來的。

一、狀態(tài)機簡介

1.1 定義

我們先來給出狀態(tài)機的基本定義。一句話:

狀態(tài)機是有限狀態(tài)自動機的簡稱,是現(xiàn)實事物運行規(guī)則抽象而成的一個數(shù)學模型。

先來解釋什么是“狀態(tài)”( State )。現(xiàn)實事物是有不同狀態(tài)的,例如一個自動門,就有 open 和 closed 兩種狀態(tài)。我們通常所說的狀態(tài)機是有限狀態(tài)機,也就是被描述的事物的狀態(tài)的數(shù)量是有限個,例如自動門的狀態(tài)就是兩個open和 closed。

狀態(tài)機,也就是 State Machine ,不是指一臺實際機器,而是指一個數(shù)學模型。說白了,一般就是指一張狀態(tài)轉換圖。例如,根據(jù)自動門的運行規(guī)則,我們可以抽象出下面這么一個圖。

自動門有兩個狀態(tài),open 和 closed ,closed 狀態(tài)下,如果讀取開門信號,那么狀態(tài)就會切換為 open 。open 狀態(tài)下如果讀取關門信號,狀態(tài)就會切換為 closed 。

狀態(tài)機的全稱是有限狀態(tài)自動機,自動兩個字也是包含重要含義的。給定一個狀態(tài)機,同時給定它的當前狀態(tài)以及輸入,那么輸出狀態(tài)是可以明確地運算出來的。例如對于自動門,給定初始狀態(tài) closed ,給定輸入“開門”,那么下一個狀態(tài)是可以運算出來的。

這樣狀態(tài)機的基本定義我們就介紹完畢了。重復一下:狀態(tài)機是有限狀態(tài)自動機的簡稱,是現(xiàn)實事物運行規(guī)則抽象而成的一個數(shù)學模型。

1.2 四大概念

下面來給出狀態(tài)機的四大概念。

第一個是 State ,狀態(tài)。一個狀態(tài)機至少要包含兩個狀態(tài)。例如上面自動門的例子,有 open 和 closed 兩個狀態(tài)。

第二個是 Event ,事件。事件就是執(zhí)行某個操作的觸發(fā)條件或者口令。對于自動門,“按下開門按鈕”就是一個事件。

第三個是 Action ,動作。事件發(fā)生以后要執(zhí)行動作。例如事件是“按開門按鈕”,動作是“開門”。編程的時候,一個 Action 一般就對應一個函數(shù)。

第四個是 Transition ,變換。也就是從一個狀態(tài)變化為另一個狀態(tài)。例如“開門過程”就是一個變換。

發(fā)生了什么事?

現(xiàn)在系統(tǒng)處在什么狀態(tài)?

在這樣的狀態(tài)下發(fā)生了這樣的事,系統(tǒng)要干什么?

用 C 語言實現(xiàn)狀態(tài)機主要有 3 種方法:switch—case 法、表格驅動法、函數(shù)指針法。

switch—case 法

狀態(tài)用 switch—case 組織起來, 將事件也用switch—case 組織起來, 然后讓其中一個 switch—case 整體插入到另一個 switch—case 的每一個 case 項中 。

「程序清單 List4 :」

switch(StateVal){ case S0: switch(EvntID) { case E1: action_S0_E1(); /*S0 狀態(tài)下 E1 事件的響應*/ StateVal = new state value;/*狀態(tài)遷移,不遷移則沒有此行*/ break; case E2: action_S0_E2(); /*S0 狀態(tài)下 E2 事件的響應*/ StateVal = new state value; break; ...... case Em: action_S0_Em(); /*S0 狀態(tài)下 Em 事件的響應*/ StateVal = new state value; break; default: break; } break; case S1: ...... break; ...... case Sn: ...... break; default: break;}


一文講解狀態(tài)機的三種騷操作

上面的偽代碼示例只是通用的情況,實際應用遠沒有這么復雜。雖然一個系統(tǒng)中事件可能有很多種,但在實際應用中,許多事件可能對某個狀態(tài)是沒有意義的。

例如在程序清單 List4中,如果 E2、······ Em 對處在 S0 狀態(tài)下的系統(tǒng)沒有意義,那么在 S0 的 case 下有關事件E2、······ Em 的代碼根本沒有必要寫,狀態(tài) S0 只需要考慮事件 E1 的處理就行了。

既然是兩個 switch—case 之間的嵌套, 那么就有一個誰嵌套誰的問題, 所以說 switch—case法有兩種寫法:狀態(tài)嵌套事件和事件嵌套狀態(tài)。這兩種寫法都可以, 各有利弊, 至于到底選用哪種方式就留給設計人員根據(jù)具體情況自行決斷吧。

關于 switch—case 法還有最后一點要說明, 因為 switch—case 的原理是從上到下挨個比較,越靠后,查找耗費的時間就越長,所以要注意狀態(tài)和事件在各自的 switch 語句中的安排順序,不推薦程序清單 List4 那樣按順序號排布的方式。出現(xiàn)頻率高或者實時性要求高的狀態(tài)和事件的位置應該盡量靠前。

表格驅動法

如果說** switch—case 法是線性的**,那么表格驅動法則是平面的。表格驅動法的實質就是將狀態(tài)和事件之間的關系固化到一張二維表格里, 把事件當做縱軸,把狀態(tài)當做橫軸,交點[Sn , Em]則是系統(tǒng)在 Sn 狀態(tài)下對事件 Em 的響應 。


5659249fbf04cfd6abcdafa64dce158d.png

如圖 4, 我把表格中的 Node_SnEm 叫做狀態(tài)機節(jié)點, 狀態(tài)機節(jié)點 Node_SnEm 是系統(tǒng)在 Sn狀態(tài)下對事件 Em 的響應。這里所說的響應包含兩個方面:輸出動作和狀態(tài)遷移。狀態(tài)機節(jié)點一般是一個類似程序清單 List5 中的結構體變量 。

struct fsm_node{ void (*fpAction)(void* pEvnt); INT8U u8NxtStat;};

程序清單 List5 中的這個結構體有兩個成員:fpAction 和 u8NxtStat。fpAction 是一個函數(shù)指針, 指向一個形式為 void func(void * pEvnt)的函數(shù), func 這個函數(shù)是對狀態(tài)轉移中動作序列的標準化封裝。

也就是說, 狀態(tài)機在狀態(tài)遷移的時候, 不管輸出多少個動作、操作多少個變量、調用多少個函數(shù),這些行為統(tǒng)統(tǒng)放到函數(shù) func 中去做。

把動作封裝好了之后,再把封裝函數(shù) func 的地址交給函數(shù)指針 fpAction,這樣,想要輸出動作,只需要調用函數(shù)指針 fpAction 就行了。

再看看上面的 func 函數(shù),會發(fā)現(xiàn)函數(shù)有一個形參 pEvnt,這是一個類型為 void * 的指針, 在程序實際運行時指向一個能存儲事件的變量,通過這個指針我們就能獲知關于事件的全部信息,這個形參是很有必要的。

事件一般包括兩個屬性:事件的類型和事件的內容。

例如一次按鍵事件,我們不僅要知道這是一個按鍵事件,還要知道按下的到底是哪個鍵。

事件的類型和狀態(tài)機當前的狀態(tài)可以讓我們在圖 4 的表格中迅速定位,確定該調用哪個動作封裝函數(shù), 但是動作封裝函數(shù)要正確響應事件還需要知道事件的內容是什么, 這也就是形參pEvnt 的意義。

由于事件的多樣性,存儲事件內容的數(shù)據(jù)格式不一定一樣,所以就把 pEvnt 定義成了 void * 型,以增加靈活性。

有關 fpAction 的最后一個問題:如果事件 Em 對狀態(tài) Sn 沒有意義,那么狀態(tài)機節(jié)點Node_SnEm 中的 fpAction 該怎么辦?

我的答案是:那就讓它指向一個空函數(shù)唄!前面不是說過么,什么也不干也叫響應。

u8NxtStat 存儲的是狀態(tài)機的一個狀態(tài)值。我們知道, 狀態(tài)機響應事件要輸出動作, 也就是調用函數(shù)指針 fpAction 所指向的那個封裝函數(shù), 函數(shù)調用完畢后程序返回主調函數(shù), 狀態(tài)機對事件的響應就算結束了, 下一步就要考慮狀態(tài)遷移的問題了。

可能要保持本狀態(tài)不變, 也可能要遷移到一個新的狀態(tài),該如何抉擇呢?u8NxtStat 存儲的狀態(tài)就是狀態(tài)機想要的答案!

圖 4 的這張表格反映在 C 語言代碼里就是一個二維數(shù)組,第 1 維就是狀態(tài)機的狀態(tài),第 2維就是統(tǒng)一分類的事件,而數(shù)組的元素則是程序清單 List5 中的結構體常量。

如果程序中使用表格驅動法,還需要注意一些特別的事項。要將狀態(tài)當做表格的橫軸,那么就要求狀態(tài)值集合必須滿足以下條件:

(1) 該集合是一個遞增的等差整數(shù)數(shù)列

(2) 該數(shù)列初值為 0

(3) 該數(shù)列等差值為 1

“事件” 作為縱軸,其特點和要求與用來做橫軸的“狀態(tài)” 完全一致。在 C 語言提供的數(shù)據(jù)類型中, 沒有比枚舉更符合以上要求的可選項了, 極力推薦將狀態(tài)集合和事件類型集合做成枚舉常量。表格驅動法的優(yōu)點:調用接口統(tǒng)一 ,定位快速。

表格驅動法屏蔽了不同狀態(tài)下處理各個事件的差異性,因此可以將處理過程中的共性部分提煉出來,做成標準統(tǒng)一的框架式代碼,形成統(tǒng)一的調用接口。

根據(jù)程序清單 List5 中的狀態(tài)機節(jié)點結構體,做成的框架代碼如程序清單 List6 所示。

表格驅動法查找目標實際上就是一次二維數(shù)組的尋址操作,所以它的平均效率要遠高于switch—case 法。

「程序清單 List6 :」

extern struct fsm_node g_arFsmDrvTbl[][]; /*狀態(tài)機驅動表格*/INT8U u8CurStat = 0; /*狀態(tài)暫存*/INT8U u8EvntTyp = 0; /*事件類型暫存*/void* pEvnt = NULL; /*事件變量地址暫存*/struct fsm_node stNodeTmp = {NULL, 0}; /*狀態(tài)機節(jié)點暫存*/u8CurStat = get_cur_state(); /*讀取當前狀態(tài)*/u8EvntTyp = get_cur_evnt_typ(); /*讀取當前觸發(fā)事件類型*/pEvnt = (void*)get_cur_evnt_ptr(); /*讀取事件變量地址*/stNodeTmp = g_arFsmDrvTbl[u8CurStat ][u8EvntTyp ];/*定位狀態(tài)機節(jié)點*/stNodeTmp.fpAction(pEvnt ); /*動作響應*/set_cur_state(stNodeTmp.u8NxtStat); /*狀態(tài)遷移*/.....

表格驅動法好則好矣,但用它寫出來的程序還有點兒小問題,我們先來看看按照表格驅動法寫出來的程序有什么特點 。

前面說過,表格驅動法可以把狀態(tài)機調度的部分做成標準統(tǒng)一的框架代碼,這個框架適用性極強, 不管用狀態(tài)機來實現(xiàn)什么樣的應用, 框架代碼都不需要做改動, 我們只需要根據(jù)實際應用場合規(guī)劃好狀態(tài)轉換圖,然后將圖中的各個要素(狀態(tài)、事件、動作、遷移,有關“條件”要素一會兒再說)用代碼實現(xiàn)就行了,我把這部分代碼稱作應用代碼。

在應用代碼的.c 文件中, 你會看到一個聲明為 const 的二維數(shù)組, 也就是圖 4 所示的狀態(tài)驅動表格, 還會看到許多彼此之間毫無關聯(lián)的函數(shù), 也就是前面提到的動作封裝函數(shù)。

這樣的一份代碼, 如果手頭上沒有一張狀態(tài)轉換圖, 讓誰看了也會一頭霧水, 這樣的格式直接帶來了代碼可讀性差的問題。

如果我們想給狀態(tài)機再添加一個狀態(tài),反映到代碼上就是給驅動表格再加一列內容,同時也要新添加若干個動作封裝函數(shù)。

如果驅動表格很大, 做這些工作是很費事兒的, 而且容易出錯。如果不小心在數(shù)組中填錯了位置, 那么程序跑起來就和設計者的意圖南轅北轍了,

遠沒有在 switch—case 法中改動來得方便、安全。Extended State Machine 的最大特點就是狀態(tài)機響應事件之前先判斷條件,根據(jù)判定結果選擇執(zhí)行哪些動作,轉向哪個狀態(tài)。

也就是說,系統(tǒng)在狀態(tài) Sn 下發(fā)生了事件 Em 后,轉向的狀態(tài)不一定是唯一的,這種靈活性是 Extended State Machine 的最有價值的優(yōu)點。

回過頭來看看程序清單 List5 中給出的狀態(tài)機節(jié)點結構體,如果系統(tǒng)在狀態(tài) Sn 下發(fā)生了事件 Em, 狀態(tài)機執(zhí)行完 fpAction 所給出的動作響應之后, 必須轉到 u8NxtStat 指定的狀態(tài)。

表格驅動法的這個特性直接杜絕了 Extended State Machine 在表格驅動法中應用的可能性, 所以表格驅動法的代碼實現(xiàn)中不存在“條件” 這個狀態(tài)機要素。ESM,你是如此的優(yōu)秀,我怎么舍得拋棄你 ?!

再看圖 4 所示的表格驅動法示例圖,如果我們把表格中的代表事件的縱軸去掉,只留下代表狀態(tài)的橫軸,將一列合并成一格,前文提到的問題是不是能得到解決呢?不錯!這就是失傳江湖多年的《葵花寶典》 ——閹割版表格驅動法 !!

閹割版表格驅動法,又名壓縮表格驅動法,一維狀態(tài)表格與事件 switch—case 的合體。壓縮表格驅動法使用了一維數(shù)組作為驅動表格,數(shù)組的下標即是狀態(tài)機的各個狀態(tài)。

表格中的元素叫做壓縮狀態(tài)機節(jié)點, 節(jié)點的主要內容還是一個指向動作封裝函數(shù)的函數(shù)指針, 只不過這個動作封裝函數(shù)不是為某個特定事件準備的, 而是對所有的事件都有效的。

節(jié)點中不再強制指定狀態(tài)機輸出動作完畢后所轉向的狀態(tài), 而是讓動作封裝函數(shù)返回一個狀態(tài), 并把這個狀態(tài)作為狀態(tài)機新的狀態(tài)。

壓縮表格驅動法的這個特點, 完美的解決了 Extended State Machine 不能在表格驅動法中使用的問題 。

程序清單 List7 中的示例代碼包含了壓縮狀態(tài)機節(jié)點結構體和狀態(tài)機調用的框架代碼。

「程序清單 List7:」

struct fsm_node /*壓縮狀態(tài)機節(jié)點結構體*/{ INT8U (*fpAction)(void* pEvnt); /*事件處理函數(shù)指針*/ INT8U u8StatChk; /*狀態(tài)校驗*/};......u8CurStat = get_cur_state(); /*讀取當前狀態(tài)*/......if(stNodeTmp.u8StatChk == u8CurStat ){ u8CurStat = stNodeTmp.fpAction(pEvnt ); /*事件處理*/ set_cur_state(u8CurStat ); /*狀態(tài)遷移*/}else{ state_crash(u8CurStat ); /*非法狀態(tài)處理*/}.....


一文講解狀態(tài)機的三種騷操作

對照程序清單 List5,就會發(fā)現(xiàn)程序清單 List7 中 struct fsm_node 結構體的改動之處。首先, fpAction 所指向函數(shù)的函數(shù)形式變了,動作封裝函數(shù) func 的模樣成了這樣的了:

INT8U func(void * pEvnt);

現(xiàn)在的動作封裝函數(shù) func 是要返回類型為 INT8U 的返回值的,這個返回值就是狀態(tài)機要轉向的狀態(tài), 也就是說, 壓縮表格驅動法中的狀態(tài)機節(jié)點不負責狀態(tài)機新狀態(tài)的確定, 而把這項任務交給了動作封裝函數(shù) func, func 返回哪個狀態(tài), 狀態(tài)機就轉向哪個狀態(tài)。

新狀態(tài)由原來的常量變成了現(xiàn)在的變量,自然要靈活許多。上面說到現(xiàn)在的動作封裝函數(shù) func 要對當前發(fā)生的所有的事件都要負責, 那么 func 怎么會知道到底是哪個事件觸發(fā)了它呢?看一下 func 的形參 void * pEvnt 。

在程序清單 List5 中我們提到過,這個形參是用來向動作封裝函數(shù)傳遞事件內容的,但是從前文的敘述中我們知道, pEvnt 所指向的內存包含了事件的所有信息, 包括事件類型和事件內容 , 所以通過形參 pEvnt , 動作封裝函數(shù) func 照樣可以知道事件的類型。

程序清單 List7 中 struct fsm_node 結構體還有一個成員 u8StatChk , 這里面存儲的是狀態(tài)機 的一個狀態(tài),干什么用的呢?

玩 C 語言數(shù)組的人都知道,要嚴防數(shù)組尋址越界。

要知道,壓縮表格驅動法的驅動表格是一個以狀態(tài)值為下標的一維數(shù)組, 數(shù)組元素里面最重要的部分就是一個個動作封裝函數(shù)的地址。

函數(shù)地址在單片機看來無非就是一段二進制數(shù)據(jù), 和內存中其它的二進制數(shù)據(jù)沒什么兩樣,不管程序往單片機 PC 寄存器里塞什么值,單片機都沒意見。假設程序由于某種意外而改動了存儲狀態(tài)機當前狀態(tài)的變量,使變量值變成了一個非法狀態(tài)。

再發(fā)生事件時, 程序就會用這個非法的狀態(tài)值在驅動表格中尋址, 這時候就會發(fā)生內存泄露,程序拿泄露內存中的未知數(shù)據(jù)當函數(shù)地址跳轉,不跑飛才怪!

為了防止這種現(xiàn)象的發(fā)生, 壓縮狀態(tài)機節(jié)點結構體中又添加了成員 u8StatChk 。u8StatChk中存儲的是壓縮狀態(tài)機節(jié)點在一維驅動表格的位置, 例如某節(jié)點是表格中的第 7 個元素, 那么這個節(jié)點的成員 u8StatChk 值就是 6。

看一下程序清單 List7 中的框架代碼示例, 程序在引用函數(shù)指針 fpAction 之前, 先檢查當前狀態(tài)和當前節(jié)點成員 u8CurStat 的值是否一致,一致則認為狀態(tài)合法,事件正常響應,如果不一致,則認為當前狀態(tài)非法,轉至意外處理,最大限度保證程序運行的安全。

當然,如果泄露內存中的數(shù)據(jù)恰好和 u8CurStat 一致,那么這種方法真的就回天乏力了。

還有一個方法也可以防止狀態(tài)機跑飛,如果狀態(tài)變量是枚舉,那么框架代碼就可以獲知狀態(tài)值的最大值, 在調用動作封裝函數(shù)之前判斷一下當前狀態(tài)值是否在合法的范圍之內, 同樣能保證狀態(tài)機的安全運行。

壓縮表格驅動法中動作封裝函數(shù)的定義形式我們已經(jīng)知道了,函數(shù)里面到底是什么樣子的呢?程序清單 List8 是一個標準的示例。

「程序清單List8:」

INT8U action_S0(void* pEvnt){ INT8U u8NxtStat = 0; INT8U u8EvntTyp = get_evnt_typ(pEvnt); switch(u8EvntTyp ) { case E1: action_S0_E1(); /*事件 E1 的動作響應*/ u8NxtStat = new state value; /*狀態(tài)遷移,不遷移也必須有本行*/ break; ...... case Em: action_S0_Em(); /*事件 Em 的動作響應*/ u8NxtStat = new state value; /*狀態(tài)遷移,不遷移也必須有本行*/ break; default: ; /*不相關事件處理*/ break; } return u8NxtStat ; /*返回新狀態(tài)*/}


一文講解狀態(tài)機的三種騷操作

從程序清單 List8 可以看出, 動作封裝函數(shù)其實就是事件 switch—case 的具體實現(xiàn)。函數(shù)根據(jù)形參 pEvnt 獲知事件類型, 并根據(jù)事件類型選擇動作響應, 確定狀態(tài)機遷移狀態(tài), 最后將新的狀態(tài)作為執(zhí)行結果返回給框架代碼。

有了這樣的動作封裝函數(shù), Extended State Machine 的應用就可以完全不受限制了!到此,有關壓縮表格驅動法的介紹就結束了。

個人認為壓縮表格驅動法是相當優(yōu)秀的,它既有表格驅動法的簡潔、高效、標準,又有 switch—case 法的直白、靈活、多變,相互取長補短,相得益彰。

函數(shù)指針法

上面說過,用 C 語言實現(xiàn)狀態(tài)機主要有 3 種方法(switch—case 法、表格驅動法、函數(shù)指針法), 其中函數(shù)指針法是最難理解的, 它的實質就是把動作封裝函數(shù)的函數(shù)地址作為狀態(tài)來看待。不過,有了之前壓縮表格驅動法的鋪墊,函數(shù)指針法就變得好理解了,因為兩者本質上是相同的。

壓縮表格驅動法的實質就是一個整數(shù)值(狀態(tài)機的一個狀態(tài))到一個函數(shù)地址(動作封裝函數(shù))的一對一映射, 壓縮表格驅動法的驅動表格就是全部映射關系的直接載體。在驅動表格中通過狀態(tài)值就能找到函數(shù)地址,通過函數(shù)地址同樣能反向找到狀態(tài)值。

我們用一個全局的整型變量來記錄狀態(tài)值,然后再查驅動表格找函數(shù)地址,那干脆直接用一個全局的函數(shù)指針來記錄狀態(tài)得了,還費那勞什子勁干嗎?!這就是函數(shù)指針法的前世今生。

用函數(shù)指針法寫出來的動作封裝函數(shù)和程序清單 List8 的示例函數(shù)是很相近的, 只不過函數(shù)的返回值不再是整型的狀態(tài)值, 而是下一個動作封裝函數(shù)的函數(shù)地址, 函數(shù)返回后, 框架代碼再把這個函數(shù)地址存儲到全局函數(shù)指針變量中。

相比壓縮表格驅動法,在函數(shù)指針法中狀態(tài)機的安全運行是個大問題,我們很難找出一種機制來檢查全局函數(shù)指針變量中的函數(shù)地址是不是合法值。如果放任不管, 一旦函數(shù)指針變量中的數(shù)據(jù)被篡改,程序跑飛幾乎就不可避免了。

總結

有關狀態(tài)機的東西說了那么多,相信大家都已經(jīng)感受到了這種工具的優(yōu)越性,狀態(tài)機真的是太好用了!其實我們至始至終講的都是有限狀態(tài)機(Finite State Machine 現(xiàn)在知道為什么前面的代碼中老是有 fsm 這個縮寫了吧!), 還有一種比有限狀態(tài)機更 NB 更復雜的狀態(tài)機, 那就是層次狀態(tài)機(Hierarchical State Machine 一般簡寫為 HSM)。

通俗的說,系統(tǒng)中只存在一個狀態(tài)機的叫做有限狀態(tài)機,同時存在多個狀態(tài)機的叫做層次狀態(tài)機(其實這樣解釋層次狀態(tài)機有些不嚴謹, 并行狀態(tài)機也有多個狀態(tài)機, 但層次狀態(tài)機各個狀態(tài)機之間是上下級關系,而并行狀態(tài)機各個狀態(tài)機之間是平級關系)。

層次狀態(tài)機是一種父狀態(tài)機包含子狀態(tài)機的多狀態(tài)機結構,里面包含了許多與面向對象相似的思想, 所以它的功能也要比有限狀態(tài)機更加強大, 當一個問題用有限狀態(tài)機解決起來有些吃力的時候, 就需要層次狀態(tài)機出馬了。

層次狀態(tài)機理論我理解得也不透徹, 就不在這里班門弄斧了,大家可以找一些有關狀態(tài)機理論的專業(yè)書籍來讀一讀。要掌握狀態(tài)機編程,理解狀態(tài)機(主要指有限狀態(tài)機)只是第一步,也是最簡單的一步,更重要的技能是能用狀態(tài)機這個工具去分析解剖實際問題:劃分狀態(tài)、 提取事件、 確定轉換關系、規(guī)定動作等等,形成一張完整的狀態(tài)轉換圖,最后還要對轉換圖進行優(yōu)化,達到最佳。

把實際問題變成了狀態(tài)轉換圖, 工作的一大半就算完成了, 這個是具有架構師氣質的任務,剩下的問題就是按照狀態(tài)圖編程寫代碼了,這個是具有代碼工特色的工作。

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或將催生出更大的獨角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關鍵字: 阿維塔 塞力斯 華為

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉型技術解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關鍵字: AWS AN BSP 數(shù)字化

倫敦2024年8月29日 /美通社/ -- 英國汽車技術公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時1.5...

關鍵字: 汽車 人工智能 智能驅動 BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務能7×24不間斷運行,同時企業(yè)卻面臨越來越多業(yè)務中斷的風險,如企業(yè)系統(tǒng)復雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務連續(xù)性,提升韌性,成...

關鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報道,騰訊和網(wǎng)易近期正在縮減他們對日本游戲市場的投資。

關鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會開幕式在貴陽舉行,華為董事、質量流程IT總裁陶景文發(fā)表了演講。

關鍵字: 華為 12nm EDA 半導體

8月28日消息,在2024中國國際大數(shù)據(jù)產(chǎn)業(yè)博覽會上,華為常務董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權最終是由生態(tài)的繁榮決定的。

關鍵字: 華為 12nm 手機 衛(wèi)星通信

要點: 有效應對環(huán)境變化,經(jīng)營業(yè)績穩(wěn)中有升 落實提質增效舉措,毛利潤率延續(xù)升勢 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務引領增長 以科技創(chuàng)新為引領,提升企業(yè)核心競爭力 堅持高質量發(fā)展策略,塑強核心競爭優(yōu)勢...

關鍵字: 通信 BSP 電信運營商 數(shù)字經(jīng)濟

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺與中國電影電視技術學會聯(lián)合牽頭組建的NVI技術創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會上宣布正式成立。 活動現(xiàn)場 NVI技術創(chuàng)新聯(lián)...

關鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會上,軟通動力信息技術(集團)股份有限公司(以下簡稱"軟通動力")與長三角投資(上海)有限...

關鍵字: BSP 信息技術
關閉