Angelika Langer - Training & Consulting
HOME | COURSES | TALKS | ARTICLES | GENERICS | LAMBDAS | IOSTREAMS | ABOUT | CONTACT | Twitter | Lanyrd | Linkedin
 
HOME 
GENERICS 
LAMBDAS 

IOSTREAMS

    BOOK PAGE
    ERRATA
    ABSTRACT
    CONTENT
    PREFACE
    EXCERPT
    QUOTES
    AUTHORS
    REVIEWS
    CODE
    FORUM
    SEMINAR   
 

ABOUT 
CONTACT 
Errata (1st Printing)

 
           

Standard C++ IOStreams and Locales

Advanced Programmer's Guide and Reference

Angelika Langer & Klaus Kreft
Addison-Wesley, January 2000
ISBN 0-201-18395-1

Errata (1st Printing)
 
Thanks to everybody who took the time to send us an email to draw our attention to mistakes and typos in the book. We thank our readers for reading the book so carefully and attentively that you could spot the flaws. Thanks a lot!

Below is a list of errors that have have been identified in the first printing. All of these errors should be corrected in the second printing. 

Feel free to send us email as soon as you detect another mistake. 
 
page 21
page 22
page 33
page 35
page 37
page 38
page 39
page 40
page 42
page 43
page 45
page 48
page 50
page 53
page 55
page 58
page 70 & 77
page 73
page 85
page 89 & 90
page 92
page 115
page 144
page 152 -155
page 156
page 160
page 161
page 162
page 171
page 177
page 180
page 188
page 221
page 222
page 225 - 248
page 233
page 240
page 241
page 242
page 245
page 255
page 272
page 275
page 281
page 284
page 286
page 287
page 288
page 296
page 298
page 305
page 315
page 316
page 317
page 322
page 323
page 325
page 327 & 333
page 335
page 336
page 338 & 339
page 456
page 464
page 479
page 487
page 502
page 508
page 511
page 511 & 513
page 512 & 514
page 516
page 549
page 565
page 614 & 615
page 621
page 632
page 636
page 638
page 640

page 21:
The example uses a C-style string for demonstration of the effect of width. However, what we describe is wrong, because the maximum number of extracted characters is width() for C++ strings and width()-1 for C string.  In our example, only 9 instead of 10 characters would  be extracted. We should have better been using a C++ string. The example but be corrected to:

// input
int i; string s;

cin.width(10);
cin >> i >> s;

error found by: 
Scott Barrett, Principal Member Technical Staff 
PAR Government Systems Corporation, Rome, NY, May 2001

page 22:
The code sample for demonstrating the effect of the field width setting is misleading because the leading white spaces are not visible.  It should be changed to:

  // output
 int i; char s[11];

 cout.width(10);
  cout.fill('.');
 cout <<i << s;

 If the variables i and s have the following values:
  i: 123
 and 
  s: "abc"

 then the output is

  ....... 123abc

that is, seven dots followed by the three digits representing the value of i , followed by the character sequence contained in s .

error found by: 
Bernd Mohr / Research Centre Juelich, ZAM, Germany, August 2000 

page 33:
The first two paragraphs in the section on "The Stream State's Effect on Insertion and Extraction" on page 33 is misleading and should read:

   The stream state affects the behavior of the IOStreams operations. By convention, all IOStreams operations have no effect once the stream state indicates an error situation. More specifically, I/O operations do nothing if the initial stream state at the time of  their invocation includes either failbit , badbit , or eofbit , and input and output operations stop as soon as one of the stream state flags is set.
   Note the interesting effect of the eofbit : Extractions do not only stop in case of an error ( failbit or badbit ), but also when the end of the input stream is reached ( eofbit ). Insertions typically stop only in case of an error, because no output operation ever sets the eofbit . If, however, the eofbit has been set before the output operation is invoked, then the attempted insertion will fail and have no effect. This can happen in bidirectional streams when an extraction that reached the end of the input is followed by an insertion to the stream, which then has the eofbit set due to the preceeding extraction. For this reason the eofbit in addition to the error flags failbit and badbit stops operations on input and bidirectional streams, but is irrelevant for operations on output streams. 

error found by: 
Bernd Mohr / Research Centre Juelich, ZAM, Germany, August 2000 

page 35:
In the middle of page 35 we describe the effect of the cast operator that converts a stream to type void* saying the following: 

The cast operator operator void*() returns a zero pointer value if failbit or badbit are set, and zero otherwise. 

Of course, this is nonsense.  It must be corrected to:

The cast operator operator void*() returns a zero pointer value if failbit or badbit are
set, and nonzero otherwise.

error found by: 
Robert P. Goddard, Senior Physicist, University of Washington, Seattle, WA, January 2001

page 37:
An alternative to wrapping the critical operations into a try block is to suppress exceptions, execute all critical operations, and activate them afterwards. Here is an example: 

cout.exceptions(ios_base::goodbit);
cout << x;
// do lots of other stream I/O
try {cout.exceptions(ios_base::badbit | ios_base::failbit);}
catch(ios_base::failure& exc)
{   if (cout.bad())
    { 
       // unrecoverable error
        ...
        throw;
    } 
    else if(cout.fail())
    { 
        // retry
        ...
        return;
    }
}

The call to cout .exceptions(ios_base::goodbit) clears the exception mask and deactivates all exceptions. All of the subsequent statements are executed because no exception can be thrown. Eventually, the call to cout .exceptions (ios_base::badbit | ios_base::failbit) is wrapped into a try block and raises an ios_base::failure exception in case that any of the previously executed operations failed. 

error found by: 
students of an IOStreams seminar held at SAP AG in St. Leon-Rot, Germany, April 2000

