Show Lecture.IO as a slide show.
CS253 I/O
I/O Class Hierarchy
┌─────┐
│ 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 │
└──────────┘ └───────────────┘ └───────────────┘ └──────────┘
- What class defines
operator<<
?
- What class defines
operator>>
?
- What class defines
.open()
?
- What class defines
.get()
?
What Header Files Define What
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
- What’s a wchar_t? It’s a wide character.
- Despite its peculiar name, wchar_t is a fundamental type,
like char or int.
- Its purpose is to hold a wide character, like ⻥ or 🐟,
that doesn’t fit into a one-byte char.
- It’s usually identical to int, and so can hold a Unicode code
point, an integer 0…143,000+.
char c = 'X';
wchar_t wc = L'⻥';
cout << sizeof(c) << '\n'
<< sizeof(wc) << '\n';
1
4
basic_whatever<type>
- How would my students have implemented all this? 💖 💖 💖
- After learning about templates, however, they would implement
the templated class basic_ostream, which takes either
char or wchar_t as a template argument.
Keep it DRY!
- Same for ostream and string.
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
Similarly, there is unformatted input:
ifstream in("/etc/resolv.conf");
string s;
getline(in, s);
cout << "First: " << s << '\n';
char c;
while (in.get(c)) {
if (c == '.') c = '*';
cout << c;
}
First: search cs.colostate edu colostate.edu
nameserver 129*82*45*181
nameserver 129*82*103*78
nameserver 129*82*103*79
seek/tell
Diogenes
- An ostream has a put pointer, an integer value that keeps track
of how far along in the output we are.
Similarly, an istream has a get pointer.
- You can query & change these:
ofstream out("xyz");
out.write("Hxllo there\n", 11);
out.seekp(1);
out.put('e');
out.close();
cout << ifstream("xyz").rdbuf();
Hello there
- Surprisingly, an fstream
(ifstream/ofstream combination) has only a single shared
put/get pointer, and not one for input and one for output.
seek/tell methods
- tell ≡ ask a question about location
- seek ≡ change location
- g ≡ discuss the input (get) pointer
- p ≡ discuss the output (put) pointer
Misuse of .open()
ifstream and ofstream both inherited fstream::open():
ifstream in;
const string home = getpwnam("cs253")->pw_dir;
in.open(home+"/pub/ducks");
char c;
while (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");
char c;
while (in.get(c))
cout << c;
Huey (red)
Dewey (blue)
Louie (green)
Misuse of .eof()
- People who program by guesswork are often wrong about istream::eof().
- They think that it means “Will the next read fail?”.
- They are wrong. It means “Did the previous read fail?”.
ifstream in("/etc/resolv.conf");
string line;
while (!in.eof()) {
getline(in, line);
cout << line << '\n';
}
search cs.colostate edu colostate.edu
nameserver 129.82.45.181
nameserver 129.82.103.78
nameserver 129.82.103.79
Where did that extra line come from?
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/resolv.conf");
string line;
while (getline(in, line))
cout << line << '\n';
search cs.colostate edu colostate.edu
nameserver 129.82.45.181
nameserver 129.82.103.78
nameserver 129.82.103.79
Or, with fewer source lines and a reduced scope for line
:
ifstream in("/etc/resolv.conf");
for (string line; getline(in, line); )
cout << line << '\n';
search cs.colostate edu colostate.edu
nameserver 129.82.45.181
nameserver 129.82.103.78
nameserver 129.82.103.79