An introduction to Conditional Statements in C
Each C program we have examined up to this point follows exactly the same steps every time it is run. A program begins execution at the start of the main procedure, and the program executes each successive line from the first to the last.
Such programs may perform simple tasks, but their usefulness is limited. For example, consider the following problem:
Problem: Find the smallest of three integers
In this problem, the user should enter three integers at the keyboard. The program then should examine each integer and determine which is smallest.
In this situation, any of the three initial integers might be the smallest, so the program will have to make decisions as it examines the user input.
Most programs must make decisions, based on the results of various tests. The program then may perform different actions, depending upon the results of each test. To perform these tests and manage the flow of execution, C provides three constructs, called conditional statements:
if statements
The first program to find the smallest of three integers compares each number in turn to the other two. Processing within the program considers three cases in turn:
-
The first number is smallest (e.g., it is smaller than the other two).
-
The second number is smallest (e.g., it is smaller than the other two).
-
The third number is smallest (e.g., it is smaller than the other two).
For each case, a test determines if the integer is smallest. If so, text is printed.
The full program is available as smallest3-1.c
/* A simple program to find the smallest of three numbers * * Version 1: using simple if-then statements */ #include <stdio.h> int main (void) { int i1, i2, i3; printf ("Program to determine the smallest of three integers\n"); printf ("Enter 3 integers: "); scanf ("%d %d %d", &i1, &i2, &i3); printf ("Considering the three numbers: %d %d %d,\n", i1, i2, i3);
Program notes
-
Preliminaries:
- Declare variables for the three integers
- Print initial program information
- Read the three integers
if ((i1 <= i2) && (i1 <= i3)) printf (" the smallest value is %d\n", i1); if ((i2 < i1) && (i2 <= i3)) printf (" the smallest value is %d\n", i2); if ((i3 < i1) && (i3 < i2)) printf (" the smallest value is %d\n", i3); return 0; }
In this program, the computer executes all three of the three if statements in turn. In each case, the Boolean expression (placed in parentheses) is evaluated. When the condition is true, the corresponding printf is executed.
For this particular program, the Boolean expressions are carefully chosen, so that exactly one will be true, ensuring only one line of output will be printed.
-
When the three numbers are distinct, one will certainly be small than the other two, and the relevant output appears.
-
Care is needed when two or three of the integers are equal. The reader is encouraged to check that only one line is printed.
-
The if statement has the form
if (condition) statement
-
The "condition" can be any Boolean expression, which is placed in parentheses after the keyword if. See the reading on Boolean expressions for more discussion of these Boolean expressions.
-
Within an if statement, the "condition" is evaluated.
- If the "condition" is true, the "statement" is executed.
- If the "condition" is false, the "statement" is skipped.
if-else Statements
The if-else statement also tests a condition. As with the if statement, one statement is executed if the condition is true. In addition, with the if-else statement, a different statement is executed if the condition is false.
For illustration, three versions follow, computing the smallest of three integers. All use if-else statements. In these versions, a first if-else statement limits the cases that must be considered, so there is no need to evaluate three conditions when answers already are known.
The following version proceeds in two steps. First, the program determines the smaller of the first two integers. Second, the smaller value is compared with the third integer to determine the smallest of the three.
/* A simple program to find the smallest of three numbers * * Version 2: using if-the-else statements with intermediate steps */ #include <stdio.h> int main (void) { int i1, i2, i3; int smaller, smallest; printf ("Program to determine the smallest of three integers\n"); printf ("Enter 3 integers: "); scanf ("%d %d %d", &i1, &i2, &i3); printf ("Considering the three numbers: %d %d %d,\n", i1, i2, i3);
Program notes
This version requires the declaration of intermediate variables, smaller and smallest. Otherwise, this program starts the same way as Version 1. The full program is available as smallest3-2.c.
if (i1 <= i2) smaller = i1; else smaller = i2; if (smaller <= i3) smallest = smaller; else smallest = i3; printf ("The smallest value is %d\n", smallest); return 0; }
After preliminaries in this program, condition i1 <= i2 is evaluated.
-
If the condition is true, then the program executes the statement
smaller = i1;
-
If the condition is false, then the program executes the statement
smaller = i2;
Overall, at the end of the first if-else statement, the variable smaller will store the smaller value of what is stored in i1 and i2.
The second if-else statement follows the same approach, comparing the values stored in smaller and i3, and variable smallest is assigned the smaller integer value.
-
The if-else statement has the form
if (condition) statement1 else statement2
-
As with the if statement, the "condition" can be any Boolean expression, which is placed in parentheses after the keyword if.
-
Within an if-else statement, the "condition" is evaluated.
- "statement1" is executed if the "condition" is true.
- "statement2" is executed if the "condition" is false.
The next version of the program compares i1 with i2.
-
If i1 is smaller, then i1 is compared with i3 (no need to consider i2 further).
-
If i2 is smaller, then i2 is compared with i3 (no need to consider i1 further).
This program requires variable smallest, which is set based on various tested cases. The full program is available as smallest3-3.c
/* A simple program to find the smallest of three numbers * * Version 3: using nested if-else statements */ #include <stdio.h> int main (void) { int i1, i2, i3; printf ("Program to determine the smallest of three integers\n"); printf ("Enter 3 integers: "); scanf ("%d %d %d", &i1, &i2, &i3); printf ("Considering the three numbers: %d %d %d,\n", i1, i2, i3);
-
This program uses one extra variable smallest, but otherwise the preliminaries are the same as with both versions 1 and 2.
if (i1 <= i2) /* compare i1 and i3; i2 cannot be smallest */ if (i1 <= i3) smallest = i1; else smallest = i3; else /* compare i2 and i3; i1 cannot be smallest */ if (i2 <= i3) smallest = i2; else smallest = i3; printf (" the smallest value is %d\n", smallest); return 0; }
Since exactly one statement is executed when the initial test if (i1 < i2) is true and a second statement is executed when the initial test is false, this program organizes the cases logically to produce the appropriate result. However, reading this code may be difficult, with several appearances of the keywords if and else. Thus, indenting is used here to clarify what statements go with each of the logical tests and cases.
More generally, it is essential to indent under each if and else construct, so the reader can clearly understand what code fits where!
-
With both the if and if-then constructs, exactly one C statement is executed if the condition is true. For the if-else, exactly one C statement is executed if the condition is false.
-
An if and if-then construct each count as a single statement.
-
The statement if i1 <= i3 counts as the single statement executed, if the first condition if i1 <=i2 is true
-
The statement if i2 <= i3 counts as the single statement executed, if the first condition if i1 <=i2 is false
-
-
Jargon When one if or if-then statement appears within another, the statements are said to be nested. Thus, this program illustrates the use of nested if statements.
Although the previous version of this program is syntactically correct and the program runs properly, the comments regarding readability raise two issues:
-
Although indenting helps a human reader understand the intention of the nested if statements, the computer does not recognize indenting as indicating program structure. How can we be certain that the computer will recognize the proper if and else constructs as intended?
-
The if and if-then constructs only allow one statement to be executed, based on a condition. How can we write code, in which several statements are executed if a condition is true or if it is false?
To address both issues, C allows a block of code statements to be grouped together with braces { ... }, and the statements within the braces count as a single statement for if and if-else statements. This grouping of statements with braces is illustrated in the next version of our program, which functionally works exactly the same as the previous version.
/* A simple program to find the smallest of three numbers * * Version 4: using nested if-then-else statements */ #include <stdio.h> int main (void) { int i1, i2, i3; int smallest; printf ("Program to determine the smallest of three integers\n"); printf ("Enter 3 integers: "); scanf ("%d %d %d", &i1, &i2, &i3); printf ("Considering the three numbers: %d %d %d,\n", i1, i2, i3);
if (i1 <= i2) /* compare i1 and i3; i2 cannot be smallest */ {if (i1 <= i3) smallest = i1; else smallest = i3; } else /* compare i2 and i3; i1 cannot be smallest */ {if (i2 <= i3) smallest = i2; else smallest = i3; } printf ("The smallest value is %d\n", smallest); return 0; }
-
The braces around the statement after if and after the outside else clarify what code is to be execute if i1 <= i2 is true and what code to execute if the condition is false.
-
If desired, additional statements could be inserted with the braces, so the program could do more than one activity if i1 < i2 is true and more than one activity if the test is false.
A Technical Observation
Since C provides both if if-else statements, we can consider what happens when these constructs combine. In particular, consider the following code segment.
int a = 1; int b = 2; int c = 3; if (a < b) if (b > c) c = 10; else c = 100;
As the indenting suggests in this code, two interpretations of this code are possible:
-
The else clause might go with the first if (a < b). In the example, this test is true, the else clause is never executed, and c is not assigned the value 100.
-
The else clause might go with the second if (b > c). In the example, the earlier test (a < b) is true, so the second if (b > c) is executed. Since that test is false, the else now is executed, and c is assigned the value 100.
In summary, syntax allows the else clause to be combined with either if — the syntax combining if and if-else is ambiguous.
In practice, C resolves this ambiguity by following the second interpretation; an else clause is paired with the most recent if.
switch Statements
Although if and if-else statements apply in a wide range of circumstances, they sometimes can be cumbersome. Two examples follow:
-
Write a program that reads an integer.
- If the integer is 0, 1, 2, ..., 10, the program prints "zero", "one", "two", ..., "ten"., respectively.
- Otherwise, the program prints "not between zero and ten, inclusive".
-
Write a program to use the Scribbler 2 light sensors (on the Fluke) to report the intensity of light in the environment. According to Scribbler 2 sensor documentation, values near 0 indicate a bright light, whereas values near 65535 indicate darkness. (With their output, one might argue the "light" sensors are really "dark" sensors.) Write a program that prints
- "very bright" for sensor readings between 0 and 9999
- "bright" for sensor readings between 10000 and 19999
- "moderate light" for sensor readings between 20000 and 29999
- "dim light" for sensor readings between 30000 and 39999
- "dark" for sensor readings between 40000 and 49999
- "very dark" for sensor readings between 50000 and 59999
- "pitch black" for sensor readings at or above 60000
In each case, a program could utilize nested if statements, such as
if (value == 0) printf ("zero"); else if (value == 1) printf ("one"); . . . else if (value == 10) printf ("ten"); else printf ("not between zero and ten, inclusive");
Although this works, the if syntax with else seems somewhat cumbersome.
In C, an alternative is to identify individual cases (for integers), using a switch statement. Program integer-words.c illustrates this alternative approach using switch.
/* This program reads an integer: If the integer is between 0 and 10, inclusive, the program prints the number's name. If the integer is outside the range 0 to 10, the program prints "not between zero and ten, inclusive". */ #include <stdio.h> int main () { /* declarations and preliminaries */ int value; printf ("This program prints the name of small positive integer\n"); printf ("Enter an integer value: "); scanf ("%d", &value); switch (value) { case 0: printf ("zero\n"); break; case 1: printf ("one\n"); break; case 2: printf ("two\n"); break; case 3: printf ("three\n"); break; case 4: printf ("four\n"); break; case 5: printf ("five\n"); break; case 6: printf ("six\n"); break; case 7: printf ("seven\n"); break; case 8: printf ("eight\n"); break; case 9: printf ("nine\n"); break; case 10: printf ("ten\n"); break; default: printf ("not between zero and ten, inclusive\n"); break; } }
Program notes
-
The header provides the expected description of the program's behavior.
-
The first part of the code explains the program's purpose, and reads the integer to be analyzed.
-
C's switch statement begins with the word switch and an integer variable or expression in parentheses.
-
The body of the switch statement is placed in brackets { }.
-
The body of the of the switch statement identifies specific cases and the code to be executed for each case. Here,
- case 0: identifies code to be executed if the variable (value in this program) is 0.
- Code following the case (in this situation, printf ("one\n");) provides the details for a specific circumstance.
- break indicates when processing for a specific case should stop.
-
default, at the end of the switch statement body identifies code that should be executed if none of the specified cases are found.
-
The break statement indicates when the program will stop processing a given case. In the example,
- The program (with the break statements included) will print exactly one word when 0 or 1 or 2 or ... or 10 is entered.
-
If the break statements were omitted at the end of
case 0, 1, and 2, then when the user types 0, the program would print
zero one two
In this situation, the value variable is 0, so the program starts with case 0, and prints "zero". Without a break, the program then would continue onto case 1, printing "one", and then onto case 2 to print "two". When a break is encountered, the computer stops its execution of the switch.
In this code, different actions are needed for each of the cases. However, if the same code is to be executed for multiple cases, the case labels may be groups together before the code to be executed:
case 0: case 1: case 4: case 9: printf ("the integer is non-negative\n"); printf ("the integer is a perfect square\n"); break;
-
When cases are grouped together, break does not appear until after the executable code for the multiple cases.
-
Although break is not required after default (there are no further cases to be considered), it is common to include this break for parallelism with the other cases.
Turning to the problem of describing the amount of light or darkness in an environment, we observe that the categorization proceeds in increments of 10000. Given a lightReading from the sensors, the expression lightReading/10000 gives an integer 0, 1, 2, 3, 4, 5, 6 for numbering the categories. The following program light-switch.c illustrates how this observation can be used in a program.
Recall that MyroC header describes in some detail various functions that determine the values reported by the Scribbler 2 and Fluke sensors.
/* This program reads the center light sensor on the front of the Scribbler 2 robot and reports the brightness category of the current environment. */ #include <stdio.h> #include "MyroC.h" int main () { printf("This program reports the brightness of the Scribbler 2's environment\n"); /* connect to the Scribbler 2 robot */ rConnect ("/dev/rfcomm0"); /* obtain the average of 3 readings of the center light sensor */ int lightReading = rGetLightTxt ("center", 3); printf ("The reading from the center light sensor is %d (out of 65535)\n", lightReading);
-
Use of the Scribbler 2 robot requires an initial rConnect command.
-
This rGetLightTxt command asks for the average of 3 readings from the center light sensor, located on the Scribbler 2 robot.
/* determine the brightness category */ switch (lightReading/10000) { case 0: printf ("The area is very bright\n"); break; case 1: printf ("The area is bright\n"); break; case 2: printf ("The area has moderate light\n"); break; case 3: printf ("The area has dim light\n"); break; case 4: printf ("The area is dark\n"); break; case 5: printf ("The area is very dark\n"); break; case 6: printf ("The area is pitch black\n"); break; default: printf ("computational error --- no category identified\n"); break; } }
-
Since the rGetLightTxt function returns values between 0 and 65535, rGetLightTxt / 10000 must give values between 0 and 6 (integer division drops any remainder).
-
The switch statement identifies each of these cases and prints the appropriate category.
Acknowledgments
The narrative in this lab draws from two primary sources:
-
An Introduction to C Through Annotated Examples by Henry M. Walker
-
An integrated reading and laboratory exercise on condition statements, originally by David Cowden, with revisions, editing, and reorganization by Dilan Ustek and Henry M. Walker.
An Introduction to C Through Annotated Examples by Henry M. Walker |
![]() ![]() |
||
created 7 September 7 1997 by Henry M. Walker revised 24 April 2001 by Henry M. Walker | |||
Reading and Laboratory Exercise on Conditional Statements | |||
created 22 July 2011 by David Cowden last full revision 29 July 2011 by David Cowden minor editing 24 August 2011 by Henry M. Walker moderate editing 3 October 2011 by Henry M. Walker moderate editing 5 October 2011 by Dilan Ustek editing (wording for cp, html corrections) 20 July 2012 by Henry M. Walker editing (updated URL) 10 September 2013 by Henry M. Walker reorganized 25 January 2014 by Henry M. Walker readings added 19 September 2014 by Henry M. Walker |
|||
Full, merged reading | |||
created 9 July 2016 by Henry M. Walker revised 16 July 2016 by Henry M. Walker | |||
For more information, please contact Henry M. Walker at walker@cs.grinnell.edu . |