Home > other >  How do I use goto with swtich in C? (FSM)
How do I use goto with swtich in C? (FSM)

Time:11-02

Let's say I have this code


switch(x)
{

region_1:

  case a:
      ...
  case b:
      goto region_1:

region_2:
      
  case c:
      ...
  case d:
      goto region_2

  default:
      ...

}

Is it possible in C to have such a recursion-like algorithm? Where from any case I can jump to a label and go though cases again? I need to build a FSM for my grand dad, he' planning to catch fish with it.

CodePudding user response:

Why use a switch at all.

For example, say you want to write an automata that checks if the input matches pattern ab c .

Automata:

  • S0:
    • a → S1
  • S1
    • b → S1
    • c → S2
  • S2
    • c → S2
    • EOF → ACCEPT

This could be done with switches, but it could also be implemented using 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);

But you could also write that as follows:

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;
}

But that's really a stepping stone to using 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;
}

If you need to do anything before switching state, just put a special case in the switch for that state. Or use a table of function pointers indexed by state.

CodePudding user response:

You could do something like the following

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:
    //...
}
  • Related