![]() |
|||||||||
2.6 Basic Input/Output |
|||||||||
Stream Operators Operator overloading is the basis for input and output (I/O) in C++. Overloading is useful for I/O because the same operation (input or output) is being performed, but on different types. This is exactly the situation that operator overloading is meant to address. In C++, there is an overloaded operator that is programmed to handle I/O for each built-in type. Thus, the same operator is used for all types. At compile time the type of the data being input or output determines which of the overloaded operations will be used. The operator that is overloaded to handle I/O is not an operator with a name like "input" or "output," but is a symbolic operator. The symbolic operator << is used to represent output and the symbolic operator >> is used to represent input. It will be seen later that most of the C++ operators (e.g., +, -, *, /, <, >, =, ==) can be overloaded. In C++, I/O is based on a stream model. In a stream model the input data is viewed as a continuous stream of data that flows from a source into the the sequence of variables presented to the input stream. The type of the variables determines how the input stream is interpreted to provide values for the variables. On output, the values of variables flow into a (logically) continuous stream to the destination. The source (for input) and the destination (for output) may be the user or a file. Interactive stream I/O is provided by two classes:
class istream {...}; // stream input
class ostream {...}; // stream output
These classes use elements of the C++ language that have not been covered yet. The study of the C++ I/O classes is taken up later. For now, a minimal understanding of how to use these classes is sufficient. The standard C++ I/O library includes two predefined variables:
istream cin; // interactive input
ostream cout; // interactive output
These variables are declared in the file "stream.h" that can be included in a program using the include directive:
#include <stream.h>
Any single built-in type can be output by the << operator as shown in the following example:
cout << 10; // output an integer
cout << 1.234; // output a float
cout << 'x'; // output a character
cout << "Hello World." // output a string
cout << '\n'; // output a "newline" character
Because output is viewed as a stream, the five statements above can be reduced to the following single line:
cout << 10 << 1.234 << 'x' << "Hello World." << '\n';
The values are entered into the output stream in a left-to-right order. For readability, blanks are often inserted into the output stream as in this example:
cout << 10 << " " << 20 << '\n';
which inserts two blanks between the 10 and the 20. The newline character ('\n') can be used to end a line of output. As an alternative to the newline character, the standard I/O library defines a symbol "endl" (for "end line") that will also end the current line of output. The above example can thus be rewritten as:
cout << 10 << " " << 20 << endl;
using the endl symbol. Notice that there is no relationship between the number of lines of code that produce output and the number of lines of text that appear in the output. For example, the following three code fragments each output the same two lines of text:
(1) cout << 10;
cout << endl;
cout << 20 << endl;
(2) cout << 10 << endl << 20 << endl;
(3) cout 10 << endl << 20;
cout << endl;
The values of variables can be output using the stream operators as shown in the following example:
int x, y; // two integers
char c; // a character
char *s = "Hello "; // a string
float z = 1.415; // a floating point value
x = 100; y = 200;
cout << x << " " << y << endl << s << z << endl;
This produces the output string:
100 200
Hello 1.415
The output will appear as two lines because the endl symbol appeared twice in the output stream. Interactive input uses the predefined variable "cin" and the >> operator in a similar manner. For example, the statements
int x;
cin >> x;
cause an integer value to be read from the standard input and assigned as the value of the variable x. When reading, "whitespace" characters, such as blanks and tabs, are ignored. A dialogue with the user usually consists of a prompt-response sequence. The program prompts the user to enter data and then reads that data. For example, a program that wants to read two integer values that represent the hour and minute might look like:
int hour, minute;
cout << "Enter hour (integer) and minute (integer): " << endl;
cin >> hour >> minute;
Input from and output to disk files use a similar strategy. Two additional classes are defined in the standard C++ library:
class ifstream {
private:
...
public:
ifstream(char* filename); // name of file to use for input
...
};
class ofstream {
private:
...
public:
ofstream(char* filename); //name of file to use for output
...
};
The following example shows how data in files is manipulated using the stream I/O operators:
ifstream is("file.dat");
ofstream os("out.dat");
int x, y;
is >> x >> y; // reads two integers from file.dat
os << "The sum is: "; // output heading to out.dat
os << (x + y) << '\n'; // output sum and end line
Stream Output to a Window A variation of the Frame class, named TextFrame, allows stream output to a window. This class presents a very simplified version of the stream I/O model; it is restricted so that only output is possible and that only for the most basic built-in types (int, long, float, double, char, and char*). A partial definition of the TextFrame class is shown below. The constructors for a TextFrame are similar to those for a Frame object, as are the MoveTo and Resize methods. Keep in mind that the TextFrame class is not part of the standard C++ library - like the Frame class, it is only part of the materials used here for learning about C++.
The TextFrame class can be used as shown in the code below. This code creates two Frame objects and a TextFrame object. The code outputs to the TextFrame the name of the Frame object in which each mouse event occurs.
Frame window1("Window1", 100,100, 200, 200);
Frame window2("Window2", 400,400, 200, 200);
TextFrame out("Display", 400, 20, 200, 200);
OnStart() {
window1.DrawText("Click in this window", 20,20);
window2.DrawText("Click in this window", 20,20);
out << "Name of window clicked in will appear below" << '\n';
}
OnPaint() {
window1.DrawText("Click in this window", 20,20);
window2.DrawText("Click in this window", 20,20);
out << "Name of window clicked in will appear below" << '\n';
}
OnMouseEvent(char* frameName, int x, int y, int buttonState) {
out << name ;
out << '\';
}
OnTimerEvent() {}
The TextFrame class is useful for displaying textual information to a user and is also convenient for displaying status information during development, testing, and debugging.
String Streams The stream I/O facilities may be used to transfer formatted data to a character array, or to read formatted data from a character array. Although the stream I/O operators are used, the stream operators in this case only cause the transfer of information between the character array and other variables in memory. The string stream operations do not involve an input or output device or file. Stream processing using a character array is useful when formatted data (e.g., several integer values) are being passed to an interface that accepts only a single string (a char*) parameter. This occurs, for example, in the Frame class's DrawText method. To display one or more integer values in a Frame using DrawText, the integer data must first be converted to a single string. Using the stream output operators on a string stream, the integer data is written into the string stream. The string stream places the data in a character array. The stream output operations maintain an end-of-string character ('\0') after the last character added to the character array. Thus, the character array can then be handled as a normal character array or string. It is also possible to use the stream input operators to read formatted data from a character array. String stream processing involves two classes that are defined in the standard C++ library:
class istrstream {...};
class ostrstream {...};
The constructor for a string stream object requires a pointer to the beginning of the character array (or memory buffer) and an integer argument giving the length of the array (or buffer). Once constructed, the stream output operator (<<) can be applied to an ostrstream object and the stream input operator (>>) can be applied to an istrstream object. An example of using string stream processing is shown in the example below, which writes to a character array a simple arithmetic expression to add two integer values. The simple expression is formatted using the output string stream object named "expression" and parsed using an input string stream object named parser.
char text[100];
ostrstream expression(text, 100); // create string stream
expression << 10 << " + " << 20 << endl;
...
istrstream parser(text, 100);
int value1, value2;
char operator;
parser >> value1 // value1 = 10
>> operator // operator = '+'
>> value2; // value2 = 20
Notice that the two string streams are constructed using the "text" character array. It is into this character array that "expression" places its formatted data and from which "parser" reads characters to produce the formatted data requested of it.
Other Methods on Streams In addition to the stream I/O operators, stream objects also provide methods that may be invoked using the dot operator (.). These methods provide ways to query the status of the stream and to perform operations that are not readily described by an operator notation. Examples of operators that query the state of the stream are those that test whether the end of an input stream has been reached or whether the last operation performed on a stream has succeeded or failed. These two methods are used in the following code fragment:
if (cin.eof()) ... // at end of standard input stream
if (cin.fail()) ... // last input operation failed
An operation may fail, for example, if the stream was unable to parse the contents of an input stream adequately to produce a value of the required type. For example, if an integer is to be read next from the input stream and the next text in the input stream is "abcd," that cannot be read as an integer value. Reading an entire string or an entire line of input is also done through methods that use the dot operator, because this operation does not fit the stream operator model (i.e., there is no data type that corresponds to a line of input in C++). The method for reading a string or line of input is named "get" and it has three parameters:
Several details about the get method that help to understand its operation are these:
An example of using the get method to read a line of input is shown in the following example: char line[100]; ... cin.get(line, 100, '\n'); Notice that the dot operator has been used to apply the get method to the standard input stream object.
Tasks
|
|||||||||
|
|||||||||
ÿ