page 38:
To reset the stream state to good after an error has occured either clear() or clear(goodbit) can be used . Let us add a call to clear() to the example above where we suggest to retry I/O processing. The code changes to: 

  cout.exceptions(ios_base::goodbit);
  cout << x;
 // do lots of other stream I/O
 try {cout.exceptions(ios_base::badbit | ios_base::failbit);}
 catch(ios_base::failure& exc)
 {   if (cout.bad())
     { 
         // unrecoverable error
         ...
         throw;
     } 
     else if(cout.fail())
     { 
         cout.clear(); 
         // redo the stream I/O that does not cause failure
         return;
     }
 }

error in code found by: 
students of an IOStreams seminar held at SAP AG in St. Leon-Rot, Germany, April 2000
typo in comment found by:
Robert W. Hand, February 2001

page 39:
The comment in the code snippet on page 39 should read:

     else if(cout.fail())
     { 
         cout.clear(); 
         // redo those stream I/O operations that do not cause failure
         return;
     }
 }

error found by: 
Vikram bir Singh, September 2000

page 40:
The first code example on page 40 should read:

ifstream source ("src.cpp") ;

error found by: 
Jonathan Levinson, July 2000

page 42:
The last paragraph on page 42 is slightly misleading and should read:

THE INITIAL FILE LENGTH . The open mode trunc (meaning truncate )  sets the initial file length to zero, which has the effect of discarding the file content. The trunc flag is  included in the default open mode of output file streams, so you can omit the trunc flag and think of the open mode out as being equivalent to out|trunc . This only holds true for output file streams. For bidirectional file streams, the trunc flag must always be explicitly specified, i.e., you must say in|out|trunc , if the file content is to be discarded.

error found by: 
Bernd Mohr / Research Centre Juelich, ZAM, Germany, August 2000

page 43:
The last code example on page 43 should read:

fstream BiStr( "poem.txt" , ios_base::in|ios_base::out );

error found by: 
Clinton James, IT Director, UCS Call One, Chicago, IL USA, July 2000 and
Vikram bir Singh, September 2000

page 45:
The first code example on page 45 should read:

// bidirectional file stream opened only for input
fstream BiFil("poem.txt", ios_base::in );

error found by: 
Vikram bir Singh, September 2000

page 48:
Typically, you use in-memory I/O if the information to be read is already available in the form of a string, or if the formatted result will be processed as a string.  For example, to interpret the contents of a string as an integer value, the code might look like this: 

 int i;
 if (istringstream("4711") >> i)
 {
    // i has the value: 4711
 }

The equivalent operation in C would be a call to the sscanf() function. However, string streams are more powerful than sscanf() , because they use the full set of formatting facilities of IOStreams, including internationalization for instance.

error found by: 
students of an IOStreams seminar held at SAP AG in St. Leon-Rot, Germany, April 2000

page 50:
A -- is printed as a plain - in the code snippet on page 50. The code snippet should read:

  // character buffer; can store lines of length 99
 // note: input adds a terminating null character 
 const int line_buffer_size = 100;
 char buffer[line_buffer_size];

 int line_number = 0;
 while (cin.getline(buffer, line_buffer_size, '\n')    // stream still good() ?
     || cin.gcount())                                 // any characters read ?
 {
   int count = cin.gcount();

   if (cin.eof())
       // end of file found; last line extracted
       cout << "Partial final line"; 
   else if (cin.fail()) 
   {   // max number of chars was reached; line was longer 99 chars
       cout << "Partial long line";
       // clear stream state so that we can continue reading
       cin.clear(cin.rdstate() & ~ios::failbit);
   } else {
       // don't include newline in count
       // mind: delimiter was extracted and counted, but not stored 
       count--;
       cout << "Line " << ++line_number;
   }
   cout << " (" << count << " chars): " << buffer << endl;
 }

error found by: 
Igor V. Rafienko, Norway, September 2000

page 53:
The last paragraph should read:

The error handling is omitted from the example. The functions tellp()/tellg() indicate failure by returning the invalid stream position pos_type(-1) and seekp()/ seekg() indicate failure by setting the stream state.

error found by: 
Wolfgang Kaisers, Germany, July 2000

page 55:
A -- is printed as a plain - in the code snippets on page 55. The code snippets should read:

 ofstream ostr("/tmp/fil"); 
 int i=10;
 ostr << unitbuf;
 while ( i-- )
 { ostr << i; }

and

 ofstream ostr("/tmp/fil"); 
 int i=10;
 while ( i-- )
 { ostr << i; 
   ostr.flush();
 }

error found by: 
Igor V. Rafienko, Norway, September 2000

page 58:
We failed to mention that sync_with_stdio is a member function of ios_base; instead our code snippet suggests that is its a global function. The corresponding section should read:

This synchronization is time consuming and for this reason might not be desired in all situations. You can switch it off by calling

  ios_base:: sync_with_stdio(false);

where sync_with_stdio() is a static stream member function defined in base class ios_base

After such a call the predefined streams will operate independently of the C standard files, with possible performance improvements in your C++ stream operations. 
 

error found by: 
Igor V. Rafienko, Norway, September 2000
further improvements suggestes by: 
Robert P. Goddard, Senior Physicist, University of Washington, Seattle, WA, January 2001

page 70 and 77:
In diagrams change basic_streamout to basic_streambuf .

error found by: 
students of an IOStreams seminar held at SAP AG in St. Leon-Rot, Germany, April 2000

page73:
On that page we describe the difference between  the base class version of rdbuf() and the hiding version in the concrete stream classes. The text says: 

Mind the difference described in the preceding chapter between the base class version of rdbuf() and the hiding version in the concrete stream classes. The base class version returns the stream buffer object referred to by the stream buffer pointer; the derived class version returns a pointer to the embedded stream buffer object. After resetting of the stream buffer pointer, both are different.

