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
|
|||
|
|
|||
|
|