Program Failure

We should pay some more attention to the notion of program failure, as it's very important. The first question, of course, is what it means to say that a program “fails”. A valid answer is that it doesn't work correctly, but that isn't very specific.

As you can imagine, this notion was the topic of some discussion with Susan:

Susan: What do you mean by a program failing? I know it means it won't work, but what happens? Do you just get error messages, and it won't do anything? Or is it like the message that you have on page 188?

Steve: In general, a program “failing” means that it does something unexpected and erroneous. Because I have put some safety features into the implementation of Vec, you'll get an error message if you misuse a Vec by referring to a nonexistent element.

In general, a program failure may or may not produce an error message. In the specific case that we've just seen, we'll probably get an error message while trying to access a nonexistent element of the Weight Vec. However, it's entirely possible for a program to just “hang” (run endlessly), “crash” your system, produce an obviously ridiculous answer, or worst of all, provide a seemingly correct but actually erroneous result.

The causes of program failures are legion. A few of the possibilities are these:

  1. Problems isolated to our code

    1. The original problem could have been stated incorrectly.

    2. The algorithm(s) we're using could have been inappropriate for the problem.

    3. The algorithm(s) might have been implemented incorrectly.

    4. An input value might be outside the expected range.

    And so on...

  2. Problems interacting with other programs

    1. We might be misusing a function supplied by the standard library, like the << operator.

    2. The documentation for a standard library function might be incorrect or incomplete. This is especially common in “guru”-oriented operating systems, where the users are supposed to know everything.

    3. A standard library function might be unreliable. This is more common than it should be.

    4. The compiler might be generating the wrong instructions. I've seen this on a few rare occasions.

    5. Another program in the system might be interfering with our program. This is quite common in some popular operating environments that allow several programs to be executing concurrently.

    And so on...

With simple programs like the ones we're writing here, errors such as the ones listed under problems with our code are more likely as we have relatively little interaction with the rest of the system. As we start to use more sophisticated mechanisms in C++, we're more likely to run into instances of interaction problems.

Why We Need to Initialize Variables Explicitly

After that excursion into the sources of program failure, let's get back to our question about initializing variables. Why do we have to worry about this at all? It would seem perfectly reasonable for the compiler to make sure that our variables were always initialized to some reasonable value; in the case of numeric variables such as a short, 0 would be a good choice. Surely Bjarne Stroustrup, the designer of C++, didn't overlook this.

No, he didn't; he made a conscious decision not to provide this facility. It's not due to cruelty or unconcern with the needs of programmers. On the contrary, he stated in the Preface to the first Edition of The C++ Programming Language that “C++ is a general-purpose programming language designed to make programming more enjoyable for the serious programmer”.[18] To allow C++ to replace C completely, he could not add features that would penalize efficiency for programmers who do not use these features. By the same reasoning that prevented the inclusion of index error checking in the vector data type, Bjarne decided not to add initialization as a built-in function of the language because it would make programs larger and slower if the programmer had already taken care of initializing all variables as needed. This may not be obvious, but we'll see in a later section why it is so.

[18] The C++ Programming Language, 3rd Edition. ix.

Here's Susan's reaction to these points about C++:

Susan: What is run-time efficiency?

Steve: How long it takes to run the program and how much memory it uses.

Susan: So are you saying that C++ is totally different from C? That one is not based on the other?

Steve: No, C++ is a descendant of C. However, C++ provides much more flexibility to programmers than C.

Susan: Now, about what Bjarne said back in 1986: Who enjoys this, and if C++ is intended for a serious programmer, why am I reading this book? What is a serious programmer? Would you not think a serious programmer should have at least taken Computer Programming 101?

Steve: This book has been used as a textbook for such a course. Anyway, if you want to learn how to program, you have to start somewhere, and it might as well be with the intention of being a serious programmer.

Preventing Improper Data Input

In the meantime, there's something else we should do if we want the program to work as it should. As the old saying “Garbage in, garbage out” suggests, by far the best solution to handling spurious input values is to prevent them from being entered in the first place. What we want to do is to check each input value and warn the user if it's invalid. Figure 4.17 illustrates a new input routine that looks like it might do the trick.

Figure 4.17. Garbage prevention, first attempt (from codevect2a.cc)
for (i = 0; i < 5; i ++)
  {
  cout << "Please type in weight #" << i+1 << ": ";
  cin >> Weight[i];
  if (Weight[i] <= 0)
						{
						cout << "I'm sorry, " << Weight[i] << " is not a valid weight.";
						cout << endl;
						}
  }