Astute reader Robert Goddard comments: The phrase "both are different" is ambiguous: different from one another (true), or both are different from their previous values (false)? I suggest the phrase "the result of a call to the base class's rdbuf() has changed but the result of a call to the concrete class's rdbuf() has not." Or, since you have spelled it out elsewhere, you may choose to shorten it to "the results of calling the two rdbuf() functions differ from one another."

Suggested reading of the section therefore is:

Mind the difference described in the preceding chapter between the base class version of rdbuf() and the hiding version in the concrete stream classes. The base class version returns the stream buffer object referred to by the stream buffer pointer; the derived class version returns a pointer to the embedded stream buffer object. After resetting of the stream buffer pointer, the results of calling the two rdbuf() functions differ from one another.

error found by: 
Robert P. Goddard, Senior Physicist, University of Washington, Seattle, WA, January 2001

page 85:
Suggested improvement:

Class basic_streambuf<class charT, class Traits> is an ”abstract” base class in the sense that no instances of this class can be constructed. Its constructor is protected and hence accessible only to derived classes. 

error found by: 
James M. Stern,   ITG, Inc., Culver City, CA, April 2001

page 89 & 90:
Typos in various places: replace "exits" by "exists":

page 89:
If the put area exists and it is not already full, i.e. next_pointer != 0 and next_pointer < end_pointer, then the character is put to the position the next_pointer is referring to, and the next_pointer is incremented. 

page 90:
 If the get area exists and characters have already been read, i.e. next_pointer != 0 and begin_pointer < next_pointer, then a putback position is available. 

error found by: 
Robert P. Goddard, Senior Physicist, University of Washington, Seattle, WA, January 2001

page 92:
The buffer in the diagram is larger than intended. Correct the diagram to:

error found by: 
Vikram bir Singh, October 2000

page 115:
The code sample must be corrected to: 

template <class charT, class Traits>
void foo(basic_streambuf<charT,Traits>* sbuf)
{
  Traits::char_type c;
  Traits::int_type i;
  i = sbuf->sgetc();      // get the next value
                          // see whether it’s end-of-file
  if (! Traits:: eq_int_type(i,Traits::eof())) 
                          // if not, convert it to a character
  { c = Traits:: to_char_type(i); 
    ...                   // pass on the character
  }
}

error found by: 
Wolfgang Kaisers, Germany, July 2000

page 144:
Must read: 

Invocation of erase_event callback functions on calls to copyfmt() is useful because copyfmt() overwrites the original data members of the stream object.

error found by: 
James M. Stern,   ITG, Inc., Culver City, CA, April 2001

page 152-155:
The references to section 3.1.4, Refined Inserters and Extractors, is incorrect in various places. The following pages must be corrected: 

page 152:
The example in section 3.1.4 , Refined Inserters and Extractors, demonstrates the correct use of sentries.

page 154:
A concrete example is shown in section 3.1.4 , Refined Inserters and Extractors.

page 155:
Some of these aspects are demonstrated in the example presented in section 3.1.4 , Refined Inserters and Extractors. 

page 155:
The inserters and extractors presented in section 3.1.5 , Generic Inserters and Extractors, are another demonstration of the principle. 

error found by: 
Mark Rodgers   Cadenza New Zealand Ltd, June 2000 and
Wolfgang Kaisers, Germany, July 2000 and
Bernd Mohr / Research Centre Juelich, ZAM, Germany, August 2000 

page 156:
Ignore the footnote on page 156. We initially had no intent to discuss format control parameters, but decided later that the example would be incomplete without it and added a section on format control (see section 3.1.4.3).  For this reason the footnote is obsolete and should be removed.

error found by: 
Bernd Mohr / Research Centre Juelich, ZAM, Germany, August 2000

page 160:
Part of the sample code for the inserter is incorrect because the fill_n algorithm does not return the advanced output itertor as we had assumed, but returns void instead. The corresponding code must be corrected to: 

if (charToPad <= 0)
{
   sink = copy(s.begin(), s.end(), sink);
}
else
{
   if (os.flags() & ios_base::left)
   {
      sink = copy(s.begin(), s.end(), sink);
    fill_n(sink,charToPad,os.fill());
   }
   else
   {
    fill_n(sink,charToPad,os.fill());
      sink = copy(s.begin(), s.end(), sink);
   }
}

error found by: 
Wolfgang Kaisers, Germany, July 2000

page 161:
The  section below might be slightly misleading. We did not mean to suggest that the C++ standard requires  dates before January 1, 1970 to be unrepresentable.

mktime() also flags date values that cannot be represented in a tm structure, such as dates before January 1, 1970. 

The C standard states that a conforming implementation of the C library is required to document its choice of range and precision of times representable in time_t. In all implementations that we know of the valid range starts with January 1, 1970. In other words, whether or not a date before January 1, 1970 can be represented is implementation-defined.

Suggested improvement: add a footnote.

mktime() also flags date values that cannot be represented. *

* The range of times representable in time_t is implementation-defined. In many implementations of the C library dates before January 1, 1970 cannot be represented. 

error found by: 
James M. Stern,   ITG, Inc., Culver City, CA, April 2001

page 162:
The sample code is a simplification of the truth: The leap-year rule in date::valid() is a little off. For example, 1900 wasn't a leap year and 2100 won't be. We were deliberately trying to keep the algorithm simple, because the focus of this section is on error indication in inserters and extractors rather than leap-year algorithms. 

Suggested improvement: add a footnote.

   bool valid()  // check for sensible date; rejects nonsense like 32.12.1999 *
   { 
    ...
   }

* The leap-year rule in date::valid() is simplified For example, 1900 wasn't a leap year and 2100 won't be.

error found by: 
James M. Stern,   ITG, Inc., Culver City, CA, April 2001

page 171:
The sample code for the inserter is incorrect and must be corrected to: 

