The Selection Structure Cont.

Another form of the selection structure in C is the switch statement. A switch statement takes the form:
	switch ( integral-expression ) {
		case const1: 	stmt1;
				stmt2;
				...
				break;
		case const2:	stmt3;
				stmt4;
				...
				break;
		case const3:	...
		...
		default:	stmt5;
				stmt6;
				...
	}
The integral-expression must evaluate to an integer value (or integer-like value from a non-continuous set, like a character). The values after each case must be integer constants; they may not be expressions. The integral-expression value is compared to each of the constants, and statements begin executing at the first matching constant. The break statements cause control to be transferred outside the switch statement. If it is omitted, control falls through to each successive case, which is usually not what we want. If none of the case values matches the expression, statements after the default label begin executing. default is optional; in some cases, it is superfluous since it is clear from the context that only the named cases are possible values for expressions, while in other cases it is needed to catch unexpected values. The behavior of a switch statement without a default for which there is no matching value is undefined, so a C program in which this occurs cannot be considered correct.

Here is an example of the switch statement. The user is presented with a menu giving three options: sadness, happiness, and apathy. Depending on which option is chosen, an appropriate emoticon (happy or sad face drawn with ASCII characters) is printed.
#include <stdio.h>

int main () {
	int	choice;

	/* prompt for and read in option */

	printf ("Choose the option best describing you:\n");
	printf ("1: Happy\n2: Sad\n3: Don't Care\n");
	scanf ("%d", &choice);
	switch (choice) {
		case 1:	printf (":-)\n"); /* happy face */
			break;
		case 2: printf (":-(\n"); /* sad face */
			break;
		case 3: printf (":-|\n"); /* apathetic face */
			break;
		default:printf (":-P\n"); /* sticking tongue out */
	}
	return 0;
}

Extra for Experts

Note that you never need to use switch, since the functionality it provides is a strict subset of if, i.e., you can always use if instead of switch. However, some implementations of the C language allow large switch statements to be executed more efficiently than the equivalent if by building a table of addresses indexed by the value of the integral expression. Instead of laboriously comparing the value to each of the case values, the compiler simply "jumps" to the correct case by indexing into the table with the value. The added overhead only pays off if you have several or more cases, though.

The Iteration Structure

The last in the three structures of structured programming is the iteration structure. It causes actions to be repeated over and over while some condition is true. The iteration structure is implemented in C in several different ways. The simplest is the while statement. A while statement takes the form:
	while ( expression ) stmt;
The expression is evaluated. If it is true (i.e., non-zero), then the stmt is executed. Then the expression is evaluated again, and the stmt executed again if the value is true. This continues until the expression is no longer true; presumably, stmt contains some code causing the value of expression to turn false eventually, or issues the break statement which aborts the while loop regardless of the value of expression.

Iteration is essential for many tasks we want to do with computers. For instance, recall the program from lecture 3 that asks the user his or her age, then computes the ranges of heart rates for aerobic exercise. If the user types in a negative number, or a number greater than 220, the program will give wrong answers. Since no one has a negative age or is older than 120 years (and still does aerobics), checking to see if the input is in this range would avoid this error. One method suggested in class was to use an if statement to check the range before proceeding with the computation; if the input was invalid, the program would exit. A more robust program would inform the user of the error and allow him or her to enter the value again. No matter how many if statements we put in the program, the user might mess up one more time than that and again cause us to exit the program. A better solution would be for the program to loop while the input is out of the valid range:
#include <stdio.h>

int main () {
	int	age;
	float	mhr, r1, r2;

	/* prompt for and get age */

	printf ("How old are you? ");
	scanf ("%d", &age);

	/* validate age, possibly reading it in again */

	while (age > 120 || age < 0) {
		printf ("No, you are not.  Please enter your age: ");
		scanf ("%d", &age);
	}

	/* compute mhr and ranges */

	mhr = 220.0 - age;
	r1 = 0.65 * mhr;
	r2 = 0.80 * mhr;

	/* let user know his or her range for aerobic exercise */

	printf  ("Your heart rate should be"
		" between %0.2f and %0.2f during aerobic exercise\n", r1, r2);

        return 0;
}
Note that, as with the if statement, the statement following while may be a compound statement enclosed in curly braces.

Let's look at another example of iteration. Suppose we have a list of positive numbers and we would like to know the average of the numbers. Recall that the average of a set of numbers is the sum of the set divided by the size of the set. Here is a program that will read a list of positive numbers, the print their average. The end of the list is signalled by a -1 as input (this is known as using a sentinel in the input):
#include <stdio.h>

int main () {
	float	input, sum;
	int	n;

	/* zero numbers seen so far */

	n = 0;

	/* sum starts out as zero */

	sum = 0;

	/* prompt and do a priming read */

	printf ("Enter a list of numbers, -1 to finish */

	scanf ("%f", &input);

	/* read until end of input, summing numbers */

	while (input != -1.0) {

		/* add input to sum */

		sum += input;

		/* count one more item */

		n++;

		/* read more input */

		scanf ("%f", &input);
	}

	/* make sure n isn't zero */

	if (n) {
		printf ("average is %f\n", sum / n);
	} else {
		printf ("no numbers input!\n");
	}
}
(Note the use of the += operator, that adds the left and right hand operands, with the side effect of placing the result in the left operand.) The first scanf is known as a priming read, so that the while statement has something to work on initially. The subsequent scanfs take place inside the while loop and continue until -1 is read. At each iteration, the input is added to the sum and the count of items is incremented. At the end, if at least one data item has been input, the ratio of sum to number of items is printed. Note that on some systems, this program could use a few input buffer flushes to process numbers read across newlines.