Modified May 17, 2010.
This is errata for Programming: Principles and Practice using C++.
Comments, improvements, bug reports, etc. are welcome.
I list both corrections and clarifications. There is essentially no problem that I consider too small to list, so you might find many pieces of errata too minor to bother with (I know because I have received email to that effect), but at this stage, I'd rather not make decisions about what an unknown reader will find bothersome. Please note that the number of errata does not equal the number of errors. I say this because I have seen the book condemned unread because the number of errata.
Big issues, such as "why don't you use XXX for your GUI?", "please add two more chapters on the STL", and "please use C++0x features to simplify the code" are not errata but considerations for future work and will not appear here.
Different people have different preferences for sorting errata: in chronological order, in page order, each printing separate, all printings merged, etc. However, I can't manage multiple organizations, so what you get is what seems to be most useful for most people.
At the request of repeat visitors to the page, I have started to add dates of posting of individual errata. If an errata is changed, so is its date.
As an abbreviation I use, s/before/after/ to mean replace "before" with "after".
This is the errata to the first printing of the book. It was applied to produce the 2nd printing.
Table of contents
Chapter 0
Chapter 1
Chapter 2
Chapter 3
Chapter 4
The string with no characters "" is called the empty string.
Chapter 5
Write a program that reads and stores a series of integers and then computes the sum of the first N integers. First ask for N, then read the values into a vector, then calculate the sum of the first N values. For example: Please enter the number of values you want to sum: 3 Please enter some integers (press '|' to stop): 12 23 13 24 15 | The sum of the first 3 numbers ( 12 23 13 ) is 48
Chapter 6
cout << "Please enter expression (we can handle +, -, *, and /)\n";
cout << "add an x to end expression (e.g., 1+2*3x): ";
int lval = 0;
int rval;
char op;
cin>>lval; // read leftmost operand
if (!cin) error("no first operand");
while (cin>>op) { // read operator and right-hand operand repeatedly
if (op!='x') cin>>rval;
if (!cin) error("no second operand");
Chapter 7
class Token {
public:
(to exactly match pg 182).
Chapter 8
double x(y); // initialize x with y (see sec8.2.2)
Chapter 9
Chapter 10
Chapter 11
fs.seekg(5); // move reading position ("g" for "get") to 5 (the 6th character)
char ch;
fs>>ch; // read and increment reading position
cout << "character[5] is " << ch << '(' << int(ch) << ")\n";
fs.seekp(1); // move writing position ("p" for "put") to 1
fs<<'y'; // write and increment writing position
Chapter 12
poly_rect.set_fill_color(Color::green);
Chapter 13
Chapter 14
Chapter 15
Chapter 16
Lines_window::Lines_window(Point xy, int w, int h, const string& title)
:Window(xy,w,h,title),
next_button(Point(x_max()-150,0), 70, 20, "Next point", cb_next),
quit_button(Point(x_max()-70,0), 70, 20, "Quit", cb_quit),
next_x(Point(x_max()-310,0), 50, 20, "next x:"),
next_y(Point(x_max()-210,0), 50, 20, "next y:"),
xy_out(Point(100,0), 100, 20, "current (x,y):"),
color_menu(Point(x_max()-70,30),70,20,Menu::vertical,"color"),
menu_button(Point(x_max()-80,30), 80, 20, "color menu", cb_menu)
{
Chapter 17
Chapter 18
struct X { // simple test class
int val;
void out(const string& s, int nv)
{ cerr << this << "->" << s << ": " << val << " (" << nv << ")\n"; }
X(){ out("X()",0); val=0; } // default constructor
X(int v) { out( "X(int)",v); val=v; }
X(const X& x){ out("X(X&)",x.val); val=x.val; } // copy constructor
X& operator=(const X& a) // copy assignment
{ out("X::operator=()",a.val); val=a.val; return *this; }
~X() { out("~X()",0); } // destructor
};
for (double* p = &ad[10]; p>&ad[0]; --p) cout << *(p-1) << '\n';However, you can't just substitute in that version because then the text would be wrong.
Chapter 19
template<class T, class A>
void vector<T,A>::reserve(int newalloc)
{
if (newalloc<=space) return; // never decrease allocation
vector_base<T,A> b(alloc,newalloc); // allocate new space
for (int i=0; i<sz; ++i) alloc.construct(&b.elem[i],elem[i]); // copy
for (int i=0; i<sz; ++i) alloc.destroy(&telem[i]); // destroy old
swap< vector_base<T,A> >(*this,b); // swap representations
}
with
template<class T, class A>
void vector<T,A>::reserve(int newalloc)
{
if (newalloc<=this->space) return; // never decrease allocation
vector_base<T,A> b(this->alloc,newalloc); // allocate new space
for (int i=0; i<this->sz; ++i) this->alloc.construct(&b.elem[i],this->elem[i]); // copy
for (int i=0; i<this->sz; ++i) this->alloc.destroy(&this->elem[i]); // destroy old
swap< vector_base<T,A> >(*this,b); // swap representations
}
(I forgot - and forgot to mention - that "this->" is required when accessing a member of a template base class of a
template class.
Not all compilers enforce this rule. When you re-test, re-test on every compiler you use.)
Chapter 20
if (h<jack_data[i]) jack_high = &jack_data [i]; //save address of largest elementby
if (h<jack_data[i]) {
jack_high = &jack_data[i]; //save address of largest element
h = jack_data[i]; //update "largest element"
}
if (h<(*jill_data)[i]) jill_high = &(*jill_data)[i]; //save address of largest elementby
if (h<(*jill_data)[i]){
jill_high = &(*jill_data)[i]; //save address of largest element
h = (*jill_data)[i]; //update "largest element"
}
if (h<v[i]) jill_high = &v[i];by
if (h<v[i]) {
jill_high = &v[i];
h = v[i];
}
if (d.line.back().size()) d.line.push_back(Line()); // add final empty line
Text_iterator& Text_iterator::operator++()
{
++pos; // proceed to next character
if (pos==(*ln).end()) {
++ln; // proceed to next line
pos = (*ln).begin(); // bad if ln==line.end(); so make sure it isn't
}
return *this;
}
Text_iterator end() // one beyond the last line
{ return Text_iterator(line.end(), (*line.end()).end()); }
with
Text_iterator end() // one beyond the last line
{
list<Line>::iterator last = line.end();
--last; // we know that the document is not empty
return Text_iterator(last, (*last).end());
}
Text_iterator find_text(Text_iterator first, Text_iterator last, const string& s)
{
if (s.size()==0) return last; // can't find an empty string
char first_char = s[0];
while (true) {
Text_iterator p = find(first,last,first_char);
if (p==last || match(p,last,s)) return p;
++first; // look at the next character
}
}
if (size()==capacity()) reserve(2*size()); // make sure we have space
with
if (size()==capacity()) reserve(size()==0?8:2*size()); // make sure we have space
*(begin()+offset) = val; // "insert" val return pos;with
*(begin()+index) = val; // "insert" val return pp;As I said: always re-test even after the slightest change - in this case I renamed local variables, but didn't re-test until later.
Chapter 21
if (yy<xx) return false; // y<x } if (x.length()==y.length()) return false; // x==y return true; // x<y (fewer characters in x) } };
Chapter 22
Chapter 23
Chapter 24
Chapter 25
unsigned char right = val&0xff; // rightmost (least significant) byte unsigned char left = val>>8; // leftmost (most significant) byte
Chapter 26
Chapter 27
Appendix A
struct Base {
int mb;
Base(int i) : mb(i) { }
};
struct Derived : Base {
int md;
Derived(int y) : md(y) { } // error: forgot to initilize Base
Derived(int x, int y) : md(y), mb(x) { } // error can't initialize base member from derived constructor
Derived(int x, int y) :Base(y), md(x) { } // ok
};
An initializer used to initialize a base is class a base initializer or base-class initializer.
Appendix B
Appendix C
Appendix E
Glossary
Bibliography
Index