template <class charT, class Traits, class Argument >
basic_ostream<charT, Traits>& g_inserter 
  (basic_ostream<charT, Traits>& os, const Argument& arg )
{ ... }

error found by: 
Ben Dorman, Ph.D.   Principal Programmer Analyst, Raytheon ITSS
Laboratory for High Energy Astrophysics, NASA/GSFC, Greenbelt MD, April 2000

page 177:
Three of the function pointer types on page 177 are incorrect and must be corrected to: 

(2) basic_ios<charT,Traits>&     (*pf)(basic_ios<charT,Traits> & )
(3) basic_istream<charT,Traits>& (*pf)(basic_istream<charT,Traits> & )
(4) basic_ostream<charT,Traits>& (*pf)(basic_ostream<charT,Traits> & )

error found by: 
Wayne Vucenic, Contract Programmer
No Bugs Software, Cupertino, California, June 2001

page 180:
The code samples contains some bugs. It must be corrected to:

  class mendl {
 public:
    explicit mendl(unsigned int i) : i_(i) {}
 private:
    unsigned int i_;

    template <class charT, class Traits>
    friend basic_ostream<charT,Traits>& operator<< 
    (basic_ostream<charT,Traits>& os, const mendl& w)
    { 
      // the manipulation: insert end-of-line characters and flush
      for (int i=0; i< w. i_;  i++)
         os.put(os.widen('\n')); 
      return os.flush();
    }
 };

error found by: 
Pete McEvoy, August 2000 

page 188:
The sample first code on this page has a couple of class keyword that shouldn't be there. It should read: 

 template <class charT, class Traits, class Argument>
  basic_ostream<charT,Traits> & operator<< 
 ( basic_ostream<charT,Traits> & os, 
 const one_arg_manip_weh<Argument>& oamw)
 {
  if(os.good())
     do_manip(os,oamw);
  return os;
 }

error found by: 
Brian Chamberlain, July 2000

page 221:
Freudian slip. The section must read:

The format string "%Y" produces the year with century as a decimal number, yet the output on  the terminal is 

 Hello World, this is ths year 1/1/00

error found by: 
James M. Stern,   ITG, Inc., Culver City, CA, April 2001

page 222:
The section must read:

Consequently, setting the format string to "%Y" has no effect.

error found by: 
James M. Stern,   ITG, Inc., Culver City, CA, April 2001

page 225 - 248:
Throughout chapter 3.4 all member functions that return an int_type are incorrectly declared: the nested type int_type  must be fully qualified with the respective class scope when the member functions are defined outside of the class scope. The following corrections must be made: 

page 231:
template <class charT, class traits >
unbuffered_streambuf<charT,traits>:: int_type
unbuffered_streambuf<charT,traits>::overflow(int_type c)
{  ...  }

page 232:
template <class charT, class traits >
unbuffered_streambuf<charT,traits>:: int_type
unbuffered_streambuf<charT,traits>::underflow()
{  ...  }

page 232:
template <class charT, class traits>
unbuffered_streambuf<charT,traits>:: int_type
unbuffered_streambuf<charT,traits>:: uflow()
{  ...  }

template <class charT, class traits >
unbuffered_streambuf<charT,traits>:: int_type
unbuffered_streambuf<charT,traits>::pbackfail(int_type c)
{  ...  }

page 237:
template <class charT, class traits>
outbuf<charT,traits>:: int_type 
outbuf<charT,traits>::overflow (int_type c)
{  ...  }

page 240:
template <class charT, class traits>
inbuf<charT,traits>:: int_type inbuf<charT,traits>::underflow()
{  ...  }

page 242:
template <class charT, class traits>
inbuf<charT,traits>:: int_type 
inbuf<charT,traits>::pbackfail(int_type c)
{  ...  }

error found by: 
Mogens Hansen  Software Engineer at MAN B&W Diesel A/S in Copenhagen, Denmark  and
Allan Stokes   Victoria BC, Canada, June 2000 

page 233:
The signature of uflow() is incorrect and must be corrected to: 

template <class charT, class traits>
unbuffered_streambuf<charT, traits>:: int_type
unbuffered_streambuf<charT, traits>:: uflow()
{  ...  }

error found by: 
Mogens Hansen  Software Engineer
MAN B&W Diesel A/S in Copenhagen, Denmark, June 2000 

page 240:
In the code snippet in the middle of the page (implementation of the constructor) we use an interger literal, although we've already defined a symbolic name for the constant value. This is so ugly and should be corrected to: 

template <class charT, class traits>
inbuf<charT,traits>::inbuf()
{
   setg(buffer+ pbSize , buffer+ pbSize , buffer+ pbSize );
}

error found by: 
Allan Stokes   Victoria BC, Canada, June 2000 

page 241:
Our implementation of inbuf::buffer_in() is copying overlapping areas, which is undefined.  We should be using memmove() instead. The code must be corrected to:

template <class charT, class traits>
int inbuf<charT,traits>::buffer_in()
{
  // determine number of putback characters
  streamsize numPutbacks = min(gptr() - eback(), pbSize);

  memmove (buffer + (pbSize-numPutbacks) * sizeof(char_type),
         gptr() - numPutbacks * sizeof(char_type),
         numPutbacks * sizeof(char_type));

  int retval = buffer_from_device(buffer + pbSize * sizeof(char_type),
                                  bufSize - pbSize);
  if (retval <= 0)
  {
    setg(0,0,0);
    return -1;
  }
  else
  {
    setg(buffer + pbSize - numPutbacks,
    buffer + pbSize, buffer + pbSize + retval);
    return retval;
  }
}

error found by: 
James M. Stern,   ITG, Inc., Culver City, CA, April 2001

page 242:
Typo. Section must read:

Again, the error handling in underflow() is oversimplified in that it always returns traits_type::eof() to indicate failure, regardless of the source of the error.

