Input/Output Streams

Introduction:

Brief Review on Objects: Streams: I/O Hierarchy:

Class ios_base

namespace std
{
  class ios_base 
  {
  public:
    // ios_base status methods
    // these read and/or manipulate the status bits
    bool  fail () const; // true iff bad or fail state 
    bool  eof  () const; // true iff stream is at end of file
    ...
    // ios_base binding methods
    ostream*  tie (ostream*);   // ties current stream to specified ostream
    ...
    // ios_base formatting methods
    format_flags setf (format_flags flags);
    ...
    // ios_base data methods
    int  width(int val);
    char fill (char fillch);
    ...
    // ios_base enumerated bitmask types
    enum iostate     { ... }; // 4 io states, representing good, eof, bad, fail
    enum formatflags { ... }; // 15 format flags, such as left, showpoint, hex
    enum openmode    { ... }; // 6 file open modes, such as in, out, binary
    enum seekdir     { ... }; // 3 file seek modes: beg, cur, end

  protected:
    unsigned long state;          // stores status bits
    unsigned long flags;          // stores flag bits
    unsigned long mode;           // stores mode bits
    int           widthvalue,     // initialized to 0
                  precisionvalue; // initialized to 0
    char          fillcharacter;  // initialized to ' '
    streambuff*   streambuffer;   // pointer to a streambuff object

    // plus other data, such as specifying tied streams
  }  ;  // end pseudo-definition of class ios_base
} // namespaced std

Class istream

namespace std
{
  class istream : public class ios_base
  {
    // overloads of input operator
    friend istream& operator >> (istream& , char);
    friend istream& operator >> (istream& , int);
    friend istream& operator >> (istream& , long);
    friend istream& operator >> (istream& , unsigned char);
    friend istream& operator >> (istream& , unsigned int);
    friend istream& operator >> (istream& , unsigned long);
    friend istream& operator >> (istream& , float);
    friend istream& operator >> (istream& , double);
    friend istream& operator >> (istream& , long double);
    friend istream& operator >> (istream& , char* );
    ...
    public:
      // methods to access next element in stream
      char get ();  
      void get (char&);
      char peek ();
      ...
  } cin;  // predefined object
} // namespace std

Standard I/O Devices

Utilizing Input/Output:


cin and cout

Using cin and cout:


cin and Extraction Operator ( >> )

Syntax of input statement using cin and extraction operator ( >> ):


Standard Input

Using Standard Input:


Data Type of Input

Extraction Operator ( >> ) distinguishes between character 2 and number 2 by right hand operand:


Reading Data

Reading data into a char variable:

Reading data into int or double variable: Examples:
int a, b;
double z;
char ch;

Statement		Input		Value Stored in Memory
1 cin >> ch;		A		ch = 'A'
2 cin >> ch;		AB		ch = 'A', 'B' held for later input
3 cin >> a;		48		a = 48
4 cin >> a;		46.35		a = 46, .35 held for later input
5 cin >> z;		74.35		z = 74.35
***Reading Data Recommendations:

While capturing entire lines of data, that is, "line oriented" input may seem easy, it can lead to read errors as well. In particular, the getline() function. Problems can be encountered when trying to read entire lines of data.

A facile solution can be found by using the extraction operator (>>) for input. The extraction operator (>>) always retrieves the next "token" from the input stream.

A token is the smallest element of a C++ program that is meaningful to the compiler. The following tokens are recognized by the C++ parser: Tokens are usually separated by "white space." White space can be one or more: Here are two examples:
int n;

char str [max];

 /*
The following code skips white space (including end of line) to next
visible char, then reads characters as long as they can be made into
an integer (optional +/- followed by digits), then builds an int from
this and puts the value into n
*/

std::cin >> n;

 /*
The following code skips white space to next visible char, then reads
characters up to the next white space char, then builds a string from
this input and puts the value into str
*/

std::cin >> str; 
Note that in all cases, end of lines are skipped over just as if they were tabs or blanks. Blank lines in the input have essentially no affect on the way the extraction operator >> reads the next token.
int n;
while (std::cin >> n)
{
  // do whatever appropriate with n, which is ensured to be of type int
}
// after all ints are read, execution picks up here
This will read ints no matter how input is formatted with blanks, tabs, and newlines. If you replaced the type "int" with "string" it will read strings in the same way, ignoring tabs, blanks, and newlines.

A final point is that the type read by the extraction operator >> can be changed at programmer convenience. For example, if input is expected to alternate between int and string, the following loop could be used:
int n;
while (std::cin >> n >> str) // read an integer and then a string
{
  // do whatever appropriate with n and str
}
// after all integer, string pairs are read, execution picks up here
Again, these reads totally ignore (by skipping over) all white space in the input.


Input Failure

Input Failure Issues:


Predefined Functions

Using Predefined Functions (see Ch 6):

