Docking or Floating a Toolbar

Chapter 18 - Complete I/O in C++

Visual C++ 6: The Complete Reference
Chris H. Pappas and William H. Murray, III
  Copyright 1998 The McGraw-Hill Companies

The iostream Class List
All of the I/O objects defined in the iostream class library share the same abstract stream base class, called ios, with the exception of the stream buffer classes. These derived classes fall into the four broad categories shown in Table 18-1.e
Table 18-1: The Four ios Class Categories
Input Stream Classes
Description
Istream
Used for general-purpose input or as a parent class for other derived input classes
Ifstream
Used for file input
Istream_withassign
Used for cin input
Istrstream
Used for string input
Output Stream Classes
Ostream
Used for general-purpose output or as a parent class for other derived output streams
Ofstream
Used for file output
Ofstream_withassign
Used for cout, cerr, and clog
ostrstream
Used for string output
Input/Output Stream Classes
iostream
Used for general-purpose input and output, or as a parent class for other derived I/O streams
fstream
File I/O stream class
strstream
String I/O stream class
stdiostream
Standard I/O stream class
Stream Buffer Classes
streambuf
Used as a parent class for derived object
filebuf
Disk file stream buffer class
strstreambuf
Stream buffer class for strings
stdiobuf
Stream buffer class for standard file I/O
Figure 18-1 illustrates the interrelationship between these ios stream classes.
Figure 18-1: C++ ios stream class hierarchy
All ios-derived iostream classes use a streambuf class object for the actual I/O processing. The iostream class library uses the three derived buffer classes with streams as shown in Table 18-2.
Table 18-2: Buffered Classes
Buffered Class
Description
filebuf
Provides buffered disk file I/O
strstreambuf
Provides an in-memory array of bytes to hold the stream data
stdiobuf
Provides buffered disk I/O with all buffering done by the standard I/O system
Derived classes usually expand upon their inherited parent class definitions. This is why it is possible to use an operator or member function for a derived class that doesn’t directly appear to be in the derived class’ definition.
Often, because of this fact, it will be necessary to research back to the root or parent class definition. Since C++ derives so many of its classes from the ios class, a portion of ios.h follows. You will be able to use this as an easy reference for understanding any class derived from ios.
#ifndef EOF
#define EOF (-1)
#endif

class streambuf;
class ostream;

class ios {
public:
   enum io_state {  goodbit   = 0x00,
                    eofbit    = 0x01,
                    failbit   = 0x02,
                    badbit    = 0x04 };

   enum open_mode { in        = 0x01,
                    out       = 0x02,
                    ate       = 0x04,
                    app       = 0x08,
                    trunc     = 0x10,
                    nocreate  = 0x20,
                    noreplace = 0x40,
                    binary    = 0x80 }; // not in latest spec.
   enum seek_dir { beg=0, cur=1, end=2 };

   enum {  skipws     = 0x0001,
           left       = 0x0002,
           right      = 0x0004,
           internal   = 0x0008,
           dec        = 0x0010,
           oct        = 0x0020,
           hex        = 0x0040,
           showbase   = 0x0080,
           showpoint  = 0x0100,
           uppercase  = 0x0200,
           showpos    = 0x0400,
           scientific = 0x0800,
           fixed      = 0x1000,
           unitbuf    = 0x2000,
           stdio      = 0x4000
                                };
   static const long basefield;   // dec | oct | hex
   static const long adjustfield; // left | right | internal
   static const long floatfield;  // scientific | fixed

   ios(streambuf*);               // differs from ANSI
   virtual ~ios( );

   inline long flags( ) const;
   inline long flags(long _l);

   inline long setf(long _f,long _m);
   inline long setf(long _l);
   inline long unsetf(long _l);

   inline int width( ) const;
   inline int width(int _i);
   inline ostream* tie(ostream* _os);
   inline ostream* tie( ) const;
   inline char fill( ) const;
   inline char fill(char _c);

   inline int precision(int _i);
   inline int precision( ) const;

   inline int rdstate( ) const;
   inline void clear(int _i = 0);

//  NOTE: inline operator void*( ) const;
   operator void *( ) const { if(state&(badbit|failbit) ) \
                             return 0; return (void *)this; }
   inline int operator!( ) const;

