3

在一些帮助之后,有一些代码可以工作,但试图完全理解使用查找表作为状态机一部分的一小部分。我理解并一直用于我正在编写的教程的状态机在这里找到http://coder-tronics.com/state-machine-tutorial-pt1 而不是在 OnExit、OnEnter 和 ActionWhileInState 中使用更多的 switch case 语句,有人建议使用我喜欢但不完全理解的这种方法。

现在我不确定的部分是这些行与 typedef 和查找表有关

typedef void (* const voidFunc)(void);

voidFunc UponEnter[S_MAX] =          {hEnter_OFF,   hEnter_ON,   hEnter_PROCESS};
voidFunc ActionWhileInState[S_MAX] = {hInState_OFF, hInState_ON, hInState_PROCESS};
voidFunc UponExit[S_MAX] =           {hExit_OFF,    hExit_ON,    hExit_PROCESS};

我查阅了 typedef 和查找表并有了基本的了解,但希望有人可以简要介绍一下在这种情况下它是如何工作的?

为了完整起见,与此相关的完整代码部分如下所示。

enum states { S_OFF, S_ON, S_PROCESS, S_MAX };
enum events { E_OFF, E_ON, E_START, E_MAX};
typedef void (* const voidFunc)(void);
void hEnter_OFF(void);   void hEnter_ON(void);   void hEnter_PROCESS(void);
void hInState_OFF(void); void hInState_ON(void); void hInState_PROCESS(void);
void hExit_OFF(void);    void hExit_ON(void);    void hExit_PROCESS(void);

voidFunc UponEnter[S_MAX] =          {hEnter_OFF,   hEnter_ON,   hEnter_PROCESS};
voidFunc ActionWhileInState[S_MAX] = {hInState_OFF, hInState_ON, hInState_PROCESS};
voidFunc UponExit[S_MAX] =           {hExit_OFF,    hExit_ON,    hExit_PROCESS};

enum states StateMachine(enum events event, enum states Current_State)
{
    int Next_State = Current_State;

    switch ( Current_State )
    {
            case S_OFF:
       switch (event )
       {
           // A transition to the next state will occur here
           case E_ON:
            Next_State = S_ON;
               break;
           default:     // Default case placed here to avoid Eclipse warnings as Eclipse expects
               break;   //to handle all enumerated values
       }
       break;
   case S_ON:
       switch (event )
       {
           // A transition to the next state will occur here
           case E_OFF:
            Next_State = S_OFF;
               break;
           case E_START:
            Next_State = S_PROCESS;
               break;
           default:     // Default case placed here to avoid Eclipse warnings as Eclipse expects
               break;   //to handle all enumerated values
       }
       break;
   case S_PROCESS:
       switch (event )
       {
           // A transition to the next state will occur here
       case E_OFF:
        Next_State = S_OFF;
           break;
       default:     // Default case placed here to avoid Eclipse warnings as Eclipse expects
           break;   //to handle all enumerated values
       }
       break;
       // The program should never arrive here
    default:
       break;
    }

    if (Next_State != Current_State)
    {
        // Function call for Upon Exit function, it can be omitted but allows extra functionality
        UponExit[Current_State]();
        // Function call for Upon Enter function, it can be omitted but allows extra functionality
        if (Next_State != S_MAX) UponEnter[Next_State]();
    }
    else // I think ActionWhileInState should only be called when NOT doing a transition!
     {
        if ( event != E_MAX) ActionWhileInState[Current_State]();
    }
    return Next_State;
}

谢谢,

蚂蚁

4

1 回答 1

3
typedef void (* const voidFunc)(void);

是函数指针的类型定义(对于指向不期望参数并且不准确返回任何内容的函数的指针)。所以你的数组

voidFunc UponEnter[S_MAX] =          {hEnter_OFF,   hEnter_ON,   hEnter_PROCESS};
voidFunc ActionWhileInState[S_MAX] = {hInState_OFF, hInState_ON, hInState_PROCESS}; 
voidFunc UponExit[S_MAX] =           {hExit_OFF,    hExit_ON,    hExit_PROCESS};

每个都包含三个不同的函数指针,每个状态一个。所以像这样的一条线

UponExit[Current_State]();

调用指针UponExit[Current_State]指向的函数,hExit_OFF如果Current_State是 0,hExit_ON如果Current_State是 1 或hExit_PROCESS如果Current_State是 2。你也可以这样写:

(*UponExit[Current_State])();

看起来更复杂但清楚的UponExit[Current_State]是一个函数指针,它被“取消引用”到对其指向的函数的调用。

编辑:

你有一个enum适合你的州:

enum states { S_OFF, S_ON, S_PROCESS, S_MAX };

因此, S_OFF == 0, S_ON == 1,S_PROCESS == 2S_MAX == 3(看这里)

于 2013-08-14T14:07:54.620 回答