Predefined Function Example: Basic Example Code for cin and member functions Using cin and get() Function: Using cin and ignore() Function: Using putback() and peek() Functions: Using Dot Notation:

Standard Output - Member Functions and Flags

Output streams (class ostream and related classes) have some useful member functions for controlling output formatting.
Here are a few:



Standard Output - Stream Manipulators

Using and Formatting Standard Output:

Types of Manipulators: Using endl manipulator: Using precision and decimal points: Using setw manipulator: Using flush manipulator: Additional Output Formatting:

Common Stream Flags and Manipulators

Here is a table of common stream flags and corresponding stream manipulators (non-parameterized, and all from namespace std).
 

Flag Name Corresponding
Stream Manipulator
Description
ios::fixed fixed if this is set, floating point numbers are printed in fixed-point notation. When this flag is set, ios::scientific is automatically unset
ios::scientific scientific if this is set, floating point numbers are printed in scientific (exponential) notation. When this flag is set, ios::fixed is automatically unset
ios::showpoint showpoint if this is set, the decimal point is always shown, even if there is no precision after the decimal. Can be unset with the manipulator noshowpoint
ios::showpos showpos if set, positive values will be preceded by a plus sign + . Can be unset with the manipulator noshowpos.
ios::right right if this is set, output items will be right-justified within the field (when using width() or setw()), and the unused spaces filled with the fill character (the space, by default).
ios::left left if this is set, output items will be left-justified within the field (when using width() or setw()), and the unused spaces filled with the fill character (the space, by default).
ios::showbase showbase Specifies that the base of an integer be indicated on the output. Decimal numbers have no prefix. Octal numbers (base 8) are prefixed with a leading 0. Hexadecimal numbers (base 16) are prefixed with a leading 0x. This setting can be reset with the manipulator noshowbase.
ios::uppercase uppercase specifies that the letters in hex outputs (a-f) and the letter 'e' in scientific notation will be output in uppercase. This can be reset with the manipulator nouppercase.


Here is table showing more of the common manipulators. All are in namespace std.
 
Manipulator Description
flush causes the output buffer to be flushed to the output device before processing proceeds
endl prints a newline and flushes the output buffer
dec causes integers to be printed in decimal (base 10)
oct causes integers from this point to be printed in octal (base 8)
hex causes integers from this point to be printed in hexadecimal (base 16)
setbase() a parameterized manipulator that takes either 10, 8, or 16 as a parameter, and causes integers to be printed in that base. setbase(16) would do the same thing as hex, for example
internal if this is set, a number's sign will be left-justified and the number's magnitude will be right-justified in a field (and the fill character pads the space in between). Only one of right, left, and internal can be set at a time.
boolalpha causes values of type bool to be displayed as words (true or false)
noboolalpha causes values of type bool to be displayed as the integer values 0 (for false) or 1 (for true)

Output considerations: aligning and formatting

Be careful when coding and viewing displays on any one particular platform. For instance, the specific behavior of tabs (\t) vary among devices. That is, the tab character may position output by four characters, six, eight, none, or some other variation. So, the primary concern of using tab (\t) characters is that their output appearance is not portable.

Instead, you may want to include setfill(), along with setw(), which will cause subsequent output controlled by setw() to pad unused character positions encompassed by the field width. The fill character is used in output insertion operations to fill spaces when results have to be padded to the field width.

So, if you wanted to begin output at a given column and display values (using a tab, other character, or a specific number of spaces), :
cout << "12345678901234567890" << endl;
cout << fixed << showpoint << setprecision(2);
cout << setfill (' ') << setw (10) << 1.234 << '\n';
Displays...
12345678901234567890
      1.23
Lastly, the effects of stream manipulators remain as previously set, until specifically changed--with one exception: setw(), which is automatically reset to setw(0) after each insertion. Example...
/*
This program demos formatting output using setw(), setfill(), fixed, showpoint,
and setprecision()
 written by Mark K. Jowett, Ph.D.
10:46 PM 6/16/9
*/

#include <iostream>
using std::cout; //standard output
using std::cin; //standard input
using std::endl; //end line
using std::right; //right-justified
using std::left; //left-justified

#include <iomanip>
using std::fixed; //write floating point values in fixed-point notation.
using std::scientific; //write floating point values in scientific notation.
using std::showpoint; //decimal point always written for floating point values
using std::setprecision; //sets decimal precision used by output 
using std::setfill; //Sets fill character to value of parameter. 
using std::setw; //Sets number of characters to be used as the field width for
the next insertion operation.

