cs1ch11sec1.htm
 CHAPTER 11

INPUT/OUTPUT
A MORE DETAILED LOOK
 


Section I: The C++ Perspective on Input and Output Section II: Basic Input Using Instances of the Class istream Section III: Basic Output Using Instances of the Class ostream Section IV: File Handling
Section V : The Design and Analysis for a Contract Program Using Files Section VI: Modifying the Code for a Contract Program Using Files Section VII: Run Time Parameters - Passing Values to 'main'

  


Table of Contents

Learning C++:
An Index of Entry Points


2. The

of C++

A reference document on the basic elements of C++.



3. The Patterns



Index!



The C++ Perspective on Input and Output

A. Introduction
In this chapter we explore in more detail the tools and functionality provided with C++ to allow complex input and output. The contract program had some rather complex output screens, and it would be nice to make them as readable as possible. We have also observed that a truly useful version of the contract program would be capable of reading the contract 'database' from a file and writing that database back to a file. In this way one would not need to re-enter the data each time the program started. These are the kinds of issues dealt with here.

C++ provides a great detail of built-in input-output functionality and many commercial versions add their own features. Here, we will only explore some of the most basic of these features. The goal is not to provide you with a complete list of all the features and how to use them but to give you an overview, so that you have a sense of what is available and feel comfortable exploring additional features on your own. For more information, you should check out Section XIV of the "Essentials of C++" and the manual for your compiler. There are also a number of books that go into more detail with regard to I/O. One useful book is "Success with C++" by Kris Jamsa (chapters 1, 11, and 12). Another useful book is "Learning C++" by Neill Graham (chapter 8). Whatever you do, be sure to play with and explore the instructions and code you find. It is only by such play that you will truly master C++ input and output.

II. Streams
You have already been introduced to the idea of a stream - a sequence of symbols coming from some input device or going to some output device. Further, you have used 'cin' as an input stream and 'cout' as an output stream. As you know, these streams are declared and defined for you in the header file "iostream.h".

By default, 'cin' is the stream that provides a connection from the keyboard to your program, while 'cout' provides a connection from your program to the screen. Some operating systems and user interfaces allow you to redirect the default input and output. When you redirect input or output, you are simply changing the source or destination of a stream.

With Dos or Unix, for example, one can write:

program name << file.dat

to indicate that the file named "file.dat" will act as the input to some program. (Substitute an actual program name for "program name".) Likewise one can write:

program name >> file.dat

to indicate that the output from "program name" will be sent to the file "file.dat".

And, you can combine them together:

program name << file1.dat >> file2.dat

Note that the "<<" and ">>" Dos and Unix character sequences have in one sense exactly the opposite meanings that they have in C++. At the operating system level, "<<" indicates that the "information depository" that follows will be the input source of the program. At the same level, ">>" indicates that what follows will be the "information depository" for the output of the program. In C++, "<<" is used with output, while ">>" is used with input. Still, while the meanings may be opposite, the symbolism makes great sense at both levels. The only real difference is in the placement of the source and destination identifiers. In Dos and Unix, the source for an input is on the right and the destination (the program) is on the left. Thus, we use "<<" to indicate going from the source to the destination. In C++ the source (for example, cin) is on the left and the destination (the variable to hold the input) is on the right, so we use ">>". The same (but reversed) analysis applies for output.

The redirection described here only has limited uses. One cannot so easily redirect input and output in more complex user interfaces such as windows-based environments. In addition, redirection is an all or nothing proposition. Using "cin >> ....", for example, the input can only come from one stream. One can choose to have all the input come from a file or from the keyboard but, since "cin" is one stream with one beginning and end, one cannot have 'cin' represent two input sources. Likewise, with 'cout' one can choose to send the output to the screen or to a file but not both. In other words, using 'cout' alone, one cannot write the information about individual contracts to the screen and, in the same program, send the complete database of contracts to a file. We will learn later in this chapter how to have multiple input sources and multiple output destinations.

C. A More Complete Understanding of the Object-Oriented Paradigm
In turns out that the C++ input- output system is designed using the full complexity of the object oriented paradigm. To understand this system, we need to know more about this paradigm.

Back in Chapter 5 we introduced the object-oriented paradigm. In describing it, we focused almost exclusively on the notion of encapsulation. This notion is extremely important in understanding what object-oriented programming provides, but it is not, by itself, the essence of the paradigm. Indeed, other approaches also emphasize encapsulation. To be object-oriented, an approach needs two other features, inheritance and polymorphism. We will only briefly describe each of these here, but you should realize that you don't really know the object-oriented paradigm or C++ unless you understand and can use these effectively.