error found by: 
James M. Stern,   ITG, Inc., Culver City, CA, April 2001 

page 245:
The description of showmanyc() could be more precise.  Suggested improvement:

The virtual member function showmanyc() (pronounced “ess-how-many-see,” not “show-manic”) returns an estimation of the number of characters available for input, or -1 . If the returned value is positive, then at least the indicated number of characters can be made available by one or more calls to underflow() . If the operations returns -1 , calls to underflow() and uflow() will fail. The intent is not only to know in advance that these calls will not return traits_type::eof() , but that they will return “immediately.” Or, to put it more simply, the purpose of this operation is to check if characters are available on the external device, which can be read by underflow() or uflow() without waiting.

error found by: 
James M. Stern,   ITG, Inc., Culver City, CA, April 2001 

page 255:
The example of a Greek date format is slightly incorrect: The iota used in the name of the day and the name of the month must be accented using the Unicode character  03AF. Click here for the correct format using ISO-8859-7 character encoding.

error found by: 
Klitos Kyriacou UK, March 2001 

page 272:
Typo in page. Should read:

The reference returned remains valid at least as long as any copy of the containing locale exists. Section 7.3 , Memory Management of Facets in a Locale, explains why this is and how it works.

Typo in footnote. Should read:

4. The facet type money_put<char, string_inserter<char> > is an instantiation of the money_put template for an output iterator other than the default, which is ostreambuf_iterator<charT> and was omitted from the list of template arguments in money_put<char> . ...

error found by: 
Klaus Wittlich, Cologne Germany, December 2000
James M. Stern,   ITG, Inc., Culver City, CA, April 2001
Steve Love, UK, April 2001

page 275:
Typo in page. Should read:

To be more precise, we should say that in every locale there is one representative of each standard facet family. Remember, we mentioned before, at the beginning of chapter 5 , that facet types are organized in facet families, that is, hierarchies of facet classes derived from each other.

error found by: 
James M. Stern,   ITG, Inc., Culver City, CA, April 2001 

page 281:
Typo in the code sample. Must read:

template <class String>
String* compare1toM ( locale loc, String one, String* begin, String* end)
{
  const collate<String::value_type>& collateFacet =
                         use_facet< collate<String::value_type> >(loc);
  String tmpOne = 
          collateFacet.transform(one.c_str(),one.c_str()+one.length());
  for (; begin < end ; begin++)
  {
    String tmpMany = collateFacet.transform((*begin).c_str(),
                                   (*begin).c_str()+(*begin).length());
    if (tmpOne == tmpMany)
      return(begin);
  }
  return (end);
}

error found by: 
Norihisa Kitazawa, Japan, April 2001

page 284:
Missing declarations. Add verbal description:

Correct usage of the conversion functions is not completely obvious from studying their signatures. The following example should help to reveal the subtleties. The example shows a situation where multibyte characters are read from a file (accessible via file descriptor fd ) and then converted to
wide characters via in() . The multibyte characters are read byte by byte from the external file into a buffer. The buffer is an array of bytes, i.e., an array of units of type char. The operating system function read() is used to fill the buffer. The characters resulting from the conversion are wide characters and are accumulated in a wchar_t buffer. The conversion therefore is from the external character type char to the internal character type wchar_t . The type of an appropriate conversion state is assumed to be ConversionState . For error indication there symbolic integral constants defined, namely ReadError , ConversionError , and ResultBufferFull . Here is the source code that does the conversion:
 

Typo in code sample (closing bracket missing). Must read:

if ((readResult = read (fd, readStart, readSize) ) <= 0)
{
  if (readResult = 0)
    err = NoMoreInput;
  else
    err = ReadError;
  break;
}

error found by: 
Klaus Wittlich, December 2000 

page 286:
Error in the signature of close(). Must read:

void close(catalog cat_id ) const;

error found by: 
Norihisa Kitazawa, Japan, April 2001

page 286:
Typo. Must read:

The C++ standard describes how message catalogs can be accessed via the messages facet’s member functions.

error found by: 
Norihisa Kitazawa, Japan, April 2001

page 286:
The section header "Formatting and Parsing Facets" can be misunderstood as talking about  formatting and parsing of facets, while we actually talk about "Facets for Formatting and Parsing".

Change section header on page 286, in the table of contents on page ix.

suggested by: 
James M. Stern,   ITG, Inc., Culver City, CA, April 2001 

page 287:
Suggested improvement:

If the last integer is <= 0 or == CHAR_MAX , the described group is unlimited.

suggested by: 
James M. Stern,   ITG, Inc., Culver City, CA, April 2001 

page 287:
For better understanding break last paragrpah in numpunct section  into 2 paragraphs. Should read:

In Nepal, on the other hand, the first group has three digits and all subsequent groups have two digits, so that the same number, 10 million, is formatted as 1,00,00,000. This grouping is described by a two-element string, where the first element is 3 and the second 2. 
    Please note that an empty string and a string that contains a single 0 describe the same grouping.

suggested by: 
Klaus Wittlich, December 2000

page 288:
Typo. Must read:

For formatting of the numeric value, the put() function takes into account the information contained in numpunct, which is obtained from the locale returned by fg.getloc() , the format flags contained in the ios_base object fg , the fill character fl , and the character classification information taken from the ctype facet contained in the locale returned by fg.getloc() .

error found by: 
Norihisa Kitazawa, Japan, April 2001

page 296:
Typo. Must read:

For example, a call to the first version of put() with a struct tm containing the 25 th of December 1993 and the character sequence "This is %A, day %d of month %B in the year %Y. \n" , i.e. the following code snippet:

error found by: 
Norihisa Kitazawa, Japan, April 2001

