Commentary: Input/Output (IO)

Steven Zeil

Last modified: Aug 18, 2020
Contents:

Input and output are the process of moving information into and out of a program.

Read chapter 3, Input/Output, of Malik, if you have not already done so. (If you are working from a different C++ textbook, you will have to figure out the corresponding chapters.)

1 A Model of I/O

I/O is one of the least standardized components of modern programming languages. It seems to be one the hardest things to get “right” when designing programming languages.

In many early programming languages, the input and output statements were “fundamental” statement types, like assignment or loops, built into the syntax of the language. Later languages tended to treat input and output as an offshoot of the language’s standard library of pre-written functions.

If you are a Python programmer.

But even then, there was considerable variation on how those libraries were designed. Designers would try to find a few unifying ideas to base their libraries upon, only to find it difficult to apply them uniformly.

If you are a Java programmer

Designers would try to find a few unifying ideas to base their libraries upon, only to find it difficult to apply them uniformly.

If you are a Java programmer

C++ bases its I/O model on the >> and << operators. These take the form:

input-stream >> variable-to-read-into

and

output-stream << variable-to-be-written

(If you think of the >> and << as arrows, the indicate the direction in which the data is “moving” during the I/O operation.)

This is a very flexible model, because

  1. On the left, we can have all manner of different I/O devices or destinations. We could have the standard streams cin and cout, or a file, or a network connection, or …

  2. On the right, we can have almost any data type. For the simple data types predefined in the C++ language, the I/O operators are already defined. And C++ allows (encourages) programmers who invent their own data types to create their own code for use when applyng << and >> on those types.

If you are a C programmer

2 Standard Input and Output

Almost all modern programming languages recognize the notion of a “standard input” that, by default, reads from the keyboard, and a “standard output” that, by default, writes to the screen.

In C++, these are cin and cout.

If you are a Java programmer
If you are a Python programmer

Actually, your program will not know whether standard input and output are the keyboard and screen. Instead, the operating system allows you program to contact the I/O streams that it considers to be standard input and standard output, but you can change or redirect them when you launch your program by telling the operating system to redirect the input and/or output of your program to files or even other programs.

3 Input operators vs. input functions

Suppose that I want to read in a pair of integers into variables named k and m, and that the actual input coming up from the keyboard/file/whatever looks like

21      42

I can do that with the code

int k, m;
input >> k >> m;

This would put the value 21 into k and 42 into m. But notice that something interesting happens between the input of the two integers – we skipped over a number of blanks between the ‘1’ at the end of the first number and the ‘4’ at the beginning of the next number.

By convention, >> always starts by skipping over any whitespace characters starting from the position where we last ended reading. The “actual” input is processed starting at the first non-whitespace character that is located.

What if we really wanted to track all of that whitespace? For example, if I were writing a program to run a maze like this:

xxxx xxxxxxxxxxxx
x  x x    x     x
x  x    xxxxxxx x
xx xxxxxx     x x
xx x      xxx   x
xx x xxxxxx xxxxx
xx x x   x   x  x
x               x
xxxx xxxxxxxxxxxx

then trying to read this in on character at a time, using >> would be an utter failure. Each time my code executed

char c;
cin >> c;

I would always get an ‘x’, because >> skips over all blanks and line breaks. My poor maze would have degenerated to:

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

That’s a big reason why the C++ <iostream> library includes the more primitive functions like get() – those functions give you the next character, no matter what it is, even if it is some kind of whitespace.