2011-07-22 15 views
4

を保持する構造体:私はSTATE1で午前FSMはKEY_UPプログラムを受信したときにステートマシン - 私は、ステートマシンを作成し、このようなインターフェースを使用したい場合は国、イベントとpFuncs

AddState (state1, state2, Key_UP); 
AddEvent (Key_UP); 
AddEventFunction (Key_UP, &UP_Function); 
AddStateFunction (state1, &State1_In_Function, &State1_Out_Function); 
AddStateFunction (state2, &State2_In_Function, &State2_Out_Function); 

State1_In_Function (void) { printf ("In #1 \n"); } 
State1_Out_Function (void) { printf ("Out #1 \n"); } 
State2_In_Function (void) { printf ("In #2 \n"); } 
State2_Out_Function (void) { printf ("Out #2 \n"); } 
UP_Function   (void) { printf ("Goin UP \n"); } 

をそのようにprint:

プログラマが配列サイズを変更する必要なく、状態および遷移情報をクラス内に格納する方法は問題です。私は2D配列を使用していつものように状態テーブルにすることができると考えていました。そして、必要に応じてベクトルタイプを使用してイベントや状態の追加を処理するだけです。ベクトルの問題は、多くの組み込みデバイスがメモリ割り当て呼び出しを使用できないことです。私の2番目のオプションは、ステートマシンでコンストラクタを呼び出し、テーブルに必要なサイズを渡しますが、新しい状態やイベントを追加する場合は、これらの値も変更する必要があります。

私は私の状態、イベント、関数ポインタを格納する必要がありますか?

+0

以下のMatthieuの例に基づいて、私が望むすべてのことをする作業システムを完成させました!興味のある方は、完全なプログラム[こちら](http://pastebin.com/RtPne3dC)を見て、単に "g ++ file.cpp"を実行してください。 – uMinded

答えて

3

それは少し難しくなりますけれどもあなたは、単に、スタックに保存することができ:)

はまだ、それは面白いなソリューションですので、ここに行きます。基本的な原則は、デコレータと変更可能性で遊ぶことです。コード例:

State state1, state2; // creates a state 
Event KEY_UP; 
Event KEY_DOWN; 

Transition t0(state1, KEY_UP, state2); 
Transition t1(state2, KEY_DOWN, state1); 

どのように動作しますか?

「シンプルな」オブジェクトであるstate1の代わりに、少し複雑になるでしょう。ような何か:

struct State; 

struct StateImpl { 
    StateImpl(char const* n): name(n) {} 
    char const* name; 
}; 

struct StateNode { 
    StateNode(Event e, State const& s, StateNode const* n): 
    event(e), state(s), next(n) {} 

    Event event; 
    State const& destination; 
    StateNode const* next; 
}; 

struct State { 
    State(char const* name): 
    me(0), impl(name) {} 

    StateNode const* me; 
    StateImpl impl; 
}; 

そしてその後、我々は定義Transition:非公式には、我々はStateに座って頭で、重リンクリストを作成している

struct Transition { 
    Transition(State& origin, Event e, State const& destination): 
    node(e, destination, origin.me) 
    { 
    origin.me = node; 
    } 
    StateNode node; 
}; 

。私たちはトランジションを追加するたびに頭を更新します。

イベントが発生すると、イベントが発生して適切にディスパッチされるか、イベントがこの状態で受信されないことを示すヌルポインタに達するまで、このリストをウォークする必要があります。

+0

Hmm ..これは本当に面白いです。このようにすることで、構造体に入出力関数へのポインタを簡単に追加できます! – uMinded

+0

私はプログラムのロジックに従っていくつかのデバッグを追加しました、あなたは完全なプログラムを見ることができます[ここ](http://pastebin.com/uKxLAReT) – uMinded

+0

私はあなたのコードを歩いていたときに、私はあなたの事例でいくつかのことを理解していないことを発見しました。 StateNodeのために状態を作成するたびに再帰的にインクルードされます。 state1.me-> destination.me-> destination.me - > ....など 遷移構造も私が想像していたようにStateNodeを渡して元通りになりません。何が欲しかったかそれに加えて、一般的には、状態は、すべての状態のために私がデフォルトでNULLになります。 あなたのコードで少しウォークスルーしてもよろしいですか? – uMinded

0

Boost.StateChartをご覧になり、必要に応じて必要なAPIを使用して薄いレイヤーを作成することをお勧めします。

これは、適切なデータ構造を設計するための必要性を解決するはずです。

+2

Boost.StateChartが組み込みデバイスに適合しているかどうかはわかりません。 –

+0

それはなぜでしょうか? –

+1

OPは、自分が気に入っているプラ​​ットフォーム上でヒープ割り当てメモリが利用できないことを明示的に参照しています。つまり、完全な標準ではなく、C++のサブセットを使用しています。私は個人的にはそれがうまくいくかどうかを知るためにBoost.StateChart侵略について十分に知りません。あなたはそれらについて知っていますか? –

0

あなたはget cute and do it this wayことができます。

+0

残念ながらそれはちょっと単純すぎます。私の州の機械のほとんどは約30の州と5の出来事を持っています。 – uMinded

関連する問題