int main()
{
    int a = 19;
    int b = 345;
    double c = 76.384;

    cout << "Demo fixed, showpoint, setprecision(), setw()...\n";

    cout << fixed << showpoint;
    cout << "12345678901234567890" << endl;

    cout << setw(5) << a << endl;
    cout << setw(5) << b << setw(5) << "Hi"
         << setw(5) << a << endl << endl;
	 
    cout << setprecision(2);
    cout << setw(6) << b << setw(6) << c
         << setw(6) << a << endl;
    cout << setw(6) << a << setw(6) << b
         << setw(6) << c << endl << endl;

    cout << setw(5) << b << a << endl;
    cout << setw(2) << b << setw(4) << a << endl;

    cout << "\nDemo setfill(), setw()...\n";
    int i = 20;
    int j = 5678;

    cout << "12345678901234567890" << endl;
    cout << setw(5) << i << setw(7) << j
         << setw(8) << "Test" << endl;

    cout << setfill('*');
    cout << setw(5) << i << setw(7) << j
         << setw(8) << "Test" << endl;

    cout << setw(5) << i << setw(7) << setfill('#')
         << j << setw(8) << "Test" << endl;

    cout << setw(5) << setfill('@') << i
         << setw(7) << setfill('#') << j
         << setw(8) << setfill('^') << "Test" << endl;

    cout << setfill(' ');
    cout << setw(5) << i << setw(7) << j
         << setw(8) << "Test" << endl;

    cout << "\nDemo setfill(), setw(), left-justified...\n";
    int x = 20;
    int y = 5678;
  
    cout << left;

    cout << "12345678901234567890" << endl;
    cout << setw(5) << x << setw(7) << y
         << setw(8) << "Test" << endl;

    cout << setfill('*');
    cout << setw(5) << x << setw(7) << y
         << setw(8) << "Test" << endl;

    cout << setw(5) << x << setw(7) << setfill('#')
         << y << setw(8) << "Test" << endl;

    cout << setw(5) << setfill('@') << x
         << setw(7) << setfill('#') << y
         << setw(8) << setfill('^') << "Test" << endl;

    cout << setfill(' ');
    cout << setw(5) << x << setw(7) << y
         << setw(8) << "Test" << endl;

    cout << "\nDemo setfill(), setw(), right-justified...\n";
    cout << right;

    cout << "12345678901234567890" << endl;
    cout << setw(5) << x << setw(7) << y
         << setw(8) << "Test" << endl;

    cout << setfill('*');
    cout << setw(5) << x << setw(7) << y
         << setw(8) << "Test" << endl;

    cout << setw(5) << x << setw(7) << setfill('#')
         << y << setw(8) << "Test" << endl;

    cout << setw(5) << setfill('@') << x
         << setw(7) << setfill('#') << y
         << setw(8) << setfill('^') << "Test" << endl;

    cout << setfill(' ');
    cout << setw(5) << x << setw(7) << y
         << setw(8) << "Test" << endl;

    cout << "\nDemo aligning numbers setfill(), setw(), right-justified...\n";
    double z = 1234.5678;

    cout << "12345678901234567890" << endl;
    cout << right;
    cout << setprecision(2);
    cout << setfill ('-') << setw (10) << 1.234 << '\n';

    cout << setprecision(2);
    cout << setfill ('-') << setw (10) << z << endl;

    cout << setprecision(3);
    cout << setfill ('-') << setw (10) << z << endl;

    cout << setprecision(4);
    cout << setfill ('-') << setw (10) << z << endl;

    cout << "\nDemo aligning numbers setfill(), setw(), left-justified...\n";
    cout << left;
    cout << setprecision(2);
    cout << setfill ('-') << setw (10) << 1.234 << '\n';

    cout << setprecision(2);
    cout << setfill ('-') << setw (10) << z << endl;

    cout << setprecision(3);
    cout << setfill ('-') << setw (10) << z << endl;

    cout << setprecision(4);
    cout << setfill ('-') << setw (10) << z << endl;

    cout << "Press Enter key to exit...";
    cin.get(); // make DOS window stay open

    return 0;
}
Displays...
Demo fixed, showpoint, setprecision(), setw()...
12345678901234567890
   19
  345   Hi   19

   345 76.38    19
    19   345 76.38

  34519
345  19

Demo setfill(), setw()...
12345678901234567890
   20   5678    Test
***20***5678****Test
***20###5678####Test
@@@20###5678^^^^Test
   20   5678    Test

Demo setfill(), setw(), left-justified...
12345678901234567890
20   5678   Test
20***5678***Test****
20***5678###Test####
20@@@5678###Test^^^^
20   5678   Test

Demo setfill(), setw(), right-justified...
12345678901234567890
   20   5678    Test
***20***5678****Test
***20###5678####Test
@@@20###5678^^^^Test
   20   5678    Test

Demo aligning numbers setfill(), setw(), right-justified...
12345678901234567890
------1.23
---1234.57
--1234.568
-1234.5678

Demo aligning numbers setfill(), setw(), left-justified...
1.23------
1234.57---
1234.568--
1234.5678-
Press Enter key to exit...