CS253: Software Development with C++

Fall 2022

Input/Output

Show Lecture.IO as a slide show.

CS253 I/O

Inclusion

For general I/O, you need to:

    
#include <iostream>

Use of fstream, ifstream, or ofstream requires:

    
#include <fstream>

Use of stringstream, istringstream, or ostringstream requires:

    
#include <sstream>

Use of I/O manipulators requires:

    
#include <iomanip>

I/O Class Hierarchy

I/O Class Hierarchy

or, if you prefer a diagram:

                                    ┌─────┐
                                    │ ios │
                                    └─────┘
                                       △
                      ┌────────────────┴────────────────┐
                 ┌────┴────┐                       ┌────┴────┐
                 │ istream │                       │ ostream │
                 └─────────┘                       └─────────┘
                      △                                 △
               ┌──────┴───────┐                  ┌──────┴───────┐
         ┌─────┴────┐ ┌───────┴───────┐  ┌───────┴───────┐ ┌────┴─────┐
         │ ifstream │ │ istringstream │  │ ostringstream │ │ ofstream │
         └──────────┘ └───────────────┘  └───────────────┘ └──────────┘

The △ indicates inheritance.

More

                           ┌─────┐
                           │ ios │
                           └─────┘
                              △
             ┌────────────────┴────────────────┐
        ┌────┴────┐                       ┌────┴────┐
        │ istream │                       │ ostream │
        └─────────┘                       └─────────┘
             △                                 △
      ┌──────┴───────┐                  ┌──────┴───────┐
┌─────┴────┐ ┌───────┴───────┐  ┌───────┴───────┐ ┌────┴─────┐
│ ifstream │ │ istringstream │  │ ostringstream │ │ ofstream │
└──────────┘ └───────────────┘  └───────────────┘ └──────────┘

Methods & Operator Overloading

                           ┌─────┐
                           │ ios │
                           └─────┘
                              △
             ┌────────────────┴────────────────┐
        ┌────┴────┐                       ┌────┴────┐
        │ istream │                       │ ostream │
        └─────────┘                       └─────────┘
             △                                 △
      ┌──────┴───────┐                  ┌──────┴───────┐
┌─────┴────┐ ┌───────┴───────┐  ┌───────┴───────┐ ┌────┴─────┐
│ ifstream │ │ istringstream │  │ ostringstream │ │ ofstream │
└──────────┘ └───────────────┘  └───────────────┘ └──────────┘
Who defines operator<<?

class ostream. Putting it in both ostringstream and ofstream wouldn’t be DRY, and putting it in ios would let cin << 42 compile.

Who defines operator>>?

class istream

Who defines .get()?

class istream

Who defines .open()?

Trick question: class fstream

Multiple Inheritance

                           ┌─────┐
                           │ ios │
                           └─────┘
                              △
             ┌────────────────┴────────────────┐
        ┌────┴────┐                       ┌────┴────┐
        │ istream │                       │ ostream │
        └─────────┘                       └─────────┘
             △                                 △
      ┌──────┴───────┐                  ┌──────┴───────┐
┌─────┴────┐ ┌───────┴───────┐  ┌───────┴───────┐ ┌────┴─────┐
│ ifstream │ │ istringstream │  │ ostringstream │ │ ofstream │
└──────────┘ └───────────────┘  └───────────────┘ └──────────┘

        ┌─────────┐                   ┌──────────────┐
        │ fstream │                   │ stringstream │
        └─────────┘                   └──────────────┘
             △                               △
      ┌──────┴───────┐             ┌─────────┴────────┐
┌─────┴────┐ ┌───────┴──┐  ┌───────┴───────┐  ┌───────┴───────┐
│ ifstream │ │ ofstream │  │ istringstream │  │ ostringstream │
└──────────┘ └──────────┘  └───────────────┘  └───────────────┘

What Header Files Define What

<sstream> <fstream> <iostream> <iomanip>
objects manipulators

istringstream ostringstream stringstream

ifstream ofstream fstream

cin cout cerr clog

These don’t take an argument:

boolalpha noboolalpha showbase noshowbase showpoint noshowpoint showpos noshowpos skipws noskipws uppercase nouppercase left right internal dec hex oct fixed scientific

These do take an argument

resetiosflags setiosflags setbase setfill setprecision setw (non-sticky)

strange type?

Consider the error message from this bad code:

cout.zork();  // 🦡
c.cc:1: error: ‘std::ostream’ {aka ‘class std::basic_ostream<char>’} 
   has no member named ‘zork’

basic_ostream

Why!?

w-streams

wchar_t

char c = 'X';
wchar_t wc = L'⻥';
cout << sizeof(c) << '\n'
     << sizeof(wc) << '\n';
1
4

basic_whatever<type>

Unformatted output

We’re familiar with formatted I/O using << or >>:

cout << "π ≈ " << 355/113.0 << endl;
π ≈ 3.14159

There’s also unformatted output:

cout.put('h');
cout.put('i');
char data[] = " there\nextra";
cout.write(data, 7);
hi there

Unformatted input

With unformatted input, you can read an arbitrary number of bytes:

ifstream in("/etc/resolv.conf");
char buf[80];
in.read(buf, size(buf));
cout << "⊢";
cout.write(buf, in.gcount());
cout << "⊣";
⊢search cs.colostate edu colostate.edu
nameserver 129.82.45.181
nameserver 129.82⊣

istream::read() reads into a char buffer, which is not '\0' terminated.

char-based unformatted input

ifstream in("/etc/resolv.conf");
char c;
c = in.peek(); cout << "First: " << c << "\n";
c = in.get(); cout << "Again: " << c << "\n";
in.unget();
c = in.get(); cout << "Again: " << c << "\n";
c = in.get(); cout << "Second: " << c << "\n";
in.ignore(10000, '9');
while (in.get(c)) cout.put(c);
First: s
Again: s
Again: s
Second: e
.82.45.181
nameserver 129.82.103.78
nameserver 129.82.103.79

seek/tell


Diogenes

Only one

seek/tell methods


Misuse of .open()

ifstream and ofstream both inherited fstream::open():

const string home = getpwnam("cs253")->pw_dir;
ifstream in;
in.open(home+"/pub/ducks");  // 🦡
for (char c; in.get(c); )
    cout << c;
Huey (red)
Dewey (blue)
Louie (green)

Why have that extra step? Just associate the filename at object construction:

const string home = getpwnam("cs253")->pw_dir;
ifstream in(home+"/pub/ducks");
for (char c; in.get(c); )
    cout << c;
Huey (red)
Dewey (blue)
Louie (green)

Misuse of .eof()

ifstream in("/etc/hostname");
string line;
while (!in.eof()) {  // 🦡 BAD!
    getline(in, line);
    cout << "Data: " << line << '\n';
}
Data: beethoven
Data: 
Where did that extra line come from?

It came from the second, failed, call to getline(). Nobody noticed the failure until the third call to .eof().

The right way to detect end-of-file

Don’t inquire in advance—just go ahead and read. It will succeed or fail:

ifstream in("/etc/hostname");
string line;
while (getline(in, line))
    cout << line << '\n';
beethoven

Or, with fewer source lines and a reduced scope for line:

ifstream in("/etc/hostname");
for (string line; getline(in, line); )
    cout << line << '\n';
beethoven