在C switch语句中的case之间跳转

时间:2013-10-20 03:38:31

标签: c switch-statement

我有以下代码来定义我的FSM状态:

enum states
{
    START,              // Send request to remote IP or wait for a request (WAIT_CONN_REQ)
    WAIT_RESP,          // Chat request sent to remote IP. Waiting for a response from the target machine
    SEND_CONN_RESP,     // Chat request received from remote IP. ACCEPT or REJECT
    ACCEPTED            // Both parties agreed to exchange datagrams. Begin application data (MESSAGES) exchange
};
typedef enum states states;
states state;

我的思维过程是这样的:我的聊天程序将具有上述四种状态。整齐地做这件事最好的方法是什么?当然,使用switch语句。那我该怎么办呢?像这样:(代码被简化并替换为printf函数“

int main(int argc, char *argv[])
{
    state = START;
    switch (state)
    {
        case START:
            printf("Simple Chat Client - START state\n");
            if (argv[1] != NULL)
            {
                SEND_CONN_REQ();
                } else {
                WAIT_CONN_REQ();
            }
            break;
        case WAIT_RESP:
            printf("WAIT_RESP STATE!");
            break;
        case SEND_CONN_RESP:
            printf("SEND_CONN_RESP state!");
            break;
        case ACCEPTED:
            printf("ACCEPTED state!");
            break;
    }
}

但这不符合我的要求。我希望它在满足条件时跳转到另一个案例。像这样:

    if (argv[1] != NULL)
                    {
                        SEND_CONN_REQ();
                        goto case WAIT_RESP;          
                        } else {
                        WAIT_CONN_REQ();
                    }
                    break;
                case WAIT_RESP:
                    printf("WAIT_RESP STATE!");
                    break;

我的逻辑告诉我,这样做的方法是更改​​state变量,假设将使用新变量再次执行整个switch。但是,我必须使用break并退出switch,或者不使用它,让程序执行下一个case

所以我查看了其他选项,例如do语句和continue。但在我看来,使用case似乎是使用FSM的方式。

如果能够正确地做到这一点,我将不胜感激。 switch声明是最好的方式吗?

2 个答案:

答案 0 :(得分:2)

像这样编码状态机的常用方法是使用循环和开关:

state = START;
while (state != STOP)
{
    switch (state)
    {
        case START:
            printf("Simple Chat Client - START state\n");
            if (argv[1] != NULL)
            {
                SEND_CONN_REQ();
            } else {
                WAIT_CONN_REQ();
            }
            break;
        case WAIT_RESP:
            printf("WAIT_RESP STATE!");
            break;
        case SEND_CONN_RESP:
            printf("SEND_CONN_RESP state!");
            break;
        case ACCEPTED:
            printf("ACCEPTED state!");
            break;
    }
}

每个操作都可以选择设置新状态,以便下一次迭代将执行相应的操作。如果要及时查看输出,请不要忘记在printf()语句的末尾输出换行符。在Windows上可能无关紧要;它在其他平台上。

答案 1 :(得分:0)

如果您始终只想执行下面的状态,则可以删除break语句。我会在/* fall through */这样的地方发表评论,这样很明显,对于跟随的人以及你未来遗忘的自我而言​​,它是故意遗漏的。我个人不喜欢这种方法。

为什么不更改state变量,然后只执行位于switch语句正上方的goto?像这样可能:

switchStart:
    switch (state)
    {
        case START:
            printf("Simple Chat Client - START state\n");
            if (argv[1] != NULL)
            {
                SEND_CONN_REQ();
                state = STATE_HERE; // change your state
                goto switchStart; // jump to the top of the switch
                } else {
                WAIT_CONN_REQ();
            }
            break;
        case WAIT_RESP:
            printf("WAIT_RESP STATE!");
            break;
        case SEND_CONN_RESP:
            printf("SEND_CONN_RESP state!");
            break;
        case ACCEPTED:
            printf("ACCEPTED state!");
            break;
    }