page 296:
The call to the time_put facet's put() function in the sample code on the bottom of page 296 is non-portable. The put() function requires two arguments of type const char* in this case. (The pointers denote begining and end of the format pattern string.) We provided string iterators instead of const char* pointers, which works out well in most implementation of string, because the string iterator is typically implemented as a character pointer. However, in general a type compatibility between basic_string<charT>::iterator and const charT* is not guaranteed by the standard. For this reason our code is non-portable and should be corrected as follows: 

 ostringstream oss;
 locale loc("American_USA.1252");
 oss.imbue(loc);
 const time_put<char>& tfac = use_facet<time_put<char> >(loc);
 struct tm xmas = { 0, 0, 12, 25, 11, 93 };
 string fmt("This is %A, day %d of month %B in the year %Y.\n");
 time_put<char>::iter_type ret 
   = tfac.put(oss,oss,' ',&xmas,
    fmt.c_str(),fmt.c_str()+fmt.length() );
 cout << oss.str() << endl;

error found by: 
Mark Rodgers, Cadenza New Zealand Ltd, June 2000

page 298:
Typo. Must read:

get_date() searches for a character sequence that matches a time_put output pro-duced
with the format character x .

error found by: 
Norihisa Kitazawa, Japan, April 2001

page 305:
Inthe diagram the occurrence of  ctype_byname<wchar_t, char, mbstate_t> must be replaced with codecvt _byname<wchar_t, char, mbstate_t>

error found by: 
Norihisa Kitazawa, Japan, April 2001

page 315:
Typo in the name numpunct_byname, appears as numpunct:byname. Must read:

Note that every instantiation of numpunct for a different character type introduces another facet family with its own facet identification. numpunct<char> has the identification numpunct<char>::id , and numpunct<wchar_t> has the identification numpunct<wchar_t>::id , which is a different static variable with a different value. The derived class numpunct_byname<char> shares the identification numpunct<char>::id with its base class numpunct<char> , and numpunct_byname<wchar_t> has the identification numpunct<wchar_t>::id of its base class.

error found by: 
Norihisa Kitazawa, Japan, May 2001

page 316:
Incorrect reference. Must read:

More about the dynamic cast can be found in section G. 8 , Dynamic Cast, in appendix G.

suggested by: 
Klaus Wittlich, December 2000

page 317:
Typo: base_facet appears as base_base. Must read:

use_facet() will find a facet with the facet interface identification base_facet::id in the locale object loc , and the dynamic cast to const base_facet * will be processed successfully, because the facet is of exactly the required type.

error found by: 
Norihisa Kitazawa, Japan, May 2001

page 322:
Typo. Must read:

Note that the base class constructor is called with the value 1 as the initial value for the facet’s refs argument. Such a facet need not be stuffed into a locale object but can be used independently. Here is the sample usage from section 6.4.3:

error found by: 
Norihisa Kitazawa, Japan, May 2001

page 323:
There is a typo in the declaration of the two destructors in the code sample on page 323:

 class base_facet : public locale::facet
 {
  public:
   base_facet(size_t refs=0) : locale::facet(refs) {}
   virtual string bar() { return ”this is the base class”; }
   static ::std::locale::id id;
  protected:
   ~ base_facet() {}
 };

 class derived_facet : public base_facet
 {
  public:
   derived_facet() : base_facet(0) {}
   virtual string bar() { return "this is the derived class"; }
   virtual string bar_2() { return "hello world"; }
  protected:
   ~ derived_facet() {}
 };

error found by: 
Bernd Mohr / Research Centre Juelich, ZAM, Germany, August 2000

page 325:
We explain that locales can be passed by value without introducing substantial overhead, but in all our examples we pass locales by reference. For this reason the first paragraph of the section on the Semantics of Locales should be modified. It should read:

Locales are designed for being passed around by value. As we have seen in the previous section, internally a locale is nothing more than a handle for a container of facets. As a result, copying and assignment of locales are relatively inexpensive and you can safely pass a locale to a function by value (rather than by reference) without risking substantial overhead. 

error found by: 
Bernd Mohr / Research Centre Juelich, ZAM, Germany, August 2000
page 327 & 333:
Typo. There are references to chapter 4 instead of chapter 7. Must read:

on page 327:
Locales and facets form an extensible framework that allows the addition of user-defined internationalization services. Such services can be encapsulated into user-defined facet types, which can have arbitrary interfaces and functionality. In chapter 7 , “The Architecture of the Locale Framework,” we explained that facet types must have the following two properties:

on page 333:
Now we come to the design and implementation of the address facet. In chapter 7 , “The Architecture of the Locale Framework,” we explained that facets must have the following two properties:

error found by: 
Norihisa Kitazawa, Japan, May 2001

page 335:
Typo in the code sample. The public put() function must be corrected to:

void put(OutIter oi,
   const String& firstname, const String& secname, const String& lastname,
   const String& address1,  const String& address2,
   const String& town,      const String& zipcode, const String& state,
   const String& country,   const String& cntrycode) const
{ do_put(oi, firstname, secname , lastname,
         address1, address2, town, zipcode, country, cntrycode); }

error found by: 
Norihisa Kitazawa, Japan, May 2001

page 335:
For performance reasons, prefer prefix increment over postfix increment. Change code to:

void put_string(OutIter oi, String s) const
{
  typename String::iterator si, end;
  for (si=s.begin(), end= s.end(); si!=end ; ++si, ++oi )
    *oi = *si;
}

suggested by: 
Klaus Wittlich, December 2000

page 336:
Typo in the chapter reference. Must read:

See sections 6.3.1.2, The Derived Byname Facets , and 5.1.1, Named Locales, for details about these locale names.

error found by: 
Norihisa Kitazawa, Japan, May 2001

page 338 & 339:
Typos in the code sample. Must read:

