CPSC 427: Object-Oriented Programming
Michael J. Fischer
Problem Set 2 Preview
Think-A-Dot
Problem set 2 will involve implementing the 50-year-old plastic
Think-A-Dot toy.
Both the commercial 8 flip-flop toy and a more recent electronic 4-sided
13 flip-flop toy were passed around the class.
More information will be contained in the PS2 assignment.
C++ I/O
Streams
C++ I/O is done through streams.
Four standard streams are predefined:
Data is read from or written to a stream using the input and output operators:
>> (for input). | Example: cin >> x >> y; |
<< (for output). | Example: cout << "x=" << x; |
Opening and closing streams
You can use streams to read and write files.
Some ways of opening a stream.
Can also specify open modes.
To test if fin failed to open correctly, write if (!fin) {…}.
Reading data
Simple forms. Assume fin is an open input stream.
Writing data
Simple forms. Assume fout is an open output stream.
Manipulators
Manipulators are objects that can be arguments of >> or << but do not
necessarily produce data.
Example: cout << hex << x << y << dec << z << endl;
Manipulators are used in place of C formats to control input and output formatting and conversions.
Print methods in new classes
Each new class should have a print() function that writes out the
object in human-readable form.
print() takes a stream reference as an argument that specifies which
stream to write to.
The prototype for such a function should be:
ostream& print(ostream& out) const;
If sq is an object of the new class, we can print sq by writing
sq.print(out);
Note that const prevents print() from modifying the object that it is printing.
Extending the I/O operators
While sq.print() allows us to print sq, we’d rather do it in the familiar way
out << sq;.
Fortunately, C++ allows one to extend the meaning of << in this way. Here’s how.
Since this function is inline, it should go in the header file for class Square.
Remarks on operator extensions
Why << returns a stream reference
Both print() and operator<<() return a stream reference.
This allows compound constructs such as
out << "The square is: " << sq << endl;
By left associativity of <<, this is the same as
((out << "The square is: ") << sq) << endl;
Must it be inline?
If one wants operator<<() to be an ordinary function, the following changes are needed:
End of File and I/O Errors
Status bits I/O functions set status flags after each I/O operation. badbit means there was a read or write error on the file I/O. failbit means the data was not appropriate to the field, e.g., trying to read a non-numeric character into a numeric variable. eofbit means that the end of file has been reached. goodbit means that the above three bits are all off.
The whole state can be read with one call to rdstate().
Status functions
Functions are also provided for testing useful combinations of status bits.
As in C, correct end of file and error checking require paying close attention to detail of exactly when these state bits are turned on.
To continue after a bit has been set, must call clear() to clear it.
What eof means
Detecting and properly handling end of file is one of the most confusing
things in C++.
The I/O stream has status flags associated with it. The eof flag is
turned on when the stream attempts to read beyond the end of the
file.
The eof flag may or may not be on after the last byte of the file has been read and returned to the user.
When eof is turned on
Whether eof is on depends on whether the current input operation can complete without looking at the next byte.
Reading an int
What happens depends on the kind of read request. Consider what happens with cin >> x, where x is an int.
Reading an int (cont.)
Examples
The following examples show the remaining bytes in the file, where ␣ represents any whitespace character such as space or newline.
Common file-reading mistakes
We now talk about the practical issue of how to write your code to
correctly handle errors and end of file.
Two programming errors are common when reading data from a file:
Failing to read the last number
good is not always true after a successful read.
If the last number is not followed by whitespace, then after it is successfully read, eof is true and good is false. If one incorrectly assumes this means no data was read, the last number will not be processed.
Here’s a naive program that illustrates this problem:
On input file containing 1␣2␣3, it will print ␣1␣2.
Reading the last number twice
eof is not always true after the last number is read.
If the last number is followed by whitespace, then after it is read, eof will still be false. If one incorrectly assumes it is okay to keep reading as long as eof is false, the last read attempt will fail and the input variable won’t change.
Here’s a naive program that illustrates this problem:
On input file containing 1␣2␣3␣, it will print ␣1␣2␣3␣3.
How to read all numbers in a file
Here’s a correct way to correctly read and process all of the numbers. Instead of printing them out, it adds them up in the register s.
Functions and Methods
Call by value Like C, C++ passes explicit parameters by value.
Call by pointer Like C, pointer values (which I call reference values) are the things that can be stored in pointer variables.
Also like C, references values can be passed as arguments to functions having corresponding pointer parameters.