CSC 161 Grinnell College Fall 2016
Scribbler 2
CSC 161:
Imperative Problem Solving and Data Structures
Scribbler 2
Course Home Syllabus Schedule MyroC Documentation Acknowledgments

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:

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


   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.


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.

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 next version of the program compares i1 with i2.

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);

   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!


Although the previous version of this program is syntactically correct and the program runs properly, the comments regarding readability raise two issues:

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;
}

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:

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:

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


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;

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 documentation 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);

  /* 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;
    }
}

Acknowledgments

The narrative in this lab draws from two primary sources:



An Introduction to C Through Annotated Examples by Henry M. Walker Valid HTML 4.01! Valid CSS!
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 .