The switch statement provides a very useful alternative to multiple if statements. It is used in conjunction with the case and default statements. The syntax is
switch(integral expression) statement the controlled statement, known as the switch body will consist of a sequence of case statements. The syntax of a case statement is
case constant-integral-expression : statement this is really nothing more than a labelled statement. The meaning of all this is that flow of control passes to the statement whose case label matches the value of the switch expression. The flow of control then continues from that point until a break is encountered or the end of the switch body is encountered. A break statement takes control out of the switch body.
If none of the case labels match the value of the switch expression then no part of the code in the switch body is executed unless a default statement appears within the switch body, this acts as a "catch-all" label when no other case label matches.
An example is in order. This is a variant of a program that has already been seen. It reads in simple expressions and evaluates them.
#include <stdio.h>
main()
{
int n1,n2;
char c;
char inbuf[30];
while(1)
{
printf("Enter Expression ");
if(gets(inbuf) == NULL) break;
sscanf(inbuf,"%d%c%d",&n1,&c,&n2);
switch(c)
{
case '+' :
printf("%d\n",n1+n2);
break;
case '-' :
printf("%d\n",n1-n2);
break;
case '*' :
printf("%d\n",n1*n2);
break;
case '/' :
printf("%d\n",n1/n2);
break;
default :
printf("Unknown operator %c\n",c);
}
}
}
A typical dialogue is shown below Enter Expression 345+45 390 Enter Expression 212/6 35 Enter Expression 234-5 229 Enter Expression 234%4 Unknown operator %Notice the frequent break statements in the switch body, these are necessary to avoid the drop-through between cases. Many people think this drop-through is annoying and the language would be better if a break from the switch body was implicit at the end of each case , however it can sometimes be useful as this example shows.
#include <stdio.h>
main()
{
int c;
int dcnt = 0; /* digits */
int wcnt = 0; /* white space count */
int ocnt = 0; /* others count */
while((c=getchar())!=EOF)
switch(c)
{
case '0' :
case '1' :
case '2' :
case '3' :
case '4' :
case '5' :
case '6' :
case '7' :
case '8' :
case '9' :
dcnt++;
break;
case ' ' :
case '\t' :
case '\n' :
wcnt++;
break;
default :
ocnt++;
}
printf("%d digits\n%d white spaces"
"\n%d others\n",dcnt,wcnt,ocnt);
}
When it consumed its own source the program produced the following output 13 digits 164 white spaces 336 othersA more elaborate use of switch statements is illustrated by the following program that extracts comments from C programs. It is not fooled by comment-like things within string constants but escaped double quotes within strings would cause the program to fail.
/* A program to extract comments */
#include <stdio.h>
#define LEAD 0 /* In normal text */
#define PSCOM 1 /* Possible start of comment */
#define INCOM 2 /* Processing Comment */
#define PECOM 3 /* Possible end of comment */
#define INSTR 4 /* In string constant */
main()
{
int c; /* input character */
int state = LEAD; /* current status */
char *dummy = "/* comment in string */";
while((c=getchar())!=EOF)
{
switch(state)
{
case LEAD :
switch(c)
{
case '/' :
state = PSCOM;
break;
case '"' :
state = INSTR;
break;
}
break;
case PSCOM :
switch(c)
{
case '*' :
state = INCOM;
break;
case '"' :
state = INSTR;
break;
default :
state = LEAD;
break;
}
break;
case INCOM :
switch(c)
{
case '*' :
state = PECOM;
break;
default :
putchar(c);
break;
}
break;
case PECOM :
switch(c)
{
case '/' :
state = LEAD;
putchar('\n');
break;
default :
state = INCOM;
putchar('*');
putchar(c);
break;
}
break;
case INSTR :
switch(c)
{
case '"' :
state = LEAD;
break;
default :
break;
}
break;
}
}
}
When presented with its own source as input the program produced the following output. A program to extract comments In normal text Possible start of comment Processing Comment Possible end of comment In string constant input character current statusThis use of nested switches, whilst it makes for rather clumsy coding, stems from a very simple design technique known as a state switch. The whole operation of the program is described by the following transition table.
+-------+-------+-----------+-----------+-------+
| LEAD | PSCOM | INCOM | PECOM | INSTR |
+------+-------+-------+-----------+-----------+-------+
| / | PSCOM | LEAD | INCOM | LEAD | INSTR |
| | | | print / | print \n | |
+------+-------+-------+-----------+-----------+-------+
| * | LEAD | INCOM | PECOM | INCOM | INSTR |
| | | | | print * * | |
+------+-------+-------+-----------+-----------+-------+
| " | INSTR | INSTR | INCOM | INCOM | LEAD |
| | | | print " | print * " | |
+------+-------+-------+-----------+-----------+-------+
|other | LEAD | LEAD | INCOM | INCOM | INSTR |
| | | | print ch | print * ch| |
+------+-------+-------+-----------+-----------+-------+
The table entries represent the new value of "state" and the action to be taken depending on the current input character (shown in the left hand column) and the current value of state (shown in the top row). In some circumstances as well as changing the value of state it is necessary to take some sort of action, in this case printing out a particular character or the current input character ("ch").