   inline int  good( ) const;
   inline int  eof( ) const;
   inline int  fail( ) const;
   inline int  bad( ) const;
The programs in the following sections use a derived class based on some parent class. Some of the example program code uses derived class member functions, while other statements use inherited characteristics. These examples will help you understand the many advantages of derived classes and inherited characteristics. While these concepts may appear difficult or frustrating at first, you’ll quickly appreciate how you can inherit functionality from a predefined class simply by defining a derived class based on the predefined one.
Input Stream Classes
The ifstream class used in the next example program is derived from fstreambase and istream. It provides input operations on a filebuf. The program concentrates on text stream input.
//
//  ifstrm.cpp
//  C++ program demonstrating how to use ifstream class,
//  derived from the istream class.
//  Copyright (c) Chris H. Pappas and William H. Murray, 1998
//
//  Valid member functions for ifstream include:
//         ifstream::open      ifstream::rdbuf
//
//  Valid member functions for istream include:
//         istream::gcount     istream::get
//         istream::getline    istream::ignore
//         istream::istream    istream::peek
//         istream::putback    istream::read
//         istream::seekg      istream::tellg
#include <fstream.h>
#define iCOLUMNS 80

void main(void)
{
 char cOneLine[iCOLUMNS];

 ifstream ifMyInputStream(“IFSTRM.CPP”,ios::in);
 while(ifMyInputStream) {
   ifMyInputStream.getline(cOneLine,iCOLUMNS);
   cout << ‘\n’ << cOneLine;
 }
 ifMyInputStream.close( );
}
The ifstream constructor is used first to create an ifstream object and connect it to an open file descriptor, ifMyInputStream. The syntax uses the name of a file, including a path if necessary (“IFSTRM.CPP”), along with one or more open modes (for example, ios::in | ios::nocreate | ios::binary). The default is text input. The optional ios::nocreate parameter tests for the file’s existence. The ifMyInputStream file descriptor’s integer value can be used in logical tests such as if and while statements and the value is automatically set to zero on EOF.
The getline( ) member function inherited from the iostream class allows a program to read whole lines of text up to a terminating null character. Function getline( ) has three formal parameters: a char *, the number of characters to input—including the null character—and an optional delimiter (default = ‘\n’).
cOneLine meets the first parameter requirement since char array names are technically pointers to characters. The number of characters to be input matches the array’s definition, or iCOLUMNS. No optional delimiter was defined. However, if you knew your input lines were delimited by a special character—for example, ‘*‘—you could have written the getline( ) statement like this:
ifMyInputStream.getline(cOneLine,iCOLUMNS,’*’);
The example program continues by printing the string and then manually closes the file ifMyInputStream.close( ).
Output Stream Classes
All ofstream classes are derived from fstreambase and ostream and allow a program to perform formatted and unformatted output to a streambuf. The output from this program is used later in this chapter in the section entitled “Binary Files” to contrast text output with binary output.
The following example uses the ofstream constructor, which is very similar to its ifstream counterpart, described earlier. It expects the name of the output file, “MYOSTRM.OUT,” and the open mode, ios::out.
//
// ostrm.cpp
// C++ program demonstrating how to use the ofstream class
// derived from the ostream class.
// Copyright (c) Chris H. Pappas and William H. Murray, 1998

// Valid ofstream member functions include:
//         ofstream::open     ofstream::rdbuf

// Valid ostream member functions include:
//         ostream::flush     ostream::ostream
//         ostream::put       ostream::seekp
//         ostream::tellp     ostream::write
#include <fstream.h>
#include <string.h>
#define iSTRING_MAX 40

void main(void)
{
 int i=0;
 long ltellp;
 char pszString[iSTRING_MAX] = “Sample test string\n”;

 // file opened in the default text mode
 ofstream ofMyOutputStream(“MYOSTRM.OUT”,ios::out);

 // write string out character by character
 // notice that ‘\n’ IS translated into 2 characters
 while(pszString[i] != ‘\0’) {
   ofMyOutputStream.put(pszString[i]);
   ltellp = ofMyOutputStream.tellp( );
   cout << “\ntellp value: ” << ltellp;
   i++;
 }


 // write entire string out with write member function

 ltellp = ofMyOutputStream.tellp( );
 cout << “\ntellp’s value before writing 2nd string: ”
      << ltellp;
 ofMyOutputStream.write(pszString,strlen(pszString));
 ltellp = ofMyOutputStream.tellp( );
 cout << “\ntellp’s updated value: ” << ltellp;

 ofMyOutputStream.close( );

}
The initial while loop prints out the pszString character by character with the put( ) member function. After each character is output, the variable ltellp is assigned the current put( ) pointer’s position as returned by the call to the tellp( ) member function. It is important that you stop at this point to take a look at the output generated by the program, shown at the end of this section.
The string variable pszString is initialized with 19 characters plus a ‘\0’ null terminator, bringing the count to a total of 20. However, although the program output generates a tellp count of 1..20, the 20th character is not the ‘\0’ null terminator. This is because in text mode, the pszString‘s ‘\n’ is translated into a 2-byte output, one for the carriage return (19th character) and the second for the linefeed (20th character). The null terminator is not output.
The last portion of the program calculates the output pointer’s position before and after using the write( ) member function to print pszString as a whole string. Notice that the tellp values printed show that the function write( ) also translates the single null terminator into a two-character output. If the character translation had not occurred, tellp‘s last value would be 39 (assuming put( ) left the first count at 20, not 19). The abbreviated output from the program looks like this:
tellp value: 1
tellp value: 2
tellp value: 3
    .
    .
    .
tellp value: 17
tellp value: 18
tellp value: 20
tellp’s value before writing 2nd string: 20
tellp’s updated value: 40
Fortunately, istream-derived class member functions such as get( ) and read( ) automatically convert the 2-byte output back to a single ‘\n’. The program highlights the need for caution when dealing with file I/O. If the file created by this program was used later as an input file and opened in binary mode, a disaster would occur. Because binary files do not use such translation, the file positions and contents would be incorrect.
Buffered Stream Classes
The streambuf class is the foundation for C++ stream I/O. This general class defines all of the basic operations that can be performed with character-oriented buffers. The streambuf class is also used to derive file buffers (filebuf class) and the istream and ostream classes that contain pointers to streambuf objects.
Any derived classes based on the ios class inherit a pointer to a streambuf. The filebuf class, as seen in Figure 18-2, is derived from streambuf and specializes the parent class to handle files.
Figure 18-2: The streambuf and derived classes
The following example begins by defining two filebuf handles, fbMyInputBuf and fbMyOutputBuf, using the open( ) member function to create each text file. Assuming there were no file-creation errors, each handle is then associated with an appropriate istream (input) and ostream (output) object. With both files opened, the while loop performs a simple echo print from the input stream is.get( ) to the output stream os.put( ), counting the number of linefeeds, ‘\n’. The overloaded close( ) member function manually closes each file.
//
//  filbuf.cpp
//  C++ program demonstrating how to use filebuf class.
//  Copyright (c) Chris H. Pappas and William H. Murray, 1998
//
//  Valid member functions include:
//         filebuf::attach      filebuf::close
//         filebuf::fd          filebuf::~filebuf
//         filebuf::filebuf     filebuf::is_open
//         filebuf::open        filebuf::overflow
//         filebuf::seekoff     filebuf::setbuf
//         filebuf::sync        filebuf::underflow
//
#include <fstream.h>
#include <fcntl.h>
#include <process.h> // exit prototype

void main(void)
{
 char ch;
 int iLineCount=0;
 filebuf fbMyInputBuf, fbMyOutputBuf;

 fbMyInputBuf.open(“c:\\FILBUF.CPP”,_O_WRONLY | _O_TEXT);
 if(fbMyInputBuf.is_open( ) == 0) {
   cerr << “Can’t open input file”;
   exit (1);
 }

 istream is(&fbMyInputBuf);

 fbMyOutputBuf.open(“c:\\output.dat”,_O_WRONLY | _O_TEXT);
 if(fbMyOutputBuf.is_open( ) == 0) {
   cerr << “Can’t open output file”;
   exit (2);
 }

 ostream os(&fbMyOutputBuf);
 while(is) {
   is.get(ch);
   os.put(ch);
   iLineCount += (ch == ‘\n’);
 }

 fbMyInputBuf.close( );
 fbMyOutputBuf.close( );

 cout << “You had ” << iLineCount << “ lines in your file”;
}
String Stream Class
The streambuf class can be used to extend the capabilities of the iostream class. Figure 18-1, shown earlier, illustrated the relationship between the ios and derived classes. It is the ios class that provides the derived classes with the programming interface and formatting features. However, it is the streambuf public members and virtual functions that do all the work. All derived ios classes make calls to these routines.
All buffered streambuf objects manage a fixed memory buffer called a reserve area. This reserve area can be divided into a get area for input and a put area for output. If an application requires, the get and put areas may overlap. Your program can use protected member functions to access and manipulate the two separate get and put pointers for character I/O. Each application determines the behavior of the buffers and pointers based on the program’s implementation of the derived class.
There are two constructors for streambuf objects. Their syntax looks like this:
streambuf::streambuf( );
streambuf::streambuf(char* pr, int nLength);
The first constructor is used indirectly by all streambuf derived classes. It sets all the internal pointers of the streambuf object to null. The second constructor creates a streambuf object that is attached to an existing character array. The following program demonstrates how to declare a string strstreambuf object derived from the streambuf base class. Once the stbMyStreamBuf object is created, the program outputs a single character using the sputc( ) member function and then reads the character back in with the sgetc( ) member function.
//
//  strbuf.cpp
//  C++ program demonstrating how to use the streambuf class.
//  Copyright (c) Chris H. Pappas and William H. Murray, 1998
//

#include <strstrea.h>
#define iMYBUFFSIZE 1024
void main(void)
{
 char c;

 strstreambuf stbMyStreamBuf(iMYBUFFSIZE);
 stbMyStreamBuf.sputc(‘A’);  // output single character to buffer
 c = stbMyStreamBuf.sgetc( );
 cout << c;
}
There are two separate pointers for streambuf-based objects, a put to and a get from. Each is manipulated independently of the other. The reason the sgetc( ) member function retrieves the ‘A’ is to return the contents of the buffer at the location to which the get pointer points. sputc( ) moves the put pointer but does not move the get pointer and does not return a character from the buffer.
Table 18-3 gives the names and explanations for all streambuf public members and highlights which functions manipulate the put and get pointers.
Table 18-3: Members of Streambuf
Public Member
Meaning
sgetc
Returns the character pointed to by the get pointer. However, sgetc does not move the pointer.
sgetn
Gets a series of characters from the streambuf buffer.
sputc
Puts a character in the put area and moves the put pointer.
sputn
Puts a sequence of characters into the streambuf buffer and then moves the put pointer.
snextc
Moves the get pointer and returns the next character.
sbumpc
Returns the current character and then moves the get pointer.
stossc
Advances the get pointer one position. However, stossc does not return a character.
sputbackc
Attempts to move the get pointer back one position. Character put back must match one from previous get.
out_waiting
Reports the number of characters in the put area.
in_avail
Reports the number of characters in the get area.
dbp
Outputs streambuf buffer statistics and pointer values.
Table 18-4 gives the names and explanations for all streambuf virtual functions.
Table 18-4: Virtual Functions of Streambuf
Virtual Function
Meaning
seekoff
Seeks to the specified offset
seekpos
Seeks to the specified position
overflow
Clears out the put area
underflow
Fills the get area if necessary
pbackfail
Extends the sputbackc( ) function
setbuf
Tries to attach a reserve area to the streambuf
sync
Clears out the put and get areas
Table 18-5 gives the names and explanations for all streambuf protected members.
Table 18-5: Protected Members of streambuf
Protected Member
Meaning
allocate
Allocates a buffer by calling doalloc
doallocate
Allocates a reserve area (virtual function)
base
Returns a pointer to the beginning of the
reserve area
ebuf
Returns a pointer to the end of the reserve area
blen
Returns the size of the reserve area
pbase
Returns a pointer to the beginning of the put area
pptr
Returns the put pointer
gptr
Returns the get pointer
eback
Returns the lower bound of the get area
epptr
Returns a pointer to the end of the put area
egptr
Returns a pointer to the end of the get area
setp
Sets all the put area pointers
setg
Sets all the get area pointers
pbump
Increments/decrements the put pointer
gbump
Increments/decrements the get pointer
setb
Sets up the reserve area
unbuffered
Sets or tests the streambuf0 buffer state variable
The streambuf class comes equipped with almost every function a programmer could possibly need for manipulating a stream buffer. Since the streambuf class is used to derive file buffers (filebuf class) and istream and ostream classes, they all inherit streambuf characteristics.

Books24x7.com, Inc 2000 –  


Visual C++ 6(c) The Complete Reference
Visual Studio 6: The Complete Reference
ISBN: B00007FYGA
EAN: N/A
Year: 1998
Pages: 207

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net