1108 lines
37 KiB
Plaintext
1108 lines
37 KiB
Plaintext
HOW TO USE THIS FILE: This file has a table of contents and
|
||
an index that refer to "pages" in this file. If your editor
|
||
has a search facility, you can use it to search for the page
|
||
numbers listed in either the table of contents or in the index.
|
||
The phrase "Page n" (where n represents the actual page number)
|
||
appears at the bottom left of the "page" it refers to. Thus, at
|
||
the bottom of page 1, you'll find "Page 1" as the last item on
|
||
that "page."
|
||
|
||
C++ VERSION 1.2 STREAMS
|
||
TABLE OF CONTENTS
|
||
___________________________________________________________________
|
||
|
||
Overview 1 Get functions . . . . . . 8
|
||
Output . . . . . . . . . . . . 1 Putback (function) . . . 8
|
||
Built-in types . . . . . . . 2 Controlling whitespace
|
||
Put functions . . . . . . . 2 skipping . . . . . . . . 9
|
||
Built-in formatting User-defined types . . . . 10
|
||
functions . . . . . . . . . 2 Initializing streams . . . 10
|
||
Numeric conversion . . . . 3 Output streams . . . . . . 10
|
||
Character string Input streams . . . . . . . 11
|
||
conversion . . . . . . . . 4 File I/O . . . . . . . . . . 12
|
||
General Formatting . . . . 5 Buffering streams . . . . . . 15
|
||
User-defined types . . . . . 6 String I/O . . . . . . . . . 16
|
||
Input . . . . . . . . . . . . 6 Stream states . . . . . . . . 18
|
||
Built-in types . . . . . . . 7
|
||
Controlling whitespace . . . 7 Index 19
|
||
|
||
|
||
OVERVIEW
|
||
|
||
This file describes C++ version 1.2 stream I/O. If you are planning
|
||
to program using or converting over to version 2.0 streams, see
|
||
Chapter 3, "C++ streams," in the Programmer's Guide.
|
||
|
||
Stream I/O in C++ is used to convert typed objects into readable text,
|
||
and vice-versa. It provides an easier and more intelligent alternative
|
||
to printf and scanf, and allows you to define input/output functions
|
||
which are then used automatically for corresponding user-defined
|
||
types. To access stream I/O, use the directive #include <stream.h>.
|
||
|
||
C++ programs start with three predefined open streams. These are
|
||
called cin, cout, and cerr. They correspond to the standard input,
|
||
output and error (stdin, stdout, and stderr) files of standard I/O
|
||
in C. You can reassign these standard names to other files or
|
||
character buffers after program startup.
|
||
|
||
|
||
Output
|
||
|
||
Stream output is accomplished via the << (put to) operator, which
|
||
is overloaded for stream output. Its left operand is an object
|
||
whose type is class ostream. Its right operand is any type for
|
||
which stream output has been defined (more about this later).
|
||
Stream output is predefined for built-in types. For example,
|
||
|
||
cout << "Hello\n"
|
||
|
||
writes the string "Hello" to cout (normally the standard output
|
||
file) followed by a newline.
|
||
|
||
The << operator binds left to right and returns its left operand,
|
||
so that several output operations may be combined in one statement.
|
||
For example,
|
||
|
||
void function display(int i, double d)
|
||
{
|
||
cout << "i = " << i << ", d = " << d << "\n";
|
||
}
|
||
|
||
Page 1
|
||
|
||
will write something like
|
||
|
||
i = 8, d = 2.34
|
||
|
||
to standard output.
|
||
|
||
|
||
Built-in types
|
||
|
||
The types directly supported for output, as in the example above,
|
||
are the built-in types char (both signed and unsigned), short, int,
|
||
long, char * (treated as a string), float, long double, and double.
|
||
Integral types are converted according to the default rules for the
|
||
ANSI C function printf. That is, for example, given the declara-
|
||
tions int i; long l;, the two statements
|
||
|
||
cout << i << " " << l;
|
||
printf("%d %ld", i, l);
|
||
|
||
produce the same result.
|
||
|
||
Similarly, floating-point types are converted according to the
|
||
default rules for the %g conversion. That is, for example, given
|
||
the declaration double d, the statements
|
||
|
||
cout << d;
|
||
printf("%g", d);
|
||
|
||
produce the same result. With character types,
|
||
|
||
cout << 'a';
|
||
|
||
produces a, not 97.
|
||
|
||
|
||
Put functions
|
||
|
||
The member function
|
||
|
||
ostream& ostream::put(char c);
|
||
|
||
writes the character c to an ostream as a character.
|
||
|
||
|
||
Built-in
|
||
formatting
|
||
functions
|
||
|
||
The following functions are defined in stream.h to aid in output
|
||
formatting. Each of these functions returns a pointer to a string
|
||
stored in a circular, or cyclical, static buffer. The buffer is
|
||
large enough to support reasonable sequences of output conversions,
|
||
|
||
Page 2
|
||
|
||
but the pointers returned should not be saved for later use--the
|
||
characters they point to may change in the meantime.
|
||
|
||
|
||
Numeric
|
||
conversion
|
||
|
||
Here are the three numeric conversion functions:
|
||
|
||
char * dec(long val, int width = 0);
|
||
|
||
char * hex(long val, int width = 0);
|
||
|
||
char * oct(long val, int width = 0);
|
||
|
||
Each of these functions takes an integral value val and returns a
|
||
pointer to a string corresponding to its decimal, hexadecimal, or
|
||
octal representation. The optional width parameter specifies the
|
||
number of characters in the returned string. If you omit this pa-
|
||
rameter or set it to zero, the exact number of characters required
|
||
will be used. Otherwise the string will be truncated on the right
|
||
or blank-filled on the left as needed.
|
||
|
||
Note that each of the statements
|
||
|
||
cout << i;
|
||
cout << dec(i);
|
||
cout << dec(i, 0);
|
||
|
||
produce identical results.
|
||
|
||
|
||
ANSI C equivalent
|
||
|
||
The numeric conversion routines have equivalents in ANSI C. For
|
||
example, the C++ statement
|
||
|
||
cout << dec(val, width);
|
||
|
||
is equivalent to the ANSI C statement
|
||
|
||
(width==0 ?
|
||
printf("%ld", (long) val) : /* convert to natural length */
|
||
(sprintf(t, "%ld", (long) val), /* else convert and */
|
||
printf("%*.*s, width, width, t))); /* possibly truncate */
|
||
|
||
where t is a temporary character array. C++ does not strictly
|
||
follow the ANSI printf conventions. In particular, passing a
|
||
negative value for width is the same as passing 0, unlike printf,
|
||
which takes a negative width value with * as a left-justify flag
|
||
(-), followed by a positive width.
|
||
|
||
Page 3
|
||
|
||
The hex and oct routines have similar equivalents, using the printf
|
||
%lx and %lo conversions, respectively.
|
||
|
||
|
||
Character string
|
||
conversion
|
||
|
||
Here are the two character string conversion functions:
|
||
|
||
char * chr(int ch, int width = 0);
|
||
char * str(const char *s, int width = 0);
|
||
|
||
Function chr returns a pointer to a string version of the input
|
||
character value. Function str takes a string pointer and returns a
|
||
string pointer. For both functions, the optional width parameter
|
||
specifies the number of characters in the returned string. If this
|
||
parameter is omitted or is zero, the exact number of characters
|
||
required will be used. Otherwise the string will be truncated on
|
||
the right or blank-filled on the left as needed.
|
||
|
||
For example, the expressions
|
||
|
||
chr(0)
|
||
str("")
|
||
|
||
are equivalent, and each returns an empty string.
|
||
|
||
Function chr is the third way to print a character as a character.
|
||
The previous example using the put function (on page 2) could also
|
||
be written as
|
||
|
||
cout << int('A') << " represents " << chr('A');
|
||
|
||
again resulting in "65 represents A".
|
||
|
||
Function str called with no width parameter (or with a 0 width)
|
||
returns a copy of the input string, but one with an undependable
|
||
lifetime. If it is called with width greater than 0, it returns a
|
||
string of the specified size, appropriately truncated or blank-
|
||
padded.
|
||
|
||
|
||
C equivalent
|
||
|
||
These string conversion routines have equivalents in C. The
|
||
following pairs of expressions are equivalent.
|
||
|
||
Page 4
|
||
|
||
___________________________________________________________________
|
||
|
||
C++ C
|
||
___________________________________________________________________
|
||
|
||
cout << chr(ch, width); (width==0 ?
|
||
printf("%c", ch) :
|
||
printf("%*c", width, ch));
|
||
|
||
|
||
cout << str(s, width); (width==0 ?
|
||
(void) printf("%s", s) :
|
||
(void) printf("%*.*s",
|
||
width, width, s));
|
||
___________________________________________________________________
|
||
|
||
|
||
General
|
||
Formatting
|
||
|
||
This function provides general formatting:
|
||
|
||
char * form (char * format ...);
|
||
|
||
As with the other conversion functions, it returns a pointer to a
|
||
static area which could be overwritten at a later time.
|
||
|
||
ANSI C equivalent
|
||
|
||
The form function is essentially the same as the ANSI C sprintf
|
||
function. The two differences are in the calling sequence.
|
||
|
||
1. The first argument of sprintf is a pointer to a character vector
|
||
to be written; form omits this argument and uses a static circu-
|
||
lar buffer instead.
|
||
|
||
2. sprintf returns the number of characters written; form returns a
|
||
pointer to the output character vector.
|
||
|
||
The form function can thus be used as part of an output specifica-
|
||
tion where the basic formatting is not adequate. For example:
|
||
|
||
cout << "pi = " << form ("%1.10f", pi); // show 10 decimal
|
||
places
|
||
|
||
The format string and additional parameters (if any) to form are
|
||
identical to those of sprintf. A C++ expression like
|
||
|
||
form (format, params)
|
||
|
||
is equivalent to the ANSI C expression
|
||
|
||
(sprintf(s, format, params), s)
|
||
|
||
Page 5
|
||
|
||
where s is a static character vector. Refer to the definition of
|
||
sprintf in the online help for more details.
|
||
|
||
|
||
User-defined
|
||
types
|
||
|
||
You can write your own output functions for your own defined types
|
||
simply by further overloading the << operator. For example, suppose
|
||
you have a type
|
||
|
||
typedef struct {
|
||
char *name;
|
||
double val;
|
||
char *units;
|
||
} info;
|
||
|
||
You could then define a function
|
||
|
||
ostream& operator << (ostream& s, info& m)
|
||
{
|
||
s << m.name << " = " << m.val << " " << m.units;
|
||
return s;
|
||
}
|
||
|
||
Then a simple reference such as
|
||
|
||
cout << m;
|
||
|
||
would produce output like "capacity = 1.25 liters".
|
||
|
||
|
||
Input
|
||
|
||
Stream input is accomplished via the >> (get from) operator, which
|
||
is overloaded for stream input. Its left operand is an object whose
|
||
type is class istream. Its right operand is any type for which
|
||
stream input has been defined. Stream input is predefined for
|
||
built-in types.
|
||
|
||
The >> input operator skips whitespace (as defined by the isspace
|
||
function in ctype.h), then reads in characters appropriate to the
|
||
type of the input object. (Actually, whitespace skipping can be
|
||
turned off; this is described below.)
|
||
|
||
The >> operator binds left to right and returns its left operand,
|
||
so that several input operations can be combined in one statement.
|
||
For example, consider
|
||
|
||
int i;
|
||
double d;
|
||
cin >> i >> d;
|
||
|
||
Page 6
|
||
|
||
This statement will cause whitespace to be skipped, digits read in
|
||
and converted to internal binary form and saved in variable i, more
|
||
whitespace to be skipped, and finally a floating-point number read
|
||
in and saved in variable d.
|
||
|
||
|
||
Built-in types
|
||
|
||
For types short, int, and long, the effect of operator >> is to
|
||
skip whitespace and convert an integral value, reading input char-
|
||
acters until one is found which cannot be part of the representa-
|
||
tion of the type. The format of integral values recognized is the
|
||
same as that of integer constants in C++, excluding integer
|
||
suffixes. That is, a leading 0x or 0X denotes hexadecimal
|
||
representation, a leading 0 not followed by x or X denotes octal
|
||
representation, and a leading 1 through 9 denotes decimal
|
||
representation. A trailing l, L, u, or U is not part of the value
|
||
and is not removed from the input stream.
|
||
|
||
For types float and double, the effect of operator >> is to skip
|
||
whitespace and convert a floating-point value, reading input
|
||
characters until one is found which cannot be part of a floating-
|
||
point representation. The format of floating-point values recog-
|
||
nized is the same as that of floating-point constants in C++,
|
||
excluding floating suffixes. That is, a trailing f, F, l, or L is
|
||
not part of the value and is not removed from the input stream.
|
||
|
||
For all numeric types, if the first non-whitespace character is not
|
||
a sign or digit (or decimal point for floating-point conversion),
|
||
the stream enters the _fail state (described on page 18) and no
|
||
further input will be done until the condition is cleared.
|
||
|
||
For type char, the effect of operator >> is to skip whitespace and
|
||
store the next (non-whitespace) character.
|
||
|
||
For type char * (treated as a string), the effect of operator >> is
|
||
to skip whitespace and store the next (non-whitespace) characters
|
||
until another whitespace character is found.
|
||
|
||
In all cases, if end of input occurs before any non-whitespace
|
||
character is found, nothing is stored in the target object. That
|
||
is, if the target was uninitialized, it will still be
|
||
uninitialized.
|
||
|
||
|
||
Controlling
|
||
whitespace
|
||
|
||
A whitespace character is one for which function isspace (in
|
||
ctype.h) returns a nonzero value. These are presently the blank
|
||
(' '), tab (\t), carriage-return (\r), newline (\n), formfeed (\f),
|
||
and vertical tab (\v).
|
||
|
||
Page 7
|
||
|
||
A standard object called WS of type struct whitespace is predefined
|
||
as a "sink" for (place to discard) whitespace characters. For
|
||
example,
|
||
|
||
cin >> WS;
|
||
|
||
will skip consecutive whitespace characters from the standard
|
||
input. The next character input will not be whitespace. This is
|
||
useful in routines reading user-defined types in conjunction with
|
||
one of the get member functions, or when skipping is turned off. We
|
||
discuss this in more detail later.
|
||
|
||
|
||
Get functions
|
||
|
||
As noted above, the >> operator for built-in types reads and
|
||
discards whitespace. The two get member functions in class istream
|
||
provide a way to read and process whitespace characters.
|
||
|
||
1. istream& istream::get (char& c);
|
||
|
||
This function reads the next character, whatever it is, into its
|
||
parameter.
|
||
|
||
2. istream& istream::get (char *buf, int max, int term='\n');
|
||
|
||
This function reads characters from the input stream into the
|
||
character vector pointed to by buf until max characters have
|
||
been read, or until the character term has been encountered,
|
||
whichever comes first. The default termination character (which
|
||
need not be specified) is the newline. The termination character
|
||
is not part of the characters read, and is not removed from the
|
||
input stream. The character vector buf must be larger than max,
|
||
since it must also hold the terminating null.
|
||
|
||
If we simply use s >> p instead, we would not be able to control
|
||
the number of characters read nor the termination character.
|
||
|
||
These are member functions, and so must be called in relation to
|
||
the input stream they are to read. See the example in the next
|
||
section.
|
||
|
||
|
||
Putback
|
||
(function)
|
||
|
||
The member function
|
||
|
||
void istream::putback(char c);
|
||
|
||
Page 8
|
||
|
||
pushes back one character into the input stream. putback pushes
|
||
back one (and only one) character onto the input stream; extras are
|
||
silently ignored. You cannot push back EOF.
|
||
|
||
Here is a simple routine which reads a C++ style identifier.
|
||
|
||
void getident (char *s /* where to put ident */)
|
||
{
|
||
char c = 0; // guard against EOF
|
||
|
||
cin >> c; // skips leading whitespace
|
||
if (isalpha(c) || c == '_')
|
||
do {
|
||
*s++ = c;
|
||
c = 0; // guard against EOF
|
||
cin.get(c);
|
||
} while (isalnum(c) || c == '_');
|
||
*s = 0; // terminate the string
|
||
if (c)
|
||
cin.putback(c); // we always get one too many
|
||
}
|
||
|
||
|
||
Controlling
|
||
whitespace
|
||
skipping
|
||
|
||
Input streams skip whitespace by default. However, you can
|
||
initialize an input stream to not skip whitespace. In addition, you
|
||
can turn the skipping on and off via the member function
|
||
|
||
int istream::skip (int doskip);
|
||
|
||
This function turns off the whitespace skipping state if parameter
|
||
doskip is zero, and turns it on otherwise. It returns the previous
|
||
skipping state.
|
||
|
||
When whitespace skipping is off, default input to the numeric,
|
||
character, and string types will fail if the next input character
|
||
is whitespace. Sending input to the WS object will discard
|
||
whitespace.
|
||
|
||
For example, suppose you want special processing for fields which
|
||
are separated by nonblank whitespace, such as tabs and newlines,
|
||
and normal processing for fields separated by blank characters.
|
||
|
||
char string[MAX], c;
|
||
int old_skip = cin.skip(0); // skipping off
|
||
while (cin.good()) {
|
||
do {
|
||
cin.get(c);
|
||
|
||
Page 9
|
||
|
||
} while (c == ' '); // skip blank characters
|
||
if (isspace(c))
|
||
special(); // nonblank whitespace
|
||
else {
|
||
cin.putback(c); // replace printable character
|
||
cin >> string; // get field and process
|
||
process(string);
|
||
}
|
||
}
|
||
cin.skip(old_skip); // restore old skip state
|
||
|
||
|
||
User-defined
|
||
types
|
||
|
||
You can write your own input functions for your own defined types
|
||
in the same way as for output functions. Here is a simple example
|
||
with no error checking to read in type info defined above.
|
||
|
||
istream& operator >> (istream& s, info& m)
|
||
{
|
||
s >> m.name >> m.val >> m.units;
|
||
return s;
|
||
}
|
||
|
||
An input line of text like "capacity 1.25 liters" can then be read
|
||
with a simple reference like
|
||
|
||
cin >> m;
|
||
|
||
|
||
Initializing
|
||
streams
|
||
|
||
The streams cin, cout, and cerr are initialized and open at program
|
||
start, and are connected to, respectively, the standard input,
|
||
standard output, and standard error files.
|
||
|
||
Initializing (constructing) a stream means associating it with a
|
||
stream buffer. We discuss input and output streams separately.
|
||
|
||
|
||
Output streams
|
||
|
||
Class ostream provides these three constructors.
|
||
|
||
1. ostream::ostream (streambuf *s);
|
||
|
||
This associates a named output stream with a stream buffer
|
||
(class streambuf or its derived classes, such as class filebuf).
|
||
|
||
Page 10
|
||
|
||
2. ostream::ostream (int fd);
|
||
|
||
This associates a named output stream with a file already
|
||
opened, and assigns a stream buffer to it. The normal use for
|
||
this is first to open a file as described below, and then imme-
|
||
diately to initialize a stream associated with it.
|
||
|
||
3. ostream::ostream (int size, char *buf);
|
||
|
||
This associates a named output stream with a character vector.
|
||
All "output" to the stream will be written to the vector. This
|
||
is described below.
|
||
|
||
The destructor for class ostream
|
||
|
||
ostream::~ostream()
|
||
|
||
flushes the output stream via the member function
|
||
|
||
ostream::flush()
|
||
|
||
You can also call this member function explicitly if you want, as
|
||
in this example:
|
||
|
||
cout << stuff; cout.flush();
|
||
|
||
|
||
Input streams
|
||
|
||
Class istream provides these three constructors.
|
||
|
||
1. istream::istream (streambuf *s, int skip = 1, ostream *t = 0);
|
||
|
||
This associates a named input stream with a stream buffer (class
|
||
streambuf).
|
||
|
||
Optional parameter skip specifies whether whitespace should be
|
||
skipped in input operations. The default is to skip.
|
||
|
||
Optional parameter t specifies an output stream to which this
|
||
input stream should be "tied". When two streams are tied, the
|
||
output stream is always flushed before anything is read from the
|
||
input stream. Standard streams cin and cout are tied.
|
||
|
||
2. istream::istream (int fd, int skip = 1, ostream *t = 0);
|
||
|
||
This associates a named input stream with a file already opened,
|
||
and assigns a stream buffer to it. The normal use for this is
|
||
first to open a file as described below, and then immediately to
|
||
initialize a stream associated with it.
|
||
|
||
The optional skip and t parameters are as described above.
|
||
|
||
Page 11
|
||
|
||
3. istream::istream (int size, char *buf, int skip = 1);
|
||
|
||
This associates a named input stream with a character vector.
|
||
All "input" from the stream will be read from the vector, as
|
||
described below.
|
||
|
||
The optional skip parameter is as described above.
|
||
|
||
Class istream includes member function
|
||
|
||
ostream * istream::tie (ostream *to);
|
||
|
||
Calling tie with the address of an output stream ties these two
|
||
streams together. Only one output stream may be tied to an input
|
||
stream. Calling tie again with a different output stream breaks the
|
||
previous tie and establishes a new one. Calling tie again with the
|
||
same output stream has no effect. Calling tie with an argument of
|
||
zero breaks the tie and associates no output stream with the input
|
||
stream.
|
||
|
||
Function tie returns the output stream previously associated, or
|
||
zero if there was none. For example, cin and cout are tied by
|
||
default. The statement
|
||
|
||
ostream *old_tie = cin.tie(0);
|
||
|
||
breaks the tie and allows asynchronous input and output with cin
|
||
and, presumably, cout. The statement
|
||
|
||
cin.tie(old_tie);
|
||
|
||
re-establishes the previous tie (presumably to cout) and ensures
|
||
that pending output is flushed before any input is requested from
|
||
cin. If cin and cout are connected to the user's terminal, you
|
||
would want them tied so that an output prompt would always appear
|
||
on the terminal before input was attempted.
|
||
|
||
|
||
File I/O
|
||
|
||
Apart from the files associated with standard streams cin, cout,
|
||
and cerr, you can associate an external file with class filebuf,
|
||
derived from class streambuf. Once you do this, you can associate
|
||
this file buffer with a stream to accomplish stream I/O on the
|
||
file.
|
||
|
||
Class filebuf has these four constructors:
|
||
|
||
1. filebuf::filebuf();
|
||
|
||
This only allocates a file buffer, without yet tying it to an
|
||
external file.
|
||
|
||
Page 12
|
||
|
||
2. filebuf::filebuf (FILE *f);
|
||
|
||
This associates a file buffer with an ANSI C standard I/O file
|
||
already open. This allows you to mix C standard I/O with stream
|
||
I/O in the same program. In the present implementation, all file
|
||
I/O is done via C standard I/O; in fact, using filebuf::open()
|
||
creates a C standard I/O file.
|
||
|
||
3. filebuf::filebuf (int fd);
|
||
|
||
This associates a file buffer with a file already open, such as
|
||
via the library function open. If input or output has already
|
||
taken place on this file, it is not guaranteed that further I/O
|
||
will work as desired. Stream I/O can't be mixed with low-level
|
||
read and write functions in particular.
|
||
|
||
4. filebuf::filebuf (int fd, char *buf, size len);
|
||
|
||
As above, this associates a file buffer with a file already
|
||
open. It further uses the supplied buffer specified by buf and
|
||
len for any file buffering, rather than allocating its own
|
||
buffer.
|
||
|
||
The class destructor, filebuf::~filebuf(), invokes member function
|
||
close, described below. Class filebuf includes the following five
|
||
public member functions:
|
||
|
||
1. filebuf * filebuf::open (char *name, open_mode om);
|
||
|
||
This member function opens a named file according to enumerated
|
||
type open_mode. It returns a pointer to the filebuf on success,
|
||
or zero on error.
|
||
|
||
Type open_mode is defined by enumerated type open_mode as
|
||
follows:
|
||
|
||
enum open_mode { input, output, append };
|
||
|
||
Mode append is for extending an existing output file. There is
|
||
no way to open a stream for both input and output (update mode).
|
||
|
||
2. int filebuf::close();
|
||
|
||
This member function closes the associated file and does any
|
||
other housekeeping actions required. It returns zero if the file
|
||
was closed successfully, and nonzero otherwise.
|
||
|
||
3. virtual int filebuf::snextc();
|
||
|
||
This gets and returns the next character from the input stream
|
||
buffer, or returns EOF on end of input.
|
||
|
||
Page 13
|
||
|
||
4. virtual int filebuf::sputc (int c);
|
||
|
||
This writes c, converted to a char, to the output stream buffer.
|
||
It returns C if successful, EOF on error.
|
||
|
||
5. virtual void filebuf::sputbackc(char c);
|
||
|
||
This pushes back one character into the (input) stream buffer.
|
||
You can always push back at least one character before reading a
|
||
character again. If you try to push back too many characters,
|
||
the extras are silently ignored. You cannot push back EOF. (That
|
||
is, the attempt to push back EOF is ignored.)
|
||
|
||
Associating a named file with a stream normally follows a sequence
|
||
such as this:
|
||
|
||
#include <stream.h>
|
||
filebuf inf;
|
||
if (inf.open(name, input) == 0) {
|
||
...error condition: exit
|
||
}
|
||
istream indata(&inf);
|
||
|
||
filebuf outf;
|
||
if (outf.open(name, output) == 0) {
|
||
...error condition: exit
|
||
}
|
||
ostream outdata(&outf);
|
||
|
||
If, for example, the input file were already open, we could replace
|
||
the first part of the code with
|
||
|
||
extern int fd;
|
||
filebuf inf(fd);
|
||
istream indata(&inf);
|
||
|
||
Be sure to call open to set up fd. Don't confuse open and
|
||
filebuf::open.
|
||
Or even more simply:
|
||
|
||
extern int fd;
|
||
istream(fd);
|
||
|
||
which includes allocating the file buffer.
|
||
|
||
Alternatively, we could open either file as a C standard I/O file.
|
||
|
||
FILE *f;
|
||
if ((f = fopen(name, "r")) == 0) {
|
||
...error condition: exit
|
||
}
|
||
filebuf inf(f);
|
||
|
||
Page 14
|
||
|
||
istream indata(&inf);
|
||
|
||
Finally, suppose a file has already been opened for C standard I/
|
||
O. We can associate a stream buffer with it like this:
|
||
|
||
extern FILE *f;
|
||
filebuf inf(f);
|
||
istream indata(&inf);
|
||
|
||
|
||
Buffering streams
|
||
|
||
Streams implement buffered text I/O. A stream is always associated
|
||
with a stream buffer, which is an object of class streambuf. This
|
||
class provides the basic buffering mechanisms independent of the
|
||
kind of device which might be physically associated with the
|
||
stream.
|
||
|
||
Class streambuf has the following two constructors:
|
||
|
||
1. streambuf::streambuf();
|
||
|
||
This only allocates a streambuf, with no buffer space reserved.
|
||
|
||
2. streambuf::streambuf (char *buf, int len);
|
||
|
||
This allocates a streambuf, using the given buffer address and
|
||
length. This is particularly useful for a stream attached to a
|
||
string.
|
||
|
||
Class streambuf has the following two protected member functions.
|
||
These are available for use by derived classes, but not by ordinary
|
||
user functions. (Notice that equivalent functions are provided by
|
||
derived classes istream and ostream where appropriate.)
|
||
|
||
1. int streambuf::allocate();
|
||
|
||
This allocates a 512 byte buffer (via new) for use by this
|
||
stream if one has not already been allocated. It returns zero if
|
||
all is well, and EOF to indicate that no buffer could be
|
||
allocated. If this mechanism allocates a buffer, the buffer is
|
||
automatically deleted by the class destructor
|
||
streambuf::~streambuf().
|
||
|
||
2. streambuf * streambuf::setbuf(char *buf, int len,
|
||
int offset = 0);
|
||
|
||
This assigns a user-supplied buffer to the streambuf. Any
|
||
previously-assigned buffer is disassociated. If the previous
|
||
buffer had been assigned via the allocate mechanism, it is
|
||
deleted. The optional parameter offset specifies where the next
|
||
free byte in the buffer is located. This allows a full or
|
||
|
||
Page 15
|
||
|
||
partially full buffer to be assigned to a streambuf, and is the
|
||
only way for a string to be usefully assigned to an input
|
||
stream. This member function always returns the streambuf.
|
||
|
||
The following three virtual functions are also protected:
|
||
|
||
1. virtual int streambuf::overflow(int c = EOF);
|
||
|
||
The derived class is responsible for providing a suitable
|
||
function for overflow. The overflow function should empty the
|
||
stream buffer, place c in the buffer, and return c, except
|
||
return EOF. This member function cannot empty a buffer (since
|
||
there is no place to put the data), so it just returns EOF.
|
||
|
||
2. virtual int streambuf::underflow();
|
||
|
||
The derived class is responsible for providing a suitable
|
||
function for underflow. This function always returns EOF.
|
||
|
||
3. virtual void streambuf::terminate();
|
||
|
||
This routine terminates the buffer with a null byte without
|
||
advancing the pointer.
|
||
|
||
The following three virtual functions are public.
|
||
|
||
1. virtual int streambuf::snextc();
|
||
|
||
This gets and returns the next character from an input stream
|
||
buffer, or EOF on end of input.
|
||
|
||
2. virtual int streambuf::sputc (int c);
|
||
|
||
This writes c, converted to a char, to an output stream buffer.
|
||
It returns c if ok, EOF on error.
|
||
|
||
3. virtual void streambuf::sputbackc(char c);
|
||
|
||
This pushes back one character into the (input) stream buffer.
|
||
You can always push back at least one character before reading a
|
||
character again. If you try to push back too many characters,
|
||
the extras are silently ignored. You cannot push back EOF.
|
||
|
||
|
||
String I/O
|
||
|
||
You can tie an input or output stream to a character vector instead
|
||
of a file. For input, the null byte terminating the string is taken
|
||
as end of file. For output, the ostream mechanism knows how big the
|
||
vector is, and will never write past the end.
|
||
|
||
Page 16
|
||
|
||
For input, an initializing part of a program can tie the input
|
||
stream to standard input, to a file, or to a string, and the rest
|
||
of the program simply does stream I/O without needing to know the
|
||
source of the input.
|
||
|
||
For output, a string can be formatted by a hierarchy of routines
|
||
which do not need to know whether they are writing to a file or to
|
||
a string, and which do not need to keep track of the current end of
|
||
the string or check for overflow.
|
||
|
||
In the following example, the main program can be invoked with a
|
||
literal string to process (flagged by "-" as the first program
|
||
parameter), with one or more file names to process, or with no
|
||
arguments, signifying that standard input is to be processed.
|
||
|
||
#include <stream.h>
|
||
|
||
// function "process" deals only with input streams,
|
||
// regardless of the actual source
|
||
void process (istream&);
|
||
|
||
main (int argc, char *argv[])
|
||
{
|
||
if (argc == 1) {
|
||
// no name given: use standard input
|
||
process(cin);
|
||
}
|
||
else if (argc == 3 && strcmp(argv[1], "-") == 0) {
|
||
// use the string
|
||
istream inp(strlen(argv[2]), argv[2]);
|
||
process(inp);
|
||
}
|
||
else {
|
||
for (int i = 1; i < argc; ++i) {
|
||
// process each file name
|
||
filebuf f; // new filebuf each iteration
|
||
if (f.open(argv[i], input) == 0) {
|
||
cerr << "Can't open " << argv[i] << '\n';
|
||
}
|
||
else {
|
||
istream inp(&f); // new istream each iteration
|
||
process(inp);
|
||
}
|
||
// automatically close and destruct at end of each
|
||
iteration
|
||
}
|
||
}
|
||
}
|
||
|
||
Page 17
|
||
|
||
Stream states
|
||
|
||
Each istream and ostream has a "state" associated with it, along
|
||
with public member functions to read and change the state. The
|
||
state is defined by enumerated type stream_state as follows:
|
||
|
||
enum stream_state { _good, _eof, _fail, _bad };
|
||
|
||
Don't rely on any particular numerical values for these state
|
||
names.
|
||
|
||
State _good means that the last I/O operation succeeded, and the
|
||
next one might succeed. State _eof means that no more input is
|
||
available from an input stream. State _fail means that the last
|
||
operation failed, and no further operations will succeed (no I/O
|
||
will be attempted once the _fail state is reached). State _bad
|
||
means that not only is the stream in a failed state, but that the
|
||
stream has been corrupted, meaning characters were lost.
|
||
|
||
The following five member functions are defined for both class
|
||
istream and ostream for testing the state:
|
||
|
||
1. enum stream_state rdstate(); // return the state
|
||
|
||
2. int eof(); // return nonzero if _eof
|
||
|
||
3. int fail(); // return nonzero if _failed or
|
||
_bad
|
||
|
||
4. int bad(); // return nonzero if _bad
|
||
|
||
5. int good(); // return nonzero if _good
|
||
|
||
The following member function can be used to set the state of a
|
||
stream. The default is to set the state to _good. Obviously, you
|
||
should use this function with care.
|
||
|
||
void clear (enum stream_state val = _good);
|
||
|
||
Finally, you can test a stream itself, with a nonzero return only
|
||
if the state is _good. This allows loops like
|
||
|
||
// process each item in file
|
||
while (cin >> val)
|
||
process(val);
|
||
|
||
or
|
||
|
||
// copy file, stripping all whitespace
|
||
char str[BIG_ARRAY];
|
||
while (cin >> str)
|
||
if (! (cout << str))
|
||
break; // error in output
|
||
|
||
Page 18
|
||
___________________________________________________________________
|
||
|
||
INDEX
|
||
|
||
>> (get from) operator input 6-12
|
||
concatenation 6 data types supported 7
|
||
overloading user-defined 10
|
||
user-defined types and 10 member functions
|
||
<< (put to) operator pushing characters into
|
||
concatenation 1 input stream 8
|
||
overloading put 2
|
||
user-defined types and 6 putback 8
|
||
<< operator skip 9
|
||
streams and 1 numbers
|
||
>> operator converting
|
||
streams and 6 ANSI C and 3
|
||
converting and conversions
|
||
3
|
||
A C++ 3
|
||
allocate (member function) 15 operators
|
||
ANSI >> (get from)
|
||
C standard overloading 10
|
||
C++ numeric conversion streams and 6
|
||
routines and 3 << (put to)
|
||
C++ string conversion concatenation 1
|
||
routines and 4 overloading 6
|
||
ASCII codes streams and 1
|
||
printing as characters operators (get from)
|
||
C++ 2 >>
|
||
concatenation 6
|
||
output 1-6
|
||
C data types supported 2
|
||
C++ formatting 2
|
||
characters user-defined 6
|
||
converting 4 streams
|
||
C and 4 << operator and 1
|
||
concatenation >> operator and 6
|
||
<< (get from) operator 1 buffering 15-16
|
||
>> (put to) operator 6 cout
|
||
constructors printf and 2
|
||
filebuf 12 initializing 10-12
|
||
istream and ostream 10, 11 using 1-19
|
||
streambuf 15 strings
|
||
destructors converting 4
|
||
~filebuf 13 C and 4
|
||
files input and output 16-17
|
||
input and output 12-15 whitespace in
|
||
identifiers controlling 7
|
||
reading 9
|
||
|
||
Page 19
|
||
|
||
characters D
|
||
converting data types
|
||
C++ 4 C++
|
||
input input and 7
|
||
C++ 7, 8 output and 2
|
||
output
|
||
C++ 2
|
||
pushing onto C++ input stream F
|
||
8 floating point
|
||
classes input
|
||
filebuf C++ 7
|
||
close member function 13 output
|
||
constructors 12 C++ 2
|
||
destructor 13 form (function)
|
||
open member function 13 sprintf and 5
|
||
snextc member function 13 format specifiers
|
||
sputbackc member function C++ and 2
|
||
14 formatting
|
||
sputc member function 14 C++
|
||
istream and ostream form function and 5
|
||
constructors 10, 11 output 2
|
||
member functions 18
|
||
states 18
|
||
tie member function 12 I
|
||
streambuf 15 integers
|
||
allocate member function 15 input
|
||
constructors 15 C++ 7
|
||
overflow member function 16 output
|
||
setbuf member function 15 C++ 2
|
||
snextc virtual member
|
||
function 16
|
||
sputbackc virtual member O
|
||
function 16 open (member function) 13
|
||
sputc virtual member overflow
|
||
function 16 member function 16
|
||
terminate virtual member
|
||
functions 16
|
||
underflow virtual member P
|
||
functions 16 printf (function)
|
||
close (member function) 13 cout and 2
|
||
conversions putback (member function) 8
|
||
C++ 3
|
||
ASCII code to characters 2
|
||
character S
|
||
C++ 4 setbuf (member function) 15
|
||
numeric skip (member function) 9
|
||
C++ 3 snextc (member function) 13, 16
|
||
strings sprintf (function)
|
||
C++ 4 form function and 5
|
||
sputbackc (member function) 14,
|
||
16
|
||
sputc (member function) 14, 16
|
||
|
||
Page 20
|
||
|
||
strings U
|
||
converting underflow
|
||
C++ 4 member function 16
|
||
|
||
|
||
T W
|
||
terminate (member function) 16 whitespace
|
||
tie (member function) 12 C++ and 7
|
||
skipping 9
|
||
|
||
Page 21
|
||
|
||
|