Switch Statement
COP-3223H
Table of Contents
switch statements
switch (expression) {
case value0:
instructions0;
break;
case value1:
instructions1;
break;
case value2:
instructions2;
break;
... // any number of cases
default:
default_instructions;
break;
}
- Evaluate the expression
- Jump to the case corresponding to its value.
- The break statement jumps to the end of the switch
The "break" statement is necessary to avoid "fall-through"
The values can be in any order.
Not all values need to be there.
The default is optional; without it, it's possible that none of the cases will run (like an if without an else).
Example: even or odd
switch (x % 2) {
case 0:
printf("even\n");
break;
case 1:
printf("odd\n");
break;
default:
printf("this should never happen\n");
assert(0);
break;
}
Like else-if statements
if (0 == (x % 2)) {
printf("even\n");
} else if (1 == (x % 2)) {
printf("odd\n");
} else {
printf("this should never happen\n");
assert(0);
}
Simpler syntax for a specific case of conditionals
Example: reading user input
switch (c) {
case 'j':
printf("pressed j, which is down\n");
break;
case 'k':
printf("pressed k, which is up\n");
break;
case 'h':
printf("pressed h, which is left\n");
break;
case 'l':
printf("pressed l, which is right\n");
break;
default:
printf("unexpected key\n");
break;
}
if ('j' == c) {
printf("pressed j, which is down\n");
} else if ('k' == c) {
printf("pressed k, which is up\n");
} else if ('h' == c) {
printf("pressed h, which is left\n");
} else if ('l' == c) {
printf("pressed l, which is right\n");
} else {
printf("unexpected key\n");
}
Example: moving a character
// https://sourceware.org/glibc/manual/latest/html_mono/libc.html#Noncanon-Example
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
/* Use this variable to remember original terminal attributes. */
struct termios saved_attributes;
void
reset_input_mode (void)
{
tcsetattr (STDIN_FILENO, TCSANOW, &saved_attributes);
}
void
set_input_mode (void)
{
struct termios tattr;
/* Make sure stdin is a terminal. */
if (!isatty (STDIN_FILENO))
{
fprintf (stderr, "Not a terminal.\n");
exit (EXIT_FAILURE);
}
/* Save the terminal attributes so we can restore them later. */
tcgetattr (STDIN_FILENO, &saved_attributes);
atexit (reset_input_mode);
/* Set the funny terminal modes. */
tcgetattr (STDIN_FILENO, &tattr);
tattr.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */
tattr.c_cc[VMIN] = 1;
tattr.c_cc[VTIME] = 0;
tcsetattr (STDIN_FILENO, TCSAFLUSH, &tattr);
}
int main(int argc, char **argv) {
char c = '\0';
int width = 40;
int height = 20;
int x = 1;
int y = 1;
int dx = 1;
int dy = 1;
set_input_mode ();
while (1) {
printf("\x1b[2J");
printf("\x1b[H");
printf("\033[%d;%dH", y, x);
putchar('o');
putchar('\n');
printf("\033[%d;%dH", height + 1, 0);
printf("y: %d\n", y);
printf("x: %d\n", x);
printf("c: %c\n", c);
read (STDIN_FILENO, &c, 1);
dx = 0;
dy = 0;
switch (c) {
case 'j':
dy = 1;
break;
case 'k':
dy = -1;
break;
case 'h':
dx = -1;
break;
case 'l':
dx = 1;
break;
case 's':
dy = 1;
break;
case 'w':
dy = -1;
break;
case 'a':
dx = -1;
break;
case 'd':
dx = 1;
break;
}
int newx = x + dx;
int newy = y + dy;
if ((0 < newx) && (newx < width)) {
x = newx;
}
if ((0 < newy) && (newy < height)) {
y = newy;
}
}
}
C gotcha: fall-through
switch (x % 2) {
case 0:
printf("even\n");
break;
case 1:
printf("odd\n");
default:
printf("this should never happen\n");
}
Without a "break", the program will continue running the next case.
case labels are just like labels for goto. The "break" here means goto to end of the switch block.
Sometimes fall-through is used intentionally: