Alternate Decision Structure (Chapter 17)

switch (<int expression>)
{                         // Begin the case block
   case <expression1>:  C statement or statements ending with break
   case <expression2>:      ditto
   . . .                   as many as are required
   default:           C statement or statements possibly ending with break
}                         // End the case block

The default is the equivalent of the bare else  statement in an if / else if structure, except that it can occur anywhere among the case statements and is not restricted to the end.

The above code is equivalent to the following if/else if/.../else structure

if (switch-expression == expression1)
{   first block of code, with NO break
else if (case-expression == expression2)
{   second block of code, with NO break
  .  .  .
{   block of code after default

Common use:  program segment involving a menu, with menu choice as integer, say from 1 to 7

Warning:  if the break is omitted, control passes into the next case block, referred to as falling through.  Sometimes you want this, but most of the time you don't..

Specimen code:  a menu of menus, breakfast, lunch, and dinner, with separate vegan menus.

The first is an if / else if / . . . implementation, the second is a careless conversion to a switch / case structure, and the third is a careful conversion to a switch / case structure
Menu_1.txt   Menu_1.c   Menu_1.exe
Menu_2.txt   Menu_2.c   Menu_2.exe
Menu_3.txt   Menu_3.c   Menu_3.exe

Homework Assignment 2

Modular Program Development / Top-down Design

In my implementation, homework assignment 1 ended up taking more than 150 lines of code for the int main(), but at that point we did not have access to user-defined functions.

The better way to develop is to use a top-down design:

Modular program development fits directly into that:  each subtask becomes a user-defined function.  That function should have a single job, and be small enough to be understood easily.  Typically no more than a page.  The function communicates with the calling function by means of the parameters passed and the single value returned.  In-class examples have already shown this behavior in forcing input of a number in a range (the low and high values passed as parameters), which is returned as the function value.

To aid in this development, the higher level functions can be sketch out by defining each job and then implementing a function with those parameters and value returned initially with a place-holder, a stub function.  In this form, the function simply returns a value that would be valid given its definition.

In homework assignment 1, we can identify these tasks:

char  inputYesNo();          // Get either Y or N, converting lower case
int   irange(int lo, int hi);// Integer range
// Tuition calculations, separated into resident and nonresident
float residentTuition(int grad, int n_credits);
float nonresidentTuition(int grad, int n_credits);

There are two instances in which we require a Yes/No answer and need to reject any other responses.  In addition, we return an upper-case character so that the calling routine can simply test for 'Y' and not have to check both 'Y' and 'y'.

We also need to accept the number of credits, forcing it to be 25 or less.  It also does not make sense to have a negative number of credits, or even zero credits.  So we can do n_credits=irange(1,25);  By far, the messiest part of the problem is computing the current tuition based on the grad./undergrad. status and the number of credits, and it turned out convenient to generate two functions, one for residents and the other for nonresidents.  Each will have six different tuition rates defined as variables within the function.  Here are the stubbed-out functions, where each one is returning a dummy value that is consistent with its definition.

// Get a single character from keyboard.  Force
// either 'y', 'Y', 'n', or 'N'
char inputYesNo()
   // Stub function:  can't say "No"
   return 'Y';

// Accept from the keyboard a value within an integer range.
int irange(int lo, int hi)
   // Stub function:  return the average
   return (lo + hi) / 2;

/* Variable naming for the various rates:
 *   U/G for undergrad./grad.
 *   Re/NR for Resident/NonResident
 *   Lo for 0-9 credits, Mid for 10-18 credits, Hi for >18
float residentTuition(int grad, int n_credits)
   // Stub function:  $1.99
   return 1.99;

float nonresidentTuition(int grad, int n_credits)
   // Stub function:  $2.99
   return 2.99;

Given these definitions, it is possible to develop the main as code that does successfully compile and run.

Welcome to the Tuition Calculator Program

How many total credits are you taking?

Are you a WA resident (Y/N)?
Are you a graduate student (Y/N)?
What percentage increase?  -11.5
Enter a NON-NEGATIVE number, please.  11.5


A graduate resident taking 13 credits currently pays $1.99

With an increase in tuition of 11.5% per credit tuition goes up $0.23,
and a graduate resident taking 13 credits will pay $2.22

Here is the initial state in the top-down solution of the assignment.
functionStub.txt   functionStub.c   functionStub.exe

The main has dropped from around 130 lines to around 80 lines.  It could have gone down further if the logic for the output were isolated in a separate function, with all the necessary variables passed as parameters.  Just that part in my implementation takes about 30 lines.