iostream examples

The sequence abstraction

The iostream library is built in two layers: The formatting layer discussed in previous subtopics, and a sequence layer based on the class streambuf. The formatting layer is responsible for converting between sequences of characters and various types of values and for high level manipulations of the streams. The sequencing layer is responsible for producing and consuming those sequences of characters. The most common way of using streambufs is with a stream. But streambuf is an independent class and may be used directly.

Abstractly, a streambuf represents a sequence of characters and two pointers into that sequence, a get and a put pointer. These pointers should be thought of as pointing at the locations either before or after characters in the sequence, rather than at specific characters. The sequences and pointers may be manipulated in a variety of ways, with the two fundamental ones being fetching the character after the get pointer, and storing a character in the position after the put pointer. Storing either replaces any previous character at that location or, if the put pointer was at the end of the sequence, extends the sequence. Other manipulations may move the pointers in various ways.

For the examples of this subtopic, we assume that there are two streambufs, pointed at by in and out. Methods for constructing streambufs appear later, but it is easy enough to get at the streambuf associated with a stream via rdbuf(). So we assume that in and out have been initialized with

   streambuf* in = cin.rdbuf() ;
   streambuf* out = cout.rdbuf() ;
An istream or ostream retains no information about the state of the associated streambuf. For example a program may alternate between extracting characters from in and cin.

The simplest operations are getting and putting characters. A simple loop to copy characters from one streambuf to another would be:

   int c ;
   while (( c = in->sbumpc()) != EOF ) {
   	if ( out->sputc(c) == EOF ) error("output error") ;
sbumpc() fetches the character after the get pointer and advances the get pointer over the fetched character. sputc() stores a character into the sequence and moves the put pointer past it. Both functions report errors by returning EOF, which is why c must be declared an int rather than a char. EOFs returned while fetching tend to mean that the streambuf has run out of characters from the ultimate producer. EOFs returned when storing tend to signal real errors. Because, unlike iostreams, streambufs do not contain any error state, it is possible that a store or fetch might fail one time and succeed the next time it is tried.

The streambuf class contains several different member functions for manipulating the get pointer. The following loop represents a common idiom:

   int c = in->sgetc() ;
   while ( c!=EOF && !isspace(c) ) {
   	c = in->snextc() ;
It scans the streambuf looking for a whitespace character (i.e., one for which isspace is non-zero). It stops when it finds that character leaving it available for extraction. This is because sgetc() and snextc() do not behave the way many programmers expect. sgetc() returns the character after the get pointer, but does not move the pointer. snextc() moves the get pointer and then returns the character that follows the new location. As usual both these functions return EOF to signal an error.

The copy loop moved characters one at a time. It is possible to do larger chunks, as in:

   static const int Bufsize = 1024 ;
   char buf[Bufsize] ;
   int p, g ;
   do {
   	g = sgetn(buf, Bufsize) ;
   	p = sputn(buf, g) ;
   	if ( p!=g ) error("output error");
   	} while ( g>0 ) ;

sgetn(b,n) attempts to fetch n characters from the sequence into the array starting at b. Similarly sputn(b,n) tries to store the n characters starting at b into the sequence. Both move the pointer (get or put respectively) over the characters they have processed and return the number transferred. For sgetn() this will be less than the number requested when the end of sequence is reached. When sputn() returns less than the number requested, it indicates an error of some sort.

Next topic: Buffering exposed
Previous topic: Manipulators

© 2004 The SCO Group, Inc. All rights reserved.
UnixWare 7 Release 7.1.4 - 27 April 2004