我如何在 C 中将 goto 与 switch 一起使用? (密克罗尼西亚联邦)
How do I use goto with swtich in C? (FSM)
假设我有这个代码
switch(x)
{
region_1:
case a:
...
case b:
goto region_1:
region_2:
case c:
...
case d:
goto region_2
default:
...
}
在C中有没有可能有这样一个类似递归的算法?无论如何,我可以从哪里跳转到标签并再次检查案例?我要给我爷爷做一个FSM,他打算用它来钓鱼。
您可以执行以下操作
switch ( x )
{
case 1:
L1: switch( y )
{
case a:
//...
case b:
//...
goto L1;
}
case 2:
L2: switch( y )
{
case c:
//...
case d:
//...
goro L2;
}
default:
//...
}
为什么要使用开关。
例如,假设您想编写一个自动机来检查输入是否匹配模式 ab+c+
。
自动机:
- S0:
- a → S1
- S1
- b → S1
- c → S2
- S2
- c → S2
- EOF → 接受
这可以通过开关来完成,但也可以使用 goto
:
来实现
S0: {
int c = getch();
if (c == 'a') goto S1;
goto ERROR;
}
S1: {
int c = getch();
if (c == 'b') goto S1;
if (c == 'c') goto S2;
goto ERROR;
}
S3: {
int c = getch();
if (c == 'c') goto S2;
if (c == EOF) goto ACCEPT;
goto ERROR;
}
ACCEPT: exit(0);
ERROR: exit(1);
不过你也可以这样写:
while (1) {
int next_state;
switch (state) {
case ERROR: exit(1);
case ACCEPT: exit(0);
case S0: {
int c = getch();
if (c == 'a') { next_state = S1; }
else { next_state = ERROR; }
break;
}
case S1: {
int c = getch();
if (c == 'b') { next_state = S1; }
else if (c == 'c') { next_state = S2; }
else { next_state = ERROR; }
break;
}
case S2: {
int c = getch();
if (c == 'c') { next_state = S2; }
else { next_state = ERROR; }
break;
}
}
state = next_state;
}
但这确实是使用 tables 的垫脚石。
#define TOK_OTHER 0
#define TOK_EOF 1
#define TOK_A 2
#define TOK_B 3
#define TOK_C 4
static int char_to_token_map[] = {
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x60 */ 0, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static int to_token(int c) {
if (c >= 128) return 0;
if (c == EOF) return 1;
return char_to_token_map[c];
}
#define ERROR -2
#define ACCEPT -1
#define S0 0
#define S1 1
#define S2 2
static int automata[3][5] {
/* state OTHER EOF a b c */
/* ----- ------- ------- ------- ------- ------- */
/* S0 */ { ERROR ERROR S1, ERROR, ERROR },
/* S1 */ { ERROR, ERROR, ERROR, S1, S2, },
/* S2 */ { ERROR, ACCEPT, ERROR, ERROR, S2, }
};
int state = S0;
while (1) {
int new_state;
switch (state) {
case ERROR: exit(1);
case ACCEPT: exit(0);
default: new_state = automata[ state ][ to_token(getch()) ];
}
state = new_state;
}
如果您需要在切换状态之前执行任何操作,只需在该状态的切换中添加一个特例即可。或者使用 table 由状态索引的函数指针。
假设我有这个代码
switch(x)
{
region_1:
case a:
...
case b:
goto region_1:
region_2:
case c:
...
case d:
goto region_2
default:
...
}
在C中有没有可能有这样一个类似递归的算法?无论如何,我可以从哪里跳转到标签并再次检查案例?我要给我爷爷做一个FSM,他打算用它来钓鱼。
您可以执行以下操作
switch ( x )
{
case 1:
L1: switch( y )
{
case a:
//...
case b:
//...
goto L1;
}
case 2:
L2: switch( y )
{
case c:
//...
case d:
//...
goro L2;
}
default:
//...
}
为什么要使用开关。
例如,假设您想编写一个自动机来检查输入是否匹配模式 ab+c+
。
自动机:
- S0:
- a → S1
- S1
- b → S1
- c → S2
- S2
- c → S2
- EOF → 接受
这可以通过开关来完成,但也可以使用 goto
:
S0: {
int c = getch();
if (c == 'a') goto S1;
goto ERROR;
}
S1: {
int c = getch();
if (c == 'b') goto S1;
if (c == 'c') goto S2;
goto ERROR;
}
S3: {
int c = getch();
if (c == 'c') goto S2;
if (c == EOF) goto ACCEPT;
goto ERROR;
}
ACCEPT: exit(0);
ERROR: exit(1);
不过你也可以这样写:
while (1) {
int next_state;
switch (state) {
case ERROR: exit(1);
case ACCEPT: exit(0);
case S0: {
int c = getch();
if (c == 'a') { next_state = S1; }
else { next_state = ERROR; }
break;
}
case S1: {
int c = getch();
if (c == 'b') { next_state = S1; }
else if (c == 'c') { next_state = S2; }
else { next_state = ERROR; }
break;
}
case S2: {
int c = getch();
if (c == 'c') { next_state = S2; }
else { next_state = ERROR; }
break;
}
}
state = next_state;
}
但这确实是使用 tables 的垫脚石。
#define TOK_OTHER 0
#define TOK_EOF 1
#define TOK_A 2
#define TOK_B 3
#define TOK_C 4
static int char_to_token_map[] = {
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x20 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x30 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x40 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x50 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x60 */ 0, 2, 3, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
/* 0x70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
static int to_token(int c) {
if (c >= 128) return 0;
if (c == EOF) return 1;
return char_to_token_map[c];
}
#define ERROR -2
#define ACCEPT -1
#define S0 0
#define S1 1
#define S2 2
static int automata[3][5] {
/* state OTHER EOF a b c */
/* ----- ------- ------- ------- ------- ------- */
/* S0 */ { ERROR ERROR S1, ERROR, ERROR },
/* S1 */ { ERROR, ERROR, ERROR, S1, S2, },
/* S2 */ { ERROR, ACCEPT, ERROR, ERROR, S2, }
};
int state = S0;
while (1) {
int new_state;
switch (state) {
case ERROR: exit(1);
case ACCEPT: exit(0);
default: new_state = automata[ state ][ to_token(getch()) ];
}
state = new_state;
}
如果您需要在切换状态之前执行任何操作,只需在该状态的切换中添加一个特例即可。或者使用 table 由状态索引的函数指针。