Переход между случаями в операторах C switch
У меня есть следующий код для определения моих состояний 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 ответа
Обычный способ кодирования конечного автомата - использование цикла и переключателя:
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; это происходит на других платформах.
Если вы всегда захотите выполнить состояние прямо под тем местом, где вы находитесь, вы можете удалить break
заявление. Я бы положил комментарий в это место, как /* fall through */
так что ясно, что оно намеренно отсутствует для людей, которые следуют за ним, а также для вашего забывчивого будущего. Мне лично не нравится этот метод.
Почему бы не изменить state
переменная, а затем просто выполнить goto
это прямо над оператором switch? Как это может быть:
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;
}