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:
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;
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 <<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
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
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);
// 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
.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
.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);
// 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
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();
//
return;
}
}
error found by:
Vikram bir Singh, September
2000
page 40:
The first code example on page 40 should read:
ifstream source
;
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(
,
);
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
fstream BiFil("poem.txt",
);
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
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
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()/
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 (
)
{ ostr << i; }
and
ofstream ostr("/tmp/fil");
int i=10;
while (
)
{ 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
sync_with_stdio(false);
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
.
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,
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
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
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
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 (!
eq_int_type(i,Traits::eof()))
// if not, convert it to a character
{ c =
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()
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
,
Refined Inserters and Extractors, demonstrates the correct use of sentries.
page 154:
A concrete example is shown in section
,
Refined Inserters and Extractors.
page 155:
Some of these aspects are demonstrated in the example presented in
section
, Refined
Inserters and Extractors.
page 155:
The inserters and extractors presented in section
,
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);
}
else
{
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.
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
{
...
}
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,
>
basic_ostream<charT,
Traits>& g_inserter
(basic_ostream<charT,
Traits>& os, const Argument&
)
{ ... }
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<
i_;
i++)
os.put(os.widen('\n'));
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>
&
operator<<
(
&
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
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
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 >
int_type
unbuffered_streambuf<charT,traits>::overflow(int_type
c)
{ ... }
page 232:
template <class charT,
class traits >
int_type
unbuffered_streambuf<charT,traits>::underflow()
{ ... }
page 232:
template <class charT,
class traits>
int_type
unbuffered_streambuf<charT,traits>::
uflow()
{ ... }
template <class charT,
class traits >
int_type
unbuffered_streambuf<charT,traits>::pbackfail(int_type
c)
{ ... }
page 237:
template <class charT,
class traits>
int_type
outbuf<charT,traits>::overflow
(int_type c)
{ ... }
page 240:
template <class charT,
class traits>
int_type
inbuf<charT,traits>::underflow()
{ ... }
page 242:
template <class charT,
class 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
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+
,
buffer+
, buffer+
);
}
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);
(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
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 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
,
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
.
...
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
,
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 (
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
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
.
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
)
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
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
, 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
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
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,
);
cout <<
oss.str() << endl;
error found by:
Mark Rodgers, Cadenza New Zealand
Ltd, June 2000
page 298:
Typo. Must read:
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
_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
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.
,
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
*
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
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
,
“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
, “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,
,
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 ;
)
*oi = *si;
}
suggested by:
Klaus Wittlich, December 2000
page 336:
Typo in the chapter reference. Must read:
See sections 6.3.1.2,
, 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.address1_, ad.address2_, ad.town_, ad.zipcode_,
ad.state_, ad.country_,
);
}
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
streampos
. See also
fpos
typedef,
error found by:
Christoph Koegl, Dept. of Computer
Science, University of Kaiserslautern, July 2000
page 487:
There is an
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>
void init(basic_streambuf<char_type,traits_type>* sb);
Initializes
this
so that:
-
,
- 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
-
.
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
(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
(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
();
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(
);
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
();
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()
returns the result of this call.
streamsize sputn(
char_type* s, streamsize n);
Calls
this->xsputn(s,n)
and returns
the result of this call.
page 513:
virtual streamsize xsputn(
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->
()
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()
;
Returns the end pointer of the put area.
page 513:
char_type
pbase()
;
Returns the begin pointer of the put area.
char_type
pptr()
;
Returns the next pointer of the put area.
page 514:
char_type
eback()
;
Returns the begin pointer of the get area.
char_type
egptr()
;
Returns the end pointer of the get area.
char_type
gptr()
;
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:
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.
()
,
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 (
)
{ /* 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.
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:
error found by:
Vikram bir Singh, September
2000
page 636 & 639:
The entries for seekp, seekg, tellp, and tellg must be corrected.
seekg()
,
52, 489
seekp()
,
52,
tellg()
stream member, 51, 52, 117, 489
tellp()
stream member, 51, 52, 117,
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
|