As usual, you can try this version out yourself. First, you have to compile the program vect2a by the usual method, then run the program, either normally or under the debugger. When you are asked for a weight, type one in and hit ENTER just as when executing normally. After you've entered 5 weights, the program will start the sorting process. When finished, it will display the top three weights of the five that were entered. Most of this should be familiar; the only line that has a new construct in it is the if statement. The condition <= means “less than or equal to”, which is reasonably intuitive.

Unfortunately, this program won't really solve the problem of bad input. The problem is what happens after the error message is displayed; namely, the loop continues at the top with the next weight, and we never correct the erroneous input. Susan didn't have much trouble figuring out exactly what that last statement meant:

Susan: When you say that “we never correct the erroneous input”, does that mean that it is added to the list and not ignored?

Steve: Right.

To fix this problem completely, we need to use an approach similar to the one shown in the final version of this program (Figure 4.18). To try this version out yourself, you have to compile the program vect2a by the usual method, then run the program, either normally or under the debugger. When you are asked for a weight, type one in and hit ENTER. After you've entered five weights, the program will start the sorting process, and will display the results when finished.

Figure 4.18. Finding the top three weights using Vecs (codevect3.cc)
#include <iostream>
#include "Vec.h"
using namespace std;

int main()
{
   Vec<short> Weight(5);
   Vec<short> SortedWeight(3);
   short HighestWeight;
   short HighestIndex;
   short i;
   short k;

   cout << "I'm going to ask you to type in five weights, in pounds." << endl;

   for (i = 0; i < 5; )
    {
    cout << "Please type in weight #" << i+1 << ": ";
    cin >> Weight[i];
    if (Weight[i] <= 0)
      {
      cout << "I'm sorry, " << Weight[i] << " is not a valid weight.";
      cout << endl;
      }
     else
      i ++;
     }

   for (i = 0; i < 3; i ++)
      {
      HighestIndex = 0;
      HighestWeight = 0;
      for (k = 0; k < 5; k ++)
        {
        if (Weight[k] > HighestWeight)
           {
           HighestWeight = Weight[k];
           HighestIndex = k;
           }
        }
      SortedWeight[i] = HighestWeight;
      Weight[HighestIndex] = 0;
      }

    cout << "The highest weight was: " << SortedWeight[0] << endl;
    cout << "The second highest weight was: " << SortedWeight[1] << endl;
    cout << "The third highest weight was: " << SortedWeight[2] << endl;

    return 0;
}

Now let's look at the changes that we've made to the program from the last revision. The first change is that the for statement that controls the block where the input is accepted from the user has only two sections rather than three. As you may recall, the first section specifies the initial condition of the index variable; in this case, we're starting i out at 0, as is usual in C and C++. The second section indicates when we should continue executing the loop; here, we should continue as long as i is less than 5. But the third section, which usually indicates what to do to the index variable, is missing. The reason for this is that we're going to adjust the index variable manually in the loop, depending on what the user enters.

In this case, if the user enters an invalid value (i.e., less than or equal to 0), we display an error message and leave i as it was, so that the next time through the loop the value will go into the same element in the Weight Vec. When the user enters a valid value, the else clause increments i so that the next value will go into the next element in the Vec. This fixes the error in our previous version that left incorrect entries in the Vec.

After finishing with the pumpkin program, let's tune in on a discussion I had with Susan on how to create an algorithm in the first place.

Susan: Do they make instruction sheets with directions of paths to follow? How do you identify problems? I mean, don't you encounter pretty much the same types of problems frequently in programming and can they not be identified some way so that if you knew a certain problem could be categorized as a Type C problem, let's say, you would approach it with a Type C methodology to the solution? Does that make sense? Probably not.

Steve: It does make sense, and in fact that's what the standard library is designed to do for very commonly used algorithms and data structures. At another level, another book of mine, Optimizing C++ (ISBN 0-13-977430-0), is designed to provide something like you're suggesting for more specific, but still relatively common, problems at the algorithmic level. There's also a book called Design Patterns (ISBN 0-201-63361-2) that tries to provide tested solutions to common design problems, at a much more abstract level, and a new book called Modern C++ Design (ISBN 0-201-70431-5) that shows how to use advanced features of C++ to implement a number of the high-level design ideas from the Design Patterns book (among a lot of other very useful material).

Now that we have beaten the pumpkin weighing example to a pulp[19], let's review the mass of information to which I've subjected you so far in this chapter.

[19] Pumpkin pie, anyone?

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset