4

如果我制作一个状态机并想使用这样的界面:

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" ); }

这样,当我处于 state1 并且 FSM 收到 Key_UP 时,程序会打印:

Out #1
Goin UP
In #2

问题是如何在不要求程序员更改数组大小的情况下将状态和过渡信息存储在类中。我在想我可以使用 2D 数组并像往常一样使其成为状态表,并使其更便携,我只需通过使用矢量类型根据需要调整大小来处理事件和状态的添加。向量的问题是没有多少嵌入式设备可以使用内存分配调用。我的第二个选择是使用状态机调用构造函数并将表所需的大小传递给它,但是如果我添加任何新的状态或事件,我也需要更改这些值......

那么我应该如何存储我的状态、事件和函数指针呢?!

4

3 回答 3

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

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

非正式地,我们正在构建一个单链表,头部位于State. 每次添加过渡时,我们都会更新头部。

在事件发生时,需要遍历此列表,直到遇到事件并因此被适当地分派,或者到达空指针,指示在此状态下不应接收到事件。

于 2011-07-22T06:55:53.233 回答
0

顺便说一句,你可以变得可爱并这样做

于 2011-07-22T12:22:03.517 回答
0

我建议您查看Boost.StateChart,如果需要,使用您想要的 API 围绕它构建一个薄层。

这应该可以解决您设计足够数据结构的需求。

于 2011-07-22T06:30:01.360 回答