cs1ch11sec3.htm
 CHAPTER 11

INPUT/OUTPUT
A MORE DETAILED LOOK
 


Section III: Basic Output Using Instances of the Class ostream Section I: The C++ Perspective on Input and Output Section II: Basic Input Using Instances of the Class istream 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!



A. The '<<' Operator
There is little new to say about '<<' by itself. We can, however, extend its power through the use of various special characters, manipulators, and member functions. You have already learned the use of the '\n' special character. Another useful one is '\t' that allows you to tab over in your output. For example, if you wanted to create nice column headings you might write the following code:

cout << "Column 1\t Column 2\t Column 3\t Column 4";

This will cause the output after each '\t' to begin at the next tab stop. Check your manual to see how tab stops are set in the environment your program will run in.

Sometimes we want the output to include characters that have special meaning in C++ output. For example, one might want to output double quotes ("). Since this symbol means the end of a string in C++, one cannot use it without special care in an output expression. To tell C++ that such a symbol is not to be understood in its C++ sense, one puts a backslash character in front of the symbol. Thus one could output 'He said, "Hello"' (with the quotes as part of the output) this way:

cout << "He said, \"Hello\"";

The quote symbols preceded by back slashes become part of the output. (The back slashes are not part of the output.)

There is a third, "kinda fun" special character you might want to play with. This is the '\a' character that causes the computer to "ring its bell". You might want to use this if a user types in an incorrect value so they will look up and read the error message you also display. (The system just 'dinged' when one of the authors tried to arrow past the last word in this file.)

B. Various Manipulators to Improve the Quality of Your Output
Suppose you want to output some set of information about the people in a database. For example, suppose you want to output the name, telephone number, age, and height (in feet) of the individuals in the database. One nice way to do this would be to create a typical table with labeled columns for each property and the property values themselves in the appropriate column. One might consider using tabs to line up the columns, but it turns out that tabs are not flexible enough and are somewhat system dependent. The 'setw' manipulator works better. Consider the following code fragment. (Remember that, to use 'setw', one must include the header file "iomanip.h"):

    
    cout << endl;   // to make sure a new line is started
    
    cout << setw(30) << "Name"       << setw(16) << "Phone Number"
         << setw(6)  << "Age"        << setw(10) << "Height" << endl;
    
    cout << setw(30) << "Curtis"     << setw(16) << "505-454-3302"
         << setw(6)  << 6            << setw(10) <<  5.75 << endl;
    
    cout << setw(30) << "Fred Smith" << setw(16) << "505-454-3302"
         << setw(6)  << 102          << setw(10) << 5.128 << endl;
    
     

In a real program, the code would not include string and numeric constants for property values, as this code does, but would use variables instead. However, the use of constants here makes it easier to study the results.

As coded, the output would be:

                           Name     Phone Number    Age      Height
                         Curtis     505-454-3302      6        5.75
                     Fred Smith     505-454-3302    102       5.128
    

We see that 'setw' provided good spacing and forced the data in the columns to line up relatively nicely. You might quarrel with the specific spacing values chosen, but if you don't like the ones used here, it is simple to change them. What 'setw' does, when used with output, is block (or set aside) as many characters as are in the setw parameter and put the next output in that block. Thus, the string "Name" and the specific names are put into a block of 30 characters, the telephone number is put into a block of 16, age in to a block of 6, and height into a block of 10.

You may have noticed one problem - we humans like our numbers right justified but our strings left justified. In other words, we would prefer that the names all start in the same column. As written, the code will not allow this because, by default, the output is right justified within each block. In other words, the output is, by default, placed at the right end of the blocks.

We talked about inheritance earlier in this chapter. Many of the properties of streams are declared in the base class, 'ios', of the stream inheritance structure. Whether output is left or right justified, is indicated by which of two one bit flags (ios::left and ios::right) is set. (Note that only one can be set at a time.)

To set these flags, you use the 'setiosflags' manipulator, which is declared in the header file iomanip.h along with 'setw'. Thus, to left justify everything, we could preface the lines above with the following code:

cout << setiosflags(ios::left);

Of course, since everything is left justified now, the output would look as follows:

    Name                      Phone Number    Age      Height
    Curtis                    505-454-3302    6        5.75
    Fred Smith                505-454-3302    102      5.128
    

Now the names look right but we might not be satisfied with the justification of the numbers. Note that unlike the setw manipulator, the setiosflags manipulator causes a more permanent change. That is because 'setiosflags' changes a specific property in the instance ('cout' in this case) while 'setw' does not. To make the output the way we want, we could write the code as follows:

    cout << endl;   // to make sure a new line is started
    cout << setw(30) << setiosflags(ios::left)  << "Name"       << setiosflags(ios::right)
         << setw(16) << "Phone Number"
         << setw(6)  << "Age" << setw(10)       << "Height"     << endl;
    cout << setw(30) <<  setiosflags(ios::left) << "Curtis"     << setiosflags(ios::right)
         << setw(16) << "505-454-3302"
         << setw(6)  << 6     << setw(10)       << 5.75         << endl;
    cout << setw(30) << setiosflags(ios::left)  << "Fred Smith" << setiosflags(ios::right)
         << setw(16) << "505-454-3302"
         << setw(6)  << 102   << setw(10)       << 5.128        << endl;
    
The only change is that 'setiosflags' is used to change the justification first to left and then back to right. The output is pretty much the way we would want it.
    Name                      Phone Number    Age      Height
    Curtis                    505-454-3302      6        5.75
    Fred Smith                505-454-3302    102       5.128
    

You might be wondering about the use of the double colons (::) in the flag designation above. We saw this earlier in the definition of functions belonging to a specific class. For example, if we had a 'Person' class with a property 'age' and a member function 'ChangeAge', the first line of the function definition would be:

void Person::ChangeAge(int newAge);

The '::' operator indicates that 'ChangeAge' belongs to the class 'Person'. It would be possible to have a different function with the same name, 'ChangeAge', that belonged to a different class (perhaps an animal or building class). Likewise, the designation 'ios::left' indicates that 'left' in this case belongs to the class 'ios'. We can have a variable 'left' that belongs to a different class or to no class at all. To differentiate between the various 'left' variables, we use the '::' symbol. Note that we do not use this inside a class's member function definitions, because the default assumption is that we are referring to the data member names of an instance of that class.

There are any number of other manipulators and member functions that can be used to shape output. We will look at just one more. The 'Height' field in the output, as coded above, can have any number of digits to the right of the decimal point. Suppose, for whatever reason, that we only wanted two places to the right of the decimal point. We can accomplish this using two more properties of a stream. The first property is another 'flag' to indicate whether fixed or scientific notation is used for floating point numbers. (Scientific notation expresses floating point values using exponents while fixed notation is what we are most familiar with.)

The second property handles the total number of digits to be printed if neither ios::fixed or ios::scientific is chosen, or, if one of these is chosen, the number of digits to the right of the decimal point. Since we want two decimal points to the right of the decimal point and we want fixed notation, we add the lines:

    cout << setiosflags(ios::fixed);
    cout << setprecision(2);
to the beginning of the code above. The output will be
    Name                      Phone Number    Age      Height
    Curtis                    505-454-3302      6        5.75
    Fred Smith                505-454-3302    102        5.13
    

No, the 5.13 is not a misprint. In the process of removing the last digit, the '8', the system performs rounding on the value. Since '8' is greater than '5', the previous digit, the '2', is rounded up to a 3.

Topics Covered in the "Essentials of C++"

The Properties of 'ios' - including 'left' and 'right'
Stream Error Codes
The '::' operator
Width and Other Stream Data Members
Width and Other Stream Function Members
setw and Other Manipulators

Top of Section Main Menu Next Section