Digamos que tengo este código
switch(x) { region_1: case a: ... case b: goto region_1: region_2: case c: ... case d: goto region_2 default: ... }¿Es posible en C tener un algoritmo similar a la recursividad? ¿En qué casos puedo saltar a una etiqueta y revisar los casos nuevamente? Necesito construir un FSM para mi abuelo, planea pescar con él.
Podrías hacer algo como lo siguiente
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: //... }¿Por qué usar un interruptor?
Por ejemplo, supongamos que desea escribir un autómata que verifique si la entrada coincide con el patrón ab+c+ .
Autómatas:
Esto podría hacerse con interruptores, pero también podría implementarse usando 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);Pero también podrías escribirlo de la siguiente manera:
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; }Pero eso es realmente un trampolín para usar tablas.
#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 ABCDEF */ /* 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 abc */ /* ----- ------- ------- ------- ------- ------- */ /* 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; }Si necesita hacer algo antes de cambiar de estado, simplemente coloque un caso especial en el interruptor para ese estado. O use una tabla de punteros de función indexados por estado.