template <class charT>
basic_ostream<charT>&
operator<<( basic_ostream<charT>& os, const address<charT>& ad)
{
  locale loc = os.getloc();

  try
  {
    const address_put<charT>& apFacet = use_facet<address_put<charT> > (loc);
    apFacet.put(os, ad.firstname_, ad.secname_, ad.lastname_ ,
    ad.address1_, ad.address2_, ad.town_, ad.zipcode_,
    ad.state_, ad.country_, ad.cntrycode_ );
  }
  catch (bad_cast&)
  {
    // locale does not contain a address_put facet ;
  }
  return (os);
}

error found by: 
Norihisa Kitazawa, Japan, May 2001

page 464:
The description of header <iosfwd> is misleading, because the types streamoff and streamsize   are explained, but not even mentioned there. It should instead read: 

       typedef basic_ios<char>       ios;
       typedef basic_ios<wchar_t>    wios;

       typedef basic_streambuf<char> streambuf;
       typedef basic_istream<char>   istream;
       typedef basic_ostream<char>   ostream;
       typedef basic_iostream<char>  iostream;

       typedef basic_stringbuf<char>     stringbuf;
       typedef basic_istringstream<char> istringstream;
       typedef basic_ostringstream<char> ostringstream;
       typedef basic_stringstream<char>  stringstream;

       typedef basic_filebuf<char>  filebuf;
       typedef basic_ifstream<char> ifstream;
       typedef basic_ofstream<char> ofstream;
       typedef basic_fstream<char>  fstream;

       typedef basic_streambuf<wchar_t> wstreambuf;
       typedef basic_istream<wchar_t>   wistream;
       typedef basic_ostream<wchar_t>   wostream;
       typedef basic_iostream<wchar_t>  wiostream;

       typedef basic_stringbuf<wchar_t>     wstringbuf;
       typedef basic_istringstream<wchar_t> wistringstream;
       typedef basic_ostringstream<wchar_t> wostringstream;
       typedef basic_stringstream<wchar_t>  wstringstream;

       typedef basic_filebuf<wchar_t>  wfilebuf;
       typedef basic_ifstream<wchar_t> wifstream;
       typedef basic_ofstream<wchar_t> wofstream;
       typedef basic_fstream<wchar_t>  wfstream;

       template <class state> class fpos;
       typedef fpos<char_traits<char>::state_type>    streampos;
       typedef fpos<char_traits<wchar_t>::state_type> wstreampos;

page 456:
Instead of including explanations of the types streamoff and streamsize in this section, the corresponding information should be given in the section about header <ios> . The section about header <ios>   on page 456 should  be extended by: 

streamoff is an implementation-defined type which can be constructed from an integral value, can be converted to an integral value, and allows checks for equality and inequality. Usually it is a typedef for one of the signed basic integral types.
streamsize is an implementation-defined type which is a typedef for one of the signed basic integral types. In general it is used to represent the number of characters transferred in an I/O-operation, or the size of an I/O-buffer.

page 638:
This also changes the index:

streamoff type 456
streampos . See also fpos
 typedef, 456

error found by: 
Christoph Koegl, Dept. of Computer Science, University of Kaiserslautern, July 2000

page 487:
There is an open issue in the C++ standard regarding the behavior of getline() in case of failure. 

In the book we write that the character buffer is zeroed out on failure, that is, when the sentry returns false or the sentry constructors throws an exception. The standard does not explicitly say so. An alternative interpretation is that getline() will NOT store a null character in case of failure. Both approaches (storing a null character and not storing it) exist in current implementations. Those implementations that do store a null character on failure only do so when the sentry returns false, but do not store it if the sentry constructor throws an exception.

The issue is still open. The proposed resolutions are listed below:

Proposed resolution 1

"If the sentry constructor exits by throwing an exception, the exception is not caught. If the sentry object returns false, when converted to a value of type bool, the function returns without
attempting to obtain any input. In either case the number of extracted characters is set to 0 and the function's argument is left unchanged."

Proposed resolution 2 

"If the sentry constructor exits by throwing an exception or if the sentry object returns false, when converted to a value of type bool, the function returns without attempting to obtain any input. In either case the number of extracted characters is set to 0; unformatted input functions taking a character array of non-zero size as an argument shall also store a null character (using charT()) in the first location of the array."

error found by: 
Martin Sebor   Rogue Wave Software, Inc., May 2000

page 479:
The descriptions of the default constructor and the init() fucntion of class basic_ios<charT,traits> are incomplete:

basic_ios();
Constructs an object of type basic_ios<charT,traits> leaving its data member  uninitialized. The object must be initialized by calling its init() member function. 
If it is destroyed before it has been initialized the behavior is undefined.
 

void init(basic_streambuf<char_type,traits_type>* sb);

Initializes this so that:

- this->rdbuf()==sb ,
- this->rdstate()==ios_base::goodbit , if sb!=0 otherwise
  this->rdstate()==ios_base::badbit,
- this->exceptions()==ios_base::goodbit,
- this->flags()==ios_base::skipws | ios_base::dec,
- this->width()==0,
- this->precision()==6,
- this->fill()==this->widen(‘ ‘),
- this->tie()==0, 
- this->getloc() returns a copy of the global locale, constructed by
  locale() , and
- this-> iarray and this->p array are null pointers .
 

error found by: 
Angelika Langer,  Trainer/Consultant, Munich, Germany, August 2000 
page 502:
A basic_ostream has seekp and tellp functions, not seekg and tellg   functions. Replace seekg and tellg by seekp and tellp:

POSITIONING
basic_ostream<char_type,traits_type>& 
seek p (pos_type pos);
Repositions this to the location designated by pos , by calling this->rdbuf()-> pubseekpos(pos) . Failures are indicated by the state of *this . Returns *this .

basic_ostream<char_type,traits_type>& 
seek p (off_type off, ios_base::seekdir dir);
Repositions this to the location designated by off and dir , by calling this->rdbuf()-> pubseekpos(off,dir) . Failures are indicated by the state of *this . Returns *this .

