Theswitchstatement is used for multiple-selection decision making. In particular, it is often used to replace nested if/else statements. Before giving the general discussion of the switchstatement, we present a simple example that uses nested if/elsestatements and then an equivalent solution that uses the switchstatement.
Suppose that we have a temperature reading from a sensor inside a large piece of machinery. We want to print a message on the control screen to inform the operator of the temperature status. If the status code is 10, the temperature is too hot and the equipment should be turned off; if the status code is 11, the operator should check the temperature every 5 minutes; if the status code is 13, the operator should turn on the circulating fan; for all other status codes, the equipment is operating in a normal mode. The correct message could be printed with the following set of nested if/elsestatements:
if (code == 10)
printf("Too hot - turn equipment off \n");
else {
if (code == 11)
printf("Caution - recheck in 5 minutes \n");
else {
if (code == 13)
printf("Turn on circulating fan \n");
else
printf("Normal mode of operation \n");
} }
In Problems 1 through 7, draw a flowchart to perform the steps indicated. Then give the cor-responding C statements. Assume that the variables have been declared and have reasonable values.
1. If timeis greater than 15.0, increment timeby 1.0.
2. When the square root of polyis less than 0.5, print the value of poly.
3. If the difference between volt_1andvolt_2is larger than 10.0, print the values of volt_1andvolt_2.
4. If the value of denis less than 0.05, set resultto zero; otherwise, set resultequal to numdivided by den.
5. If the natural logarithm of xis greater than or equal to 3, set timeequal to zero and decrementcount.
6. If distis less than 50.0 and timeis greater than 10.0, increment timeby 2; otherwise, incrementtimeby 2.5.
7. If distis greater than or equal to 100.0, increment timeby 2.0. If distis between 50 and 100, increment timeby 1. Otherwise, increment timeby 0.5.
P R A C T I C E !
P R A C T I C E !
An equivalent statement is the following switchstatement:
switch (code) {
case 10:
printf("Too hot - turn equipment off \n");
break;
case 11:
printf("Caution - recheck in 5 minutes \n");
break;
case 13:
printf("Turn on circulating fan \n");
break;
Thebreakstatement causes the execution of the program to continue with the statement follow-ing the switchstatement (Statement 1), thus skipping the rest of the statements in the braces.
Nestedif/elsestatements do not always easily translate to a switchstatement. However, when the conversion works, the switchstatement is usually easier to read. It is also easier to determine the punctuation needed for the switchstatement. In fact, if the punctuation is not correct in the if/elsestatements, the compiler may not execute the statements as expected.
Theswitchstatement selects the statements to perform based on a controlling expres-sion, which must be an expression of type integer or character. In the general form that fol-lows, case labels (label_1, label_2, . . .) determine which statements are executed, and thus, in some languages, this structure is called a case structure. The statements execut-ed are the ones that correspond to the case for which the label is equal to the controlling ex-pression. The case labels must be unique constants; an error occurs if two or more of the case labels have the same value. The default label provides a statement to execute if no other statement is executed; the default label is optional. Here is the code:
switch (controlling expression)
The statements in the switchstructure usually contain the breakstatement. When the breakstatement is executed, the execution of the program breaks out of the switchstructure, and continues executing with the statement following the switch structure. Without the breakstatement, the program will execute all statements that follow the ones selected with the case label.
Section 3.4 Problem Solving Applied: Face Recognition 97 Although the defaultclause in the switchstatement is optional, we recommend that it be in-cluded so that the steps are clearly specified for the situation in which none of the case labels is equal to the controlling expression.We also use the breakstatement in the default clause to emphasize that the program continues with the statement following the switchstatement.
It is valid to use several case labels with the same statement, as in the following:
switch (op_code) {
case 'N': case 'R':
printf("Normal operating range \n");
break;
case 'M':
printf("Maintenance needed \n");
break;
default:
printf("Error in code value \n");
break;
}
When more than one case label is used for the same statement, the evaluation is performed as if the logical operator ||joined the cases. For this example, the first statement is executed if op_codeis equal to 'N'or if op_codeis equal to 'R'.
Convert the following nested if/elsestatements to a switchstatement:
if (rank==1 || rank==2)
printf("Lower division \n");
else {
if (rank==3 || rank==4)
printf("Upper division \n");
else {
if (rank==5)
printf("Graduate student \n");
else
printf("Invalid rank \n");
} }
P R A C T I C E ! P R A C T I C E !
3.4 Problem Solving Applied: Face Recognition
In this section, we use the new statements presented in this chapter to solve a problem related to facial recognition.
One technique for comparing faces uses ratios of distances between key points on a face, as indicated in Figure 3.7. These ratios might include the distance between the eyes divided by the distance between the nose and the chin. Because these measurements are ratios, they
1. PROBLEM STATEMENT
Given information on three faces, use ratios to determine the two faces that are the most similar.
2. INPUT/OUTPUT DESCRIPTION
The following diagram shows that the inputs to the program are the distance between the outer edges of the eyes and the distance between the tip of the chin and the tip of the nose, for three different images. The output is the image numbers for the two images that are most similar based on ratios of these distances.
Figure 3.7 Key points for face recognition.
can be computed from images of different sizes and should still be similar for the same face.
The computer programs that compute these measurements must be able to locate a face in an image and then also locate the eyes and other key points on the face. There are additional challenges if the head is turned in a different direction in one of the images.
For this problem, assume that we have three images of a person looking at the camera.
We would like to determine if the two images are likely to be of the same person. The technique that we will use is one that compares ratios of the distances between the outer edges of the eyes to the distances between the tip of the chin and the tip of the nose. Write a C pro-gram to read the two distances for each face, compute the ratios, and then determine which two images have the closest ratios.
eye distance, image 1
nose to chin distance, image 2 nose to chin distance, image 1 eye distance, image 2
eye distance, image 3 nose to chin distance, image 3
image number image number
Section 3.4 Problem Solving Applied: Face Recognition 99
3. HAND EXAMPLE
Assume that the following distances are measured from the three images, in cm:
Image 1 Image 2 Image 3
Outer eye distance 5.7 6.0 6.0
Nose to chin distance 5.3 5.0 5.6
We can then compute the ratio of the outer eye distance to the nose to chin distance for each image:
ratio_1= 5.7/5.3 =1.08 ratio_2= 6.0/5.0 = 1.20 ratio_3= 6.0/5.6 = 1.07
We then compute the differences between each pair of ratios, using an absolute value so that each difference is a positive number:
diff_1_2 = | ratio_1 – ratio_2 | = | 1.08 – 1.20 | = 0.12 diff_1_3 = | ratio_1 – ratio_3 | = | 1.08 – 1.07 | = 0.01 diff_2_3 = | ratio_2 – ratio_3 | = | 1.20 – 1.07 | = 0.13
The difference with the smallest value then determines the two images that are the most similar, using these two distances. In this case, image 1 and image 3 are the closest. Note that it is possible that all these differences are large, and thus the smallest of the three may still not represent a good match. Commercial face recognition systems that use dis-tances use a large number of disdis-tances in order to improve their accuracy.
4. ALGORITHM DEVELOPMENT
The first step in the development of an algorithm is the decomposition of the problem solution into a set of sequentially executed steps.
Decomposition Outline
1. Read the distances for each image.
2. Compute the ratios for each image.
3. Compute the differences between each pair of ratios.
4. Find the minimum difference.
5. Print the corresponding image numbers as the best match.
This program has a simple structure, so we can convert the decomposition directly into C.
/*–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* Program chapter3_1 */
/* */
/* This program selects the two images that are most similar */
/* using the distance between the eyes and the distance */
/* between the nose and the chin.
#include <stdio.h>
#include <math.h>
int main(void) {
/* Declare variables. */
double eyes_1, eyes_2, eyes_3, nose_chin_1, nose_chin_2, nose_chin_3, ratio_1, ratio_2, ratio_3, diff_1_2, diff_2_3, diff_1_3;
/* Get user input from the keyboard. */
printf("Enter values in cm. \n");
printf("Enter eye distance and nose-chin distance for image 1: \n");
scanf("%lf %lf",&eyes_1,&nose_chin_1);
printf("Enter eye distance and nose-chin distance for image 2: \n");
scanf("%lf %lf",&eyes_2,&nose_chin_2);
printf("Enter eye distance and nose-chin distance for image 3: \n");
scanf("%lf %lf",&eyes_3,&nose_chin_3);
/* Compute ratios. */
ratio_1 = eyes_1/nose_chin_1;
ratio_2 = eyes_2/nose_chin_2;
ratio_3 = eyes_3/nose_chin_3;
/* Compute differences. */
diff_1_2 = fabs(ratio_1 – ratio_2);
diff_1_3 = fabs(ratio_1 – ratio_3);
diff_2_3 = fabs(ratio_2 – ratio_3);
/* Find minimum difference and print image numbers. */
if ((diff_1_2 <= diff_1_3)) && (diff_1_2 <= diff_2_3) printf("Best match is between images 1 and 2 \n");
if ((diff_1_3 <= diff_1_2)) && (diff_1_3 <= diff_2_3) printf("Best match is between images 1 and 3 \n");
if ((diff_2_3 <= diff_1_3)) && (diff_2_3 <= diff_1_2) printf("Best match is between images 2 and 3 \n");
/* Exit program. */
return 0;
}
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
5. TESTING
We first test the program with the data from the hand example. This generates the following interaction:
Enter values in cm.
Enter eye distance and nose-chin distance for image 1:
5.7 5.3
Section 3.5 Loop Structures 101 Enter eye distance and nose-chin distance for image 2:
6.0 5.0
Enter eye distance and nose-chin distance for image 3:
6.0 5.6
Best match is between images 1 and 3
The answer matches the hand example, so we can then test the program with additional lengths. Print an image of each of three different friends and see if you can predict which pair would be the best match for this very simple face recognition system.
Run the program with information from two different images of the same person and a third person to see if this technique selects the two images that are from the same person.
These problems relate to the program developed in this section for finding the best matching pair from three images.
1. Modify the program so that it also prints out all three differences. This gives additional information about the quality of the match; if the differences are small, the quality of the match is better.
2. What would the output be if two of the ratios were the same minimum value? What would the output be if all three of the ratios were the same value? Generate data to make these cases happen and check your answers.
3. Modify the program to use a nested ifstatement in the solution instead of three independentifstatements. Does the answer to Problem 2 change with this solution?
4. Modify the program to print the image numbers for the two images that are the most different.
5. Modify the program to print the best match between four images. (Note that this causes the program to get longer, because with four images there are six possibilities.
In Chapter 5 we will learn additional C language functionality that allows us to handle situations such as this one without ever increasing lines of code.)
M O D I F Y ! M O D I F Y !
3.5 Loop Structures
Loops are used to implement repetitive structures. C contains three different loop structures—
thewhileloop, the do/whileloop, and the forloop. In addition, C allows us to use two ad-ditional statements with loops to modify their performance—the breakstatement (which we used with the switchstatement) and the continuestatement.
Before presenting these loop structures, we would like to present two debugging sugges-tions that are useful when trying to find errors in programs that contain loops. When compil-ing longer programs, it is not uncommon to have a large number of compiler errors. Rather than trying to find each error separately, we suggest that you recompile your program after correcting several obvious syntax errors.One error will often generate several error messages.
Some of these error messages may describe errors that are not in your program, but were printed because the original error confused the compiler.
The second debugging suggestion relates to errors inside a loop. When you want to de-termine if the steps in a loop are working the way that you want, include printfstatements in the loop to provide a memory snapshot of key variables each time the loop is executed.
Then, if there is an error, you have much of the information that you need to determine the cause of the error.
while
Loop
The general form of a whileloop follows:
while (condition) {
statements;
}
The condition is evaluated before the statements within the loop are executed. If the condition is false, the loop statements are skipped, and execution continues with the statement follow-ing the whileloop. If the condition is true, then the loop statements are executed, and the condition is evaluated again. If it is still true, then the statements are executed again, and the condition is evaluated again. This repetition continues until the condition is false. The state-ments within the loop must modify variables that are used in the condition; otherwise, the value of the condition will never change, and we will either never execute the statements in the loop or we will never be able to exit the loop. An infinite loop is generated if the condi-tion in a whileloop is always true. Most systems have a system-defined limit on the amount of time that can be used by a program and will generate an execution error when this limit is exceeded. Other systems require that the user enter a special set of characters, such as the con-trol key followed by the character c(abbreviated as ) to stop or abort the execution of a pro-gram. Nearly everyone eventually writes a program that inadvertently contains an infinite loop, so be sure that you know the special characters to abort the execution of a program for your system.
The following pseudocode and program use a whileloop to generate a conversion table for converting degrees to radians (note that the degree values start at 0°, increment by 10°, and go through 360°):
Refinement in Pseudocode main: set degrees to zero while degrees ≤ 360
convert degrees to radians print degrees, radians add 10 to degrees
¿c Infinite loop
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* Program chapter3_2 */
/* */
/* This program prints a degree-to-radian table */
/* using a while loop structure. */
#include <stdio.h>
#define PI 3.141593 int main(void) {
/* Declare and initialize variables. */
int degrees=0;
double radians;
/* Print radians and degrees in a loop. */
printf("Degrees to Radians \n");
while (degrees <= 360) {
radians = degrees*PI/180;
printf("%6i %9.6f \n",degrees,radians);
degrees += 10;
}
/* Exit program. */
return 0;
}
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
The first few lines of output from the program are the following:
Degrees to Radians 0 0.000000 10 0.174533 20 0.349066 . . .
do/while
Loop
Thedo/whileloop is similar to the whileloop except that the condition is tested at the end of the loop instead of at the beginning of the loop. Testing the condition at the end of the loop en-sures that the do/whileloop is always executed at least once; a whileloop may not be execut-ed at all if the condition is initially false. The general form of the do/whileloop is as follows:
do {
statements;
} while (condition);
The following pseudocode and program print the degree-to-radian conversion table using ado/whileloop instead of a whileloop:
Section 3.5 Loop Structures 103
Refinement in Pseudocode main: set degrees to zero
do
convert degrees to radians print degrees, radians add 10 to degrees while degrees ≤ 360
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/
/* Program chapter3_3 */
/* */
/* This program prints a degree-to-radian table */
/* using a do-while loop structure. */
#include <stdio.h>
#define PI 3.141593 int main(void) {
/* Declare and initialize variables. */
int degrees=0;
double radians;
/* Print radians and degrees in a loop. */
printf("Degrees to Radians \n");
do {
radians = degrees*PI/180;
printf("%6i %9.6f \n",degrees,radians);
degrees += 10;
} while (degrees <= 360);
/* Exit program. */
return 0;
}
/*––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––*/