C++ I/O
Contents
Standard input and output
You can write to the standard output using code like this:
cout << x << y << endl;
(Note: this is like calling System.out.println in Java.)
The code is evaluated from left to right, so the value of x is written
first, then the value of y, then a newline.
Therefore, the code given above is equivalent to:
cout << x;
cout << y;
cout << endl;
Similarly, you can read from the standard input using code like this:
cin >> x >> y;
which is equivalent to:
cin >> x;
cin >> y;
(Again, the code is evaluated from left to right, so variable x will
be set to the first input value and variable y will be set to the
second input value.)
Note:
- Remember that you must #include <iostream> in order to
use cin, cout, or endl.
- To remember which is the input operator and which is the output
operator, think of the angle brackets as pointing in the direction
the values are flowing; for example, when you write the value of x
using "cout << x", the brackets point to cout (so the value
is going from x to cout).
When you read a value into x you use "cin >> x"; this time, the
brackets point to x (so the value is going from cin to x).
- Both the output operator << and the input operator >> are
overloaded; they can be used to write/read any of the
primitive types.
However, the input operator >> skips all whitespace in the input, so you
cannot use it to read a whitespace character (e.g., a space, tab, or
newline).
- It is up to you as the programmer to know what kind of data you
are going to read. If the data in the input does not match the
type of the variable you are reading into, you will either get a
runtime error, or the value you read will be garbage. For example,
if you run the following program:
#include <iostream>
int main() {
int x;
cout << "enter a number: ";
cin >> x;
return(0);
}
and you type a letter instead of a number, you will either get a runtime
error, or the value of x will be garbage.
TEST YOURSELF NOW
Write a C++ program that uses a loop to sum ten numbers read from the
standard input, and then writes the sum to the standard output.
solution
File I/O
To read from a file you must use a variable of type ifstream.
To write to a file you must use a variable of type ofstream.
In both cases, you must open the file before you can read or write.
For example, here's how to open the file named "input.dat" for reading:
#include <fstream>
ifstream inFile;
inFile.open("input.dat");
if (inFile.fail()) {
cerr << "unable to open file input.dat for reading" << endl;
exit(1);
}
Note that to use files you must #include <fstream>
(including iostream is not good enough). Also note that this code
writes its error message to cerr; that is the standard
error, and should generally be used for error messages instead of
the standard output.
Once inFile has successfully been opened for reading, you can use the
usual input operator to read values:
int n, sum = 0;
while (inFile >> n) {
sum += n;
}
In this example, each time the while loop condition is evaluated, the
next integer in the input file is read into variable x.
The while loop condition will evaluate to false when all of the
values in the input file have been read.
If you prefer to read one character at a time (including whitespace
characters), you can use the get operation:
char ch;
while (inFile.get(c)) {
...
}
In this example, each time the while loop condition is evaluated, the next
character in the input file is read into variable ch. As in the previous
example, the condition will evaluate to false when there are no more
characters in the input.
I/O Parameters
It is often useful to write a function that takes an input stream or an
output stream as a parameter, and reads from or writes to the given stream
(without worrying about whether it is using the standard input/output or a
particular file).
To do this, you should use parameters of type istream (for input), and
ostream (for output).
For example:
void f( istream & input, ostream & output ) {
int n;
output << "enter a number: ";
input >> n;
}
Note:
- "input" and "output" are the names used in the example for the two
parameters, but there is nothing special about those names; as usual,
it is up to the programmer to choose parameter names.
- The ampersands in front of the parameter names mean that the
two parameters are passed by reference.
The difference between value parameters and reference parameters
will be discussed in another set of notes. For now, just remember
that input and output streams must always be passed by reference
(or you will get a not-very-clear compile-time error).
- A call to function f can pass either the standard input or a file
(an ifstream) as the first parameter, and can pass either the
standard output, the standard error, or a file (an ofstream)
as the second parameter.
TEST YOURSELF NOW
Write a C++ program that includes two functions:
- function Compare has 3 parameters: 2 input streams and 1 output
stream. The function reads the characters from each of the two
inputs. If the sequences of characters are exactly the same, it
writes "equal" to the output stream; otherwise, it writes "not equal".
- function main opens the files "Input1" and "Input2" for
reading (giving an appropriate error message and quitting if either
open fails), then calls Compare, passing the two input files as well
as the standard output.
solution
Solutions to Self-Study Questions
Test Yourself #1
#include <iostream>
int main() {
int sum = 0;
int num;
for (int k=1; k<11; k++) {
cin >> num;
sum += num;
}
cout << "The sum is: " << sum << endl;
return 0;
}
Test Yourself #2
#include <fstream>
void Compare(istream &in1, istream &in2, ostream &out) {
char ch1, ch2;
while (in1.get(ch1)) {
if (!in2.get(ch2) || (ch1 != ch2)) {
out << "not equal";
return;
}
}
// here when no more characters in in1
// input files are the same iff there are also no more characters in in2
if (!in2.get(ch2)) out << "equal";
else out << "not equal";
}
int main() {
ifstream inFile1, inFile2;
inFile1.open("Input1");
if (inFile1.fail()) {
cerr << "unable to open file Input1 for reading" << endl;
exit(1);
}
inFile2.open("Input2");
if (inFile2.fail()) {
cerr << "unable to open file Input2 for reading" << endl;
exit(1);
}
Compare(inFile1, inFile2, cout);
return 0;
}
Note that the order of the two parts of the first "if" condition:
if (!in2.get(ch2) || (ch1 != ch2)) ...
is very important. Both C++ and Java guarantee that boolean expressions
are evaluated left-to-right, so the expression
!in2.get(ch2)
is evaluated before the expression
(ch1 != ch2)
This is important since we want to compare the character read in by
the call to get to the character in ch1. If the
two expressions might be evaluated right-to-left, then the first time
through the loop, the expression
(ch1 != ch2)
would use variable ch2 before it had been initialized.