pos_type tell p ();
If this->fail()==true , returns pos_type(-1) . Otherwise gets the stream positions by calling  this->rdbuf()->pubseekoff(0,ios_base::cur,ios_base::out) and returns the result from this call.

error found by: 
Bernd Mohr / Research Centre Juelich, ZAM, Germany, August 2000 
page 508:
Minor typos. The title and page header should read:

basic_streambuf<charT,traits > 2

There is blank missing in the definition of traits_type :

typedef traits traits_type;

error found by: 
Allan Stokes   Victoria BC, Canada, June 2000 
Bernd Mohr / Research Centre Juelich, ZAM, Germany, August 2000
Klaus Wittlich, January 2001

page 511:
The argument of the function sputc() is missing. The signatures must be corrected to:

page 511:
int_type sputc( char_type c );
Stores the character c in the put area, e.g. (*pptr()) = c . If the put area does not exist or is full ( i.e. pptr()==0 || pptr()==epptr() ), this->overflow() is called and the result of this call returned. 

error found by: 
Angelika Langer, Trainer/Consultant, Munich, Germany,  August 2000

page 511&513:
There are typos in the description of xsputn(), sputn(), and sungetc(). The signatures and descriptions must be corrected to:

page 511:
int_type sunget c ();
If a putback position is available (i.e. gptr()!= 0 && eback()<gptr() ), the next pointer of the get area is decremented and the element the next pointer is now pointing to is returned. The element is converted to int_type before the return. Otherwise calls  this-> backfail() and returns the result of this call.

streamsize sputn( const char_type* s, streamsize n);
Calls this->xsputn(s,n) and returns the result of this call.

page 513:
virtual streamsize xsputn( const char_type* s, streamsize n);
Writes n successive characters beginning with (*s) to the put area. It behaves like repeated calls to this->sputc() . Writing stops when either n characters have been written or a call to this-> sputc () would return traits_type::eof() . The functions returns the number of written characters.

error found by: 
Angelika Langer, Trainer/Consultant, Munich, Germany,  August 2000

page 512 - 514:
The return type of the functions epptr(), pbase(), pptr(), eback(), egptr(), and gptr() must be char_type* instead of char_type, and these functions are const emember functions. The signatures must be corrected to:

page 512:
char_type * epptr() const ;
  Returns the end pointer of the put area.

page 513:
char_type * pbase() const ;
  Returns the begin pointer of the put area.

char_type * pptr() const ;
  Returns the next pointer of the put area.

page 514:
char_type * eback() const ;
  Returns the begin pointer of the get area.

char_type * egptr() const ;
  Returns the end pointer of the get area.

char_type * gptr() const ;
  Returns the next pointer of the get area.

error found by: 
Allan Stokes, Victoria BC, Canada, June 2000 and 
Angelika Langer, Trainer/Consultant, Munich, Germany,  August 2000

page 516:
The stream buffer's function imbue() is a virtual function and, different from the stream's imbue() function, it does not return anything. The signature must be corrected to:

virtual void imbue(const locale& loc);
Allows an object of a derived class to be informed that the locale of this has changed, by overwriting this function in the respective derived class. basic_streambuf <charT,traits>::imbue() does nothing.

error found by: 
Rajesh Kommu, October 2000

page 549:
The synopsis is entirely wrong; it describes iterator_traits instead of iterator , which is plain wrong The synopsis must read:

    namespace std {
      template<class Category, class T, class Distance = ptrdiff_t,
               class Pointer = T*, class Reference = T&>
      struct iterator {
            typedef T         value_type;
            typedef Distance  difference_type;
            typedef Pointer   pointer;
            typedef Reference reference;
            typedef Category  iterator_category;
      };
    }

error found by: 
Klaus Wittlich, January 2001

page 565:
Section must read:

If ct is the radix separator, i.e., ct == use_facet< numpunct<charT> >loc. decimal_point () , the related character is set to '.' .

error found by: 
James M. Stern,   ITG, Inc., Culver City, CA, April 2001 

page 614 & 615:
These two pages should use the same code sample in the paragraph on SAFE DOWNCAST and THE DYNAMIC_CAST OPERATOR. The code sample should read:

void foo(Base* ptr) 
{
  Derived* dp = dynamic_cast<Derived*>(ptr);
  if ( dp == 0 )
    { /* whatever is appropriate, but do not access any members 
         of the derived class */ 
    } 
  else
    dp->cnt = 0;
}

error found by: 
William Moffatt UK, May 2000

page 621:
This page has a dangling reference to a section that we did not include in the final version of the book. Ignore the last sentence of the following section:

ALLOCATORS C++ strings support different memory allocation models by means of so-called allocators. See box on ”Error! Reference source not found.”

error found by: 
Michael S. Scherotter   Software Architect
Tartus Development, Inc., San Rafael, CA, May 2000 

page 632:
The entry for istream has a typo. It should read:

istream . See basic_istream typedef, 453

error found by: 
Vikram bir Singh, September 2000

page 636 & 639:
The entries for seekp, seekg, tellp, and tellg must be corrected. 

seekg() stream member , 52, 489
seekp() stream member , 52, 502
tellg() stream member, 51, 52, 117, 489
tellp() stream member, 51, 52, 117, 502

error found by: 
Bernd Mohr / Research Centre Juelich, ZAM, Germany, August 2000 
page 640:
The index lacks an entry for unformatted input/output. The following entry should be added:

Unformatted
  input 49-51, 486-488
  output 51,501

error found by: 
Allan Stokes   Victoria BC, Canada, June 2000 

  © Copyright 1995-2008 by Angelika Langer.  All Rights Reserved.    URL: < http://www.AngelikaLanger.com/IOStreams/errata1st.htm  last update: 18 Jul 2008