Topical Information

This program should help clarify to you the use of templates.

Program Idea

You've been thinking about some cascading if/switch structures (aside from those bad dreams, I mean). You wonder if maybe you could make them more re-usable by changing them into loops looking through an array. Let's give it a shot:

Given the if structure:

    if (score >= 90)
    {
        grade = 'A';
    }
    else if (score >= 80)
    {
        grade = 'B';
    }
    else if (score >= 70)
    {
        grade = 'C';
    }
    else if (score >= 60)
    {
        grade = 'D';
    }
    else
    {
        grade = 'F';
    }

You see that there are numbers being translated into letters. You envision a set of parallel arrays:

    cutoffs        grades
    +----+         +---+
    | 90 | <- 0 -> | A |
    +----+         +---+
    | 80 |    .    | B |
    +----+         +---+
    | 70 |    .    | C |
    +----+         +---+
    | 60 |    .    | D |
    +----+         +---+
    |  0 | <- 4 -> | F |
    +----+         +---+

    MAX_cutoff = 5

Now you write a simple loop:

    i = 0;
    while (i < MAX_cutoff && score < cutoffs[i])
    {
        i++;
    }
    grade = grades[i];

A little testing shows that this seems to work for normal cases, but fails when the data is over 100% or below 0% (whether by accident or on purpose). You decide to write the input functions to avoid such non-sense as negative scores, but think maybe the over 100% wouldn't be bad if it were your score. So you alter your arrays a bit:

    cutoffs         grades
    +-----+         +---+
    | 100 | <- 0 -> | + |
    +-----+         +---+
    |  90 |    .    | A |
    +-----+         +---+
    |  80 |    .    | B |
    +-----+         +---+
    |  70 |    .    | C |
    +-----+         +---+
    |  60 |    .    | D |
    +-----+         +---+
    |   0 | <- 5 -> | F |
    +-----+         +---+

    MAX_cutoff = 6

Checking again, everything is working except the negatives. Just in case someone by-passes your input routines, you decide to make it safe and change:

    grade = (i >= MAX_cutoff) ? ('U') : (grades[i]);

Now everything is working fine!

Note how no changes are needed to the loop! Just the array needed to be changed to adjust it!

Could this possibly be made into a nice generic function that could be applied to many problems -- simply getting the arrays and overflow error value as arguments? Wow!

Thought Provoking Questions (I)

  1. Why don't we need to check both ends of the bounds for a grade?

  2. What inputs would your generic function need? What value would it return?

  3. How generic is it, really? Would you need to overload it if you changed the above program to translate from insurance codes to deduction values (like in the payroll program)? How many overloaded version can you see the need for?

  4. Are the 0 and F in the last position needed? Why/Why not?

  5. Does this loop processing take any extra time over a branching structure? What operations need to be performed to find, say, a D in each case?

Program Information

Write a program using the above idea but to solve the following situation:

In a certain application (details withheld to protect the company's 'privacy'), legitimate values are:

     Range of Values          Category
        0 -  5                    B
        8 - 14                    N
       20 - 21                    Q
       25 - 43                    D
       50 - 59                    N
       60 - 99                    A

The values are decimal ones -- not integers (the cutoff valuse just happen to be whole numbers). Any value not inside a specified range is considered invalid and should receive a category value of '-'. (Note that category 'N' has two ranges associated with it...)

Write templated functions which can receive a value, the arrays for legal value limits and resulting categories, and an invalid category value and return the resulting mapped category. (You'll have at least two -- one for this program and one for the grade situation as above.) Place these in a library (conversion.h?).

Test these functions with a simple driver program.

Thought Provoking Questions (II)

  1. Did I leave any arguments out of the list above? If so, what is it?

  2. Can you get away with just checking one end of a range as we did in the grades program above? Why/Why not?

  3. How many arrays will it take to store the value ranges?

  4. Are any of your functions' arguments 'const'? Are they actually constants or did C++'s argument passing rules force your use of 'const'?

  5. Which arguments should be templated? How many template 'blanks' are there for each function?

  6. For each template 'blank' for each function, what operations are required to be supported by the instantiation type?

  7. How many tests will be needed to prove your function works? How did you determine that without the branches there to help you count?

  8. Can you think of any other places such 'conversion' loops might come in handy?

This assignment is (Level 3.5).

Options

Thinking about it, you realize that many programs might have several related sets of conversion arrays. Add (Level 0.5) to allow them to concatenate these arrays together and still use your functions to use just the piece for the current conversion:

  +- +-----+        +---+ -+
  |  | 100 |        | + |  |
  c  +-----+        +---+  g
  u  |  90 |        | A |  r
  t  +-----+        +---+  a
  o  |  80 |        | B |  d
  f  +-----+        +---+  e
  f  |  70 |        | C |  s
  s  +-----+        +---+  |
  |  |  60 |        | D |  |
  |  +-----+        +---+  |
  |  |   0 |        | F |  |
  +- +-----+        +---+ -+
  |  |  60 |        | P |  |
  "  +-----+        +---+  "  (same for pass-fail courses)
  |  |   0 |        | F |  |
  +- +-----+        +---+ -+

(Hint: Think about using just a part of the array -- not just from 0 to size-1 but from start to end. See many examples I've done this semester in your notes or on the web site.)