1. Inheritance
We know what inheritance means with humans. You probably inherit many of the features of your parents (and maybe you have already or someday will inherit their money). In the object-oriented approach, inheritance is a way of organizing the classes required in a program and taking advantage of any redundancy found among the classes. Often, different classes have almost the same structure and, if we can avoid constant repetition of declaration and definition code, we can avoid some work and errors.

Scientists also often use a similar approach in organizing those aspects of the world they are studying. Biologists, for example, create classification schemes for living beings, based on similarities. Using this approach, one can then say that all dogs are mammals and know, therefore, that all dogs have the common set of characteristics held by mammals. It then becomes unnecessary to repeat these characteristics in describing a specific species of dog. Later, if someone tells you that "Cyndal" is a Belgian Sheep Dog, you know that Cyndal is a mammal and that she, therefore, has (inherits) certain characteristics from the type mammal.

Consider a program that deals with many different kinds of contracts - office cleaning contracts, swimming pool contracts, athletic contracts, business executive contracts, and all the variations of each. There would be certain properties and responsibilities/behaviors common to all contracts, and it would be best if these properties and behaviors could be coded once for all contracts. Likewise, athletic and business executive contracts have common properties and behaviors that are not shared by office contracts. For example, there is no salary field in an office contract. We might consider a common contract class called 'employee' to represent the common features of athletic and business executive contracts. Likewise, swimming pool and office contracts might have common features, and we could group these under the class 'cleaning' contracts. Below is a simplistic drawing of how the inheritance structure might look:

DRAW Contract

Cleaning Employee

Office etc.
FIGURE 1

2. Polymorphism
The analysis and design of such inheritance structures is a course in itself and won't be discussed here. In a moment, however, we will see that such an inheritance structure is part of C++'s input - output system.

First, we need to discuss polymorphism. Don't let the word overwhelm you. Actually, you have already seen a hint of polymorphism. 'Poly' means 'many' and a 'morph' has traditionally meant form. (More recently it has taken on a somewhat new meaning as in graphics where 'to morph' is to change from one form to another. ) Used in conjunction with the object-oriented paradigm, polymorphism refers to the ability of a variable to refer to instances from different sub-classes in an inheritance structure and thereby respond differently to the same message. In other words, the variable can take on many forms. OK, OK, an example is needed.

Suppose we have a variable (call it 'theContract') that is capable of referring to a specific office contract or to a specific swimming pool, athletic or business executive contract. Suppose further, that each of these classes has a method called "CalculateCost" that calculates and returns the cost of the contract. Each of these methods would have different definitions, depending on how office vs swiming pool vs athletic vs business executive contract costs are calculated. It would be nice if the system could call the appropriate "CalculateCost" method depending on the type of contract stored in 'theContract'. That is what polymorphism makes possible.

Using polymorphism, when the variable 'theContract' is sent the 'CalculateCost' message, the system responds by executing the code corresponding to whatever type of contract 'theContract' holds at this moment. At one point in the program, 'theContract' may be holding an office contract, and the system will then execute the office contract version of 'CalculateCost'. Later, if 'theContract' holds an instance of the athletic contract class, the code corresponding to athletic contracts will be executed. This can become a powerful tool in programming. (It is often used, for example, in games programming to simplify the process of getting all the game elements to respond to a change in situation.)

3. Object-Based Input-Output
Input and Output can be greatly simplified if we implement their capabilities, using these three essential properties of the object-oriented paradigm - encapsulation, inheritance, and polymorphism. Consider the different types of streams we might have - general input streams (such as 'cin'); general output streams (such as 'cout'); streams for handling file input; and streams for handling file output. All these streams have some characteristics/behaviors in common so, just as we did for contracts, we might consider a common class (often called a base class) to represent all that is common. All the classes would inherit from this class. We might also conclude that file input streams have all the characteristics of general input streams but add more. Therefore, they would inherit from the general input class. Here is the inheritance structure for part of the input-output system.

DRAW
Figure 2

Although simplified, this is essentially how C++ has organized the input-output system. To begin with, the properties and behaviors common to all input and output are stored in the 'ios' class. For example, all streams have a property to record the 'error' state of the stream. Rather than have this property re-declared in all classes, it is declared once in 'ios' and inherited by all the other classes and their instances.

Topics Covered in the "Essentials of C++"

Inheritance and Polymorphism
Streams

Top of Section Main Menu Next Section