C++ I/O

Input/Output in C++

C++ has a very simple system for I/O.

Here are some examples:

std::cin >> thing1 >> thing2;    // read thing1 then thing2 from cin, standard input stream
std::cout << thing1 << thing2;   // write thing1 then thing2 to cout, standard output stream (no spaces included)
std::cout << '\n' << std::endl;  // output newline, newline and flush buffer
std::cin.get(ch);                // read one character

// equivalent form if appropriate using declarations were given:

cin >> thing1 >> thing2;
cout << thing1 << thing2;
cout << '\n' << endl;
cin.get(ch);

Files in C++

Stream Classes

Inheritance is used for different file access modalities, where ‘f’ streams are for files (ifstream, ofstream, fstream). C++ also enables using IO operations to read from or write to *stringstreams, using strings instead of files.

                              ios
                            /     \
                    istream         ostream
            /----/     /     \    /     \     \----\
istringstream     ifstream  iostream  ofstream    ostringstream
                                /    \
                          fstream    stringstream

Using File Streams

Open mode flags for files are in the same sprit as C:

Flags can be combined (via logical or, |, not via the strings "bw+" of C). Example:

#include <iostream>
#include <fstream> // file stream library
int main(void) {
    // open for read only
    // ios::in optional here, class ifstream makes it implicit
    std::ifstream ifile("files.txt", std::ios::in);

    // open for write, append to end
    // ios::out optional here, ofstream makes it implicit
    std::ofstream ofile("out.txt", std::ios::out | std::ios::app);
    char ch;
    int num;
    do {
        ifile.get(ch);
        ifile >> num;        // same I/O << and >> syntax as for std::cin/cout/cerr
        ofile << ch << " " << num;
    } while (!ifile.eof());
    ifile.close();
    ofile.close();
    return 0;
}

Random access (block I/O) files are treated the same as in C. Member functions, manipulators & operators for iostreams (see below) can be used with iofstreams for sequential files also, not random access files.

stringstream

This is a string buffer that contains a sequence of characters, similar to a file stream.

#include <string>
#include <iostream>
#include <sstream>
int main() { 
  std::stringstream ss;
  ss << "Hello" << ' ' << 35 << " world";
  std::string word1, word2;
  int num;
  ss >> word1 >> num >> word2;
  std::cout << word1 << ", " << word2 << '!' << std::endl;
  std::cerr << ss.str() << std::endl;
  return 0;
}

Formatted output in C++

Several methods for adding formatting to I/O

#include <iostream>
#include <iomanip>   // I/O manipulators library
using std::cin; using std::cout;
using std::setw; using std::endl;
using std::setfill; using std::setprecision;
using std::fixed; using std::showpoint;

int main()
{
    // inline manipulators examples from iomanip library
    
    // setw(#) to set field width
    cout << setw(8) << 100/29 << endl; // right justify in 8 char field
    cout << setw(6) << "jo" << endl; // right justify in 6 field width

    // setfill to change fill character
    setfill('*');
    cout << setfill('*') << setw(5) << "jo" << endl; // fill with * not ' '
    //  setfill is persistent, remains until reset or changed
    cout << setfill(' ') ;           // sets fill back to space

    // setprecision/fixed/showpoint to change numerical formatting
    cout << setprecision(3) << 100/29 << endl;    // <=3 digits after decimal
    cout << fixed;        // forces fixed precision # of digits
    cout << showpoint;    // force decimal when precision=0
    cout << 10.2344 << endl;
    
    // alternative to above: use I/O member function flags
    // flags determine how output is displayed
    // changes are persistent
    cout.setf(std::ios::fixed); // set fixed flag
    cout.setf(std::ios::showpoint);
    cout.precision(3);    // 3 digits after decimal point
    cout << 12.3 << endl;
    cout.unsetf(std::ios::fixed);

    // to save fill flag before changing and restore:
    char oldfill = cout.fill('*');
    cout << setw(4) << "jo" << endl; // **jo
    cout.fill(oldfill);
    cout << setw(4) << "jo" << endl; //   jo
} 

[See also operator overloading notes (to be added).]