C Books and C++ Books You Don't Want !
Copyright © 1998-2012 All rights reserved
by Yechiel Kimchi
The Age of Disinformation
- Science
School-Books.
The text begins:
"Did you ever get the feeling that what
you learnt in science class at high school was just plain wrong?
Did you feel stupid because you couldn't understand
what the textbook was getting at?
Did you get a question wrong even when you'd faithfully
applied the right formula?
Well, turns out you might have been right all along."
Oops... The above link died.
Here is a
local copy found by the help of
Google cache.
- Teach yourself programming
in Ten years!
(Hebrew)
Feb. 10, 2011
- Bad Books about C and C++: Please read
a review of a specific book and a general comment.
(June 2, 2008)
This page is continuously
This page owes its existence to my frustration of not having good books
in Hebrew for teaching the C and C++ programming languages.
I really wish there were good books in Hebrew for those who are interested
in studying C and/or C++. Alas, I haven't seen one.
It is truly unfortunate.
Meanwhile, many of my students approached me, asking my opinion about
some books in English. Not surprisingly, there were bad books among them too.
Then, I have decided that when I have an opinion about a book,
not necessarily in Hebrew, I will put it here - for the benefits of my students
and any other interested person. Obviously, I am limited to the books
that I can, at least, leaf through.
My sources are: The bookstores at the Technion and the University of Haifa,
books that are sent to me by publishers,
and books that are shown to me by students.
Books that I look at are divided to three categories:
- The good ones (even "relatively good") - find their way to my
C and C++ sources as a reference book,
or as a text book at my Text Book List
(each has a comment,
stating strengths and weaknesses).
- The bad ones - find their way here. I do not really read them,
because I have specific criteria that make a book bad
to my view - usually, exemplifying that the author (or whoever
wrote a particular part of the book) has a misunderstanding
of the programming language at question, or a misconception
of basic programming techniques in that language.
Then, I exemplify my findings with quotes from the book.
Let me emphasize that the only reason I put books here,
is to warn my students from learning from them - I consider these
books a "risk" to my students' grades, if they base their
answers at the exam on these books.
By the way, even the list of bad books in Hebrew is not complete.
I have listed the most commonly known books (at least among
the students that I meet), because I did not have the time
to list EVERY BAD BOOK. I hereby announce, that every book in Hebrew
about C and/or C++ that I have seen - belongs to this category.
Sorry.
- All others, I just do not mention - they are not good enough
to be recommended, and I have not found reasons which are
good enough to justify public denunciation (namely,
they are not that big "risk" to my students).
A few tips for choosing a textbook
in C or in C++.
Disclaimer:
The following is given as a service to my students in C and C++ courses,
and to anyone interested in studying these programming languages.
The opinions below are solely mine, and represent what I have learned
about high quality programming (from my own experience, and by learning
from many others). If you think I am mistaken in any of the items below,
please inform me
- and I will correct it (if you are right).
Notes:
- New books are added to the list whenever I have the time.
- I have a long list of comments on each book.
I have given you only a few examples.
- The errors I have found were not found by reading the books,
but by leafing through them - there must be many more
that I have not found.
- Some of the books may have updated editions.
I hope they have corrected some of the errors.
Nevertheless, it would not change my opinion about the books,
since I do not comment on typos or overlooked errors.
My comments refer to basic knowledge of the programming
languages and to basic knowledge of programming techniques.
If the authors want to write a good book, they should
not rewrite the old one - they should start from scratch.
Introduction
Bad books on C and C++ (as well as on any other subject)
exist in any language that has such books - not just in Hebrew.
But I care for the students in Israel, so I comment on books that are
available in Israel - mainly in Hebrew and in English
(sorry, I do not know Russian, however, several books in Russian that I have
seen are translations of books that appear on this list ;-).
Indeed, I have not found ANY book in Hebrew (about C or C++),
that I thought was good enough to recommend. On the contrary, they are
bad enough to cause my students to loose valuable points in their exams -
if they use these books to learn these languages.
If you know about a good book in Hebrew, I'll be delighted to hear about it
(but if it is not good, it will be added to this list of examples).
The only good thing that I can say about these books is that, overall,
they are correct with respect to the syntax of the languages (well,
I believe that their examples were correctly compiled ;-), but you will be
able to see that even in syntax the books can be improved in one or two things.
Regarding syntax, it is my opinion that knowing the syntax of a programming
language is just about knowing 5% of what is to be learnt about it.
Some of the bad books in Hebrew, are just translations of bad books in other
languages (see below) - it is impossible to introduce conceptual errors
while translating.
For obvious reasons, only a small selection
of foreign literature (mostly in English) on C and C++
is available in Israeli bookstores. Unfortunately, these books are not always
the best choice in their classes (to say it mildly) - and some very good books,
on the other hand, are hard to find.
The interested people should either order them personally from a bookstore,
or use the Internet in order to purchase them. Books that
I recommend
are only those that I personally read - though not always cover to cover.
My prefered text-books are on
a separate page.
See a few references at the bottom of this page.
General Remarks about Bad Books
(not necessarily in Hebrew)
-
Many of the books do not care about the standard (ANSI), either for
C or C++. They do refer occasionally to the standard,
but in their examples or subject matter, they never make
a clear distinction between what is standard and what is not.
In all cases I have noticed, they refer to the PC system and compilers
(e.g, the size of an int is always two bytes).
-
The books do not care about teaching good programming style.
Wherever I look, I see too many global variables, functions
which are too long, and ill-defined interfaces of various kinds.
-
In most cases, each book has its own style of program writing,
and it is very hard to understand the structure of a code
from the indentation. There seems to be a significant positive correlation
between books that use explicitly structured and well indented code
(usually, a minor variation on K&R style), and books that exemplify
good programming style.
-
Too many books, even some that are otherwise reasonably good,
use the type float instead of double.
There is no reason to use float, unless you have
millions of them, and you need to save memory
on the expense of accuracy. Note, however, that according to the standard
these types may be identical - so you may gain nothing.
(When using external libraries, however, you should be aware of the fact
that they may use the type float,
whether justifiably or not, in their API,
and you should find the right way to adapt your software to it.)
The type double is the C native type
for floating point numbers, which is the reason why you should
use it as your default choice. For example, the comparison
x == 3.7
is guaranteed to succeed if you had
double x = 3.7; before
(see K&R2, p.198, A6.4, first sentence, that it always works).
But it is not guaranteed to succeed if you had
float x = 3.7;.
The latter will surprise novices, which good textbooks should avoid.
(Yes, I know, floating point comparison should be done with
epsilon, but how do you show to second-week C students
the way to solve a quadratic equation ?)
(for more information look at GNU's page about
non-bugs in gcc
and role down to (search for) floating point. They also direct
you to David Goldberg's paper
What Every Computer Scientist Should Know About Floating Point
Arithmetics
(PDF, and a local
compact PS)
-
Too many books, even some that are otherwise reasonably good,
use the C MACRO assert() for sanity checks
as part of the regular code. This is in contrast to the way
assert() is #defined,
and may jeopardize using assert() for what it meant
to be: A DEBUGGING AID.
To make a long story short, suppose such a software is compiled
with the definition of NDEBUG set on (e.g, with the flag
-DNDEBUG set while compiling under gcc),
then the resulting executable is no longer valid.
Moreover, any "guards" that will be put in the source-code
to prevent such hazardous compilation - will prevent using
assert() for REAL debugging.
Yet, the real problem in using
assert() is its behaviour, which is to
shut your program off.
I am sure you would not like to hear the following announcement during
a trans-Atlantic flight:
"Ladies and gentlemen, this is your captain speaking.
You are kindly adviced
that our plain is going to ditch in the
Atlantic Ocean. The computer system crashed
after my co-pilot
had entered an impossible value for our latitude."
Read someone else's
opinion about that matter.
(June 2, 2008)
For a typical good review
about a bad book
look here.
(June 2, 2008)
My reviews on the Internet
Wrong Information on the Web is also too Common
(Oct. 6th, 2012)
- Reading the information on
this page reveals that the publisher (who sells e-books)
is ignorant about basic features of C++ (and C).
- This is an example of
a "professional" discussion page, where the participants are clueless
about the basics of C and C++.
- Here is a good
discussion page that denounces the above pages.
Books in English
Herbert Schildt:
Any Book on C or C++ .
Why ?
Read this (Q-16, temporary link)
A future substitute -
html version (different numbering, I did not check it yet
Sep. 28, 2006)
Read an example-review for
a specific book.
(June 2, 2008)
I. Pohl:
Object-Oriented Programming Using C++
1997, 2nd ed. Addison-Wesley Longman
Why ? Read
this review.
(June 2, 2008)
H. M. Deitel & P. J. Deitel:
C++ How to Program,
3rd ed. 2001, Prentice-Hall
This book used to be on my
Text Books page,
but I have always been hesitant about it. That book had the
longest comment on it, and as mentioned in my
comments page
the shorter the comment is, the better I think of a book.
The next paragraph is the original comment that I wrote for this book.
My decision for including this book in my text-books page was that
despite the shortcomings of it, it was not completely bad
as many others, and most of all there were very few good books
in the market. I may regret about my past decision in the future,
but given the fact that nowadays there are a few more good books
about C++, there is no doubt in my mind that it is now the appropriate
time to put this book where it belongs - the bad-books section.
- This is the original comment:
"C++ How to Program"
may help novices in C++
(especially when they lack previous programming experience,
or even if they have no C background).
Indeed, it combines very thorough explanations for basic constructs
in C++ with a touch of more advanced features of the language.
In addition, it gives many DO and DON'T rules,
illustrated by many programming examples.
Unfortunately,
despite the
authors'
prominence
a few of the rules are misleading (or plainly wrong) -
which novices cannot detect them.
On top of that, many of the code examples are not of high quality
(to put it mildly).
Here are a few examples:
- General:
- assert is used for algorithmic error detecting
instead of for debugging only. This is a serious error,
common to many, otherwise good, books. But here it is very
widely used.
- In many classes, data members are assigned in constructors,
rather than being initialized.
This should be considered
a potential bug (and sometimes it is indeed a syntax-error)
and is almost always a redundant (sometimes severe) overhead.
- Here is a (partial) list of comments about
class String, pp. 487-492:
- The two general problems, mentioned above, are exemplified.
- Relational operators ( ==, >, etc.) are asymmetric.
{ char *s = "abc";
String st(s); // Try their class String
bool t1 = st == s, // o.k.
t2 = s == st; // syntax error
}
- operator! is defined - which is nice.
But, in that case, operator bool
should be defined. Otherwise you will need
{ String st("abc");
if (!st) { // Is String empty ?
// .....
}
if (!!st) { // Is String NOT empty ?
// .....
}
}
Once operator bool is defined,
there is no need
for operator!
- Had setString returned
a char * value, it could have been used
in initialization list for the class constructors.
- operator<< uses
a magic number
with an unreasonable value.
- main() is 72 lines long.
Want to read
additional review (by someone else) ?
And finally, the authors do not reply to e-mail sent to them,
concerning the quality of the book. Makes one wonders ...
Alan R. Neibauer: Your First C/C++ Program 1994,
ISBN-0-7821-1414-8
A Hebrew translation from English, by Ronen Eliav.
This one seems to be the worst C/C++ book
ever translated to Hebrew :-(among the ones I have seen ;-)
and one of the worst on this list.
The following are direct translations from the Hebrew edition of
the book, and I hope it is not far from the original text in English.
The meaning of the content in Hebrew was preserved in full.
The book claims that it teaches C and adds (special, boxed, Y.K.)
comments that are relevant for C++. Most of citations below
were taken from such "C++ Comments".
-
P. 9, C++ Comments:
"Later on, you will learn that C++
is a kind of improved version of the C language.
It means that if a C compiler can compile your program,
so will a C++ compiler."
What ???
(*)
-
P. 11, C++ Comments:
"Remember that all information included in this book
is related to both the C and C++ languages.
Instead of explicitly mentioning C/C++ again and again,
we shall usually refer to the C language only.
It does not mean that you learn the C language only -
you learn both languages at the same time."
-
P. 17, What the C Language Can Do for You,
and What It Cannot Do:
"... and once you have learn the C language,
the transition to the C++ language is easy and simple."
-
P. 24, C++ Comments:
"The C language and the C++ language
have identical structure. Once you learn how to write programs
in C, you will know how to write programs in C++."
-
P. 27:
- It says that return is a function
-
P. 251, C++ Comments:
All that the book has to say about classes in C++
is exemplified in an example that is less than one page long.
What I have to say about it, I have already said
somewhere else.
Here, let me put it as politely as possible:
DO NOT BELIEVE ANY OF
THE STATEMENTS ABOVE.
(*) There are MANY reasons that make a
strictly conforming C program
an illegal C++ program.
Here is a very simple one, that after making it C++ correct
(e.g, replace `new' by `New')
will produce different output!!!
#include <stdio.h>
int
main()
{
int new = sizeof('a');
printf("sizeof('a') = %d\n", new);
return 0;
}
I have dealt with such books on my
ChoosingBooks page.
You'll be delighted to see also
what B. Stroustrup has to say about it.
Michael Smith:
Object-Oriented Software in ANSI C++
2nd ed. Publisher: McGraw-Hill .
Read
my review (more general
(
older version)
link
June 2, 2008)
for ACCU.
- P.59: The Chapter on Classes precedes the Chapter on Functions.
- P.64: No initializations in a Ctor.
- P.65: Bad coding-style at Account::withdraw(). (test yourself:
think about both the function and its environment):
float Account::withdraw( float money )
{
if ( the_balance-money >= the_min_money )
{
the_balance = the_balance - money;
return money;
} else {
return 0.0;
}
}
- P.100: Uses #ifdef protection
for implementation-file
- P.130: Uses exceptions, which are introduced 90 pp. ahead.
- P.257: What can be virtual and what cannot:
On top of redundancy,
it forgets static functions.
- P.325: A Ctor with two parameters (and no default value(s))
is declared explicit
- P.402:
- Declare cin as a local variable
- Uses the type istrstream,
which is designated depreciated.
- The while loop control is
buggy.
- P.415: A full Chapter-26
Using legacy C++ compilers.
I think it is appropriate to cite the Rational
for the C-Standard:
"Existing code is important,
existing implementations are not."
- P.468: References: Only four references
This may explain the author's poor knowledge.
The fact that B. Stroustrup's book is there
does not guarantee that it has been read
Angela B. Shiflet:
Problem Solving in C++. Publisher: PWS.
- There is hardly inheritance in the book.
- P.537, P.768 Talking about overloading operator=
(which is so important) in so few words, without a single
example, or any reference to an example.
- P.810 Using assignment in constructor
(rather than initialization).
- P.811 Funny
code:
boolean_t list::ListIsEmpty(void)
{
return (head == NULL ? TRUE : FALSE);
}
I am NOT going to tell you
how this code should have been written.
But there are AT LEAST three (in fact
) different things
that should not have been here
(either wrong or very bad style).
J. Hennefeld & C. Burchard:
Using C++. Publisher: PWS.
- There is hardly inheritance in the book.
- There is hardly overloading in the book.
- P.159 C style for loops.
- P.533 void main()
- If you want to know why it is important to use
int main() please look
at Steve Summit's C-FAQ
11.14a
11.15
- P.533 A List is built, consisting of
links only,
and without supporting functions.
- P.546 A list template is presented,
only interface - no implementation.
- P.645 Examples of functions:
- The code is sloppy even by C coding standards
(by no means this is a criticism of C, nevertheless,
C++ has more constructs for better coding).
This means that the authors are not even aware of the
constructs available in C for good coding style.
- The function round()
has a BUG
Steven C. Lawlor:
Computer Science with C++. Publisher: PWS.
- NO inheritance at all.
- NO overloading
in the index (probably none at all).
- P.240 class Employee
with public
data.
- P.240 Constructor uses assignments, not initializations.
SAMS Teach Yourself:
C++ in 21 days. Publisher: SAMS.
- Above all
I strongly object to the title of the book
that too many people will take seriously.
See what Marshal Cline has to
say about that.
- P.363 - 365 class String
- No initializations in Ctors
(and also in many other classes).
- Code duplication in operator=
and copy Ctor.
- Funny Dtor
- The two (correctly set) operator[]
suffer from code duplication AND bad coding style.
- Code duplication for operator+
and operator+=
- operator+= returns
void AND bad coding style.
- operator+ is not symmetric
(using friend is unnecessary,
and nevertheless, friend
is introduced much too late).
- The type for the length of the string
should have been defined using
typedef
(because it is
not an int).
- P.366 In function main()
- Clumsy code.
- Why there is no operator<<
for class String ?
- P.445 The Shape class hierarchy
is a design error
in various aspects.
- P.482 class Employee uses
getFirstName(), setFirstName() etc.
instead of using function overloading.
- P.517 class String (again)
with two versions of operator+,
which are ambiguous (AND code duplication).
SAMS Teach Yourself:
C in 21 days. 5th ed. Publisher: SAMS. ISBN 0-672-31766-4
Read
my review (more general) for ACCU.
Still Under Construction.
A reader review I had sent to
Amazon
- I will soon add coding examples (the following are comments on a previous edition).
- Above all
I strongly object to the title of the book
that too many people will take seriously.
It takes at least two weeks learn and understand
the full syntax of C and its intended meaning.
But you are definitely NOT a C programmer, yet.
Having experience in other languages, may shorten the time
for understanding the syntax, but then, you will have
to unlearn quite a few things before you become
a C programmer.
See what I have said before.
- The book is full of errors, I'll give you a (short) list
of examples in the near future.
- (from an older edition) P. 572 - 575 The following two are
enough to disqualify a book about C
:
- Using magic numbers instead of
using #define.
- Using the library function gets()
instead of fgets().
Greg Perry:
C by Example. Publisher: Que [for Macmillan USA].
ISBN 0-7897-2239-9
Read
my review (more general) for ACCU.
Still Under Construction.
A reader review I had sent to
Amazon
- I will soon add coding examples.
Jeff Alger:
C++ for Real Programmers. Publisher: AP professional.
ISBN 0-12-049942-8
- First of all
I strongly object to the title of the book.
The good news about it is that
the title for the first edition was even worse,
"Secrets of the C++ Masters".
- Ch.1 "Why yet another book about C++ ?"
is pretentious as it sounds:
"... There are 2,768,942 books about C++ and 2,768,940
of them are either for beginners, or about specific compiler,
or just about the syntax of C++ ...".
Well, I'll give the author the benefit of a doubt that
for the other two books, he refers (besides his own book)
to B. Stroustrup's book.
So what about the books by M. Cline, S. Meyers,
M. Henricson & E. Nyquist (to name a few) ?
[ more info]
One thing is true, though, there are only a handful of good
books about C++, BUT this one, despite some good things in it,
is NOT at the top of the list (to put it mildly).
Once you realize that the author is from Microsoft Corporation,
things start to clear up: Isn't it the way they always do it,
down there at M$ ? ["Mirror, mirror, tell me who else
is ..."].
- P. 52: If the author is so sure he addresses his book
to those who already know well the basics of C++, how come
he makes two beginners mistakes at a single class ?
At class String:
-
the constructor initializes a pointer to a trivial value
(NULL), only to start working on it at the body
of the constructor. To my view, it is
worse than not initializing the pointer at all,
since it gives the illusion that
it is a well built constructor.
-
How come operator=() is protected against
self assignment by a primitive method (which is, I admit,
the way I teach my C++ beginner students), and not
the better way (see, for example, M. Cline's book
C++ Programming FAQs).
- P. 192:
There is a typo (two lines at the top of a function are
duplicated). This teaches me one thing, and makes me
suspect of another one:
- Examples were not compiled
- Is it the case that the author has been trapped
into a bug of (his own company's) M$-Word ?
I have no idea which programming language was used
for M$-Word and alike, but based on my minimal
experience with M$ products, I am quite sure I do
not want to learn the way THEY program.
- Read another (not so friendly)
review, from ACCU.
It says that the section about smart pointers, and alike,
is very good. I trust the reviewer, Francis Glassborow,
and he has said it about the 1st edition. Nowadays,
there are other good sources for such things, and the
reviewer main claim is that the book has not come any better
from first edition, and is dated in quite several respects.
Kris Jamsa:
Rescued by C++ .
Translation to Hebrew: Shmuel Ben-Tolila
Publisher: Hod-Ami.
- All over the book it uses void main()
- P.220, final example before conclusion,
class dog has
public
data.
- P. 248, class string
- It uses magic numbers.
- operator+ returns void
(and so does operator-).
- P. 250, still class string,
additive operators return char *,
thus allowing unrestricted access to private data.
- P.269, Ctor for class employee
- Assignments instead of initializations.
- magic numbers.
- No overloading for operator<<.
- P.270, Assignments in Ctor for class manager.
- P.272, class book
inherits from
class library_card.
- P.375-7, it recommends using
MACRO.
You will be delighted
to read
a review about another book, by the same author.
Leen Ammeraal:
C++ for Programmers 3rd ed. Publisher: Wiley.
ISBN 0-471-60697-9
Read
my review (more general) for ACCU.
Still Under Construction.
- P. 25: "If we use i++ or ++i
only to increment i, ignoring the values of these
expressions, it does not matter which form is used: ..."
Not quite true:
overloading the postfix operator is, usually, done
using a temporary, while a temporary is not needed
for the prefix version. In some cases the postfix version
is a performance burdon.
- P. 51: Does not teach testing successful input.
An example of
while (cin >> i, i > 0) is given
but
while (cin >> i && i > 0) is
much much much better.
- P.121(top): int minimum(const int a[], int n)
"Note that the array length is omitted in a[];
if we had written it, then it would necessarily have been
a constant, which would have made the function
less general and elegant."
Do not believe any word of it.
- P.145(bottom): "We can write either of the following
two line to achieve this:"
int a[2][3] = {{60, 30, 50}, {20, 80, 40}};
int a[2][3] = {60, 30, 50, 20, 80, 40};
but there is no explanation about (the more common situation)
where these two styles of array initializations
are not equivalent.
- P.180: Claims that all assignment operators must be
overloaded by member functions. This contradicts
Stroustrup's 3rd (11.2.2). Indeed, Ammeraal conforms
with the literal reading of the C++ Standard,
but it seems the wording of the standard is not
what the committee intended (and will probably be corrected).
- P.196: How to get over the possibility of self-assignment?
The author prefers the inferior option
(see
C++ Programming FAQs).
- P.197: Implements private operator=
and copy-Ctor as no-op.
- P.205 (bottom): "If B is a base class
from which D is derived ... a reinterpret_cast
is required for the conversion from B* to D*."
This is a serious mistake.
Almost every non-toy C++ program
will crash if the above advice is followed.
- More to come.
David Collopy:
Introduction to C++ Programming - A Modular Approach
Publisher: Prentice Hall.
ISBN 0-13-888801-9
A tentative review that will appear at ACCU reviews:
Introduction to C++ Programming - A Modular Approach
----------------------------------------------------
by David M. Collopy
[Pub. Prentice Hall, ISBN 0-13-888801-9, @ ? ukp]
Reviewed by: Yechiel M. Kimchi
NOT RECOMMENDED
---------------
The subtitle of the book "A Modular Approach" made me think
it was related to the didactic approach of the author,
of how to teach C++.
I was really waiting for this book to arrive
- but I was disappointed. By "modular approach",
the author means "programming in the module-paradigm".
Here is how the author uses the module-paradigm in practice:
The last big example in the book (Chapter 15, p. 557)
is a six-page long program about files updated with
course-data. It has global variables for two files,
a global struct-variable for courses and several
more global variables. Then, about ten utility functions
are all declared to have no arguments and no returned values
(all are typed as "void f(void)"). As the cherry on the pie,
main() is in the same file, hence, there is not even
a minimal attempt to create a genuine, old-style module
(static variables, as well as multi-file programs are
unheard of in this book). Does the program use ANSI-C++ ?
Not in the least!
It #includes <conio.h>,
main() defaults to int (i.e, no return type
is mentioned at main() definition),
and the following statement opens a file (p. 558):
keyFile.open("a:course.key", ios::out));
Yes, the excessive ')' is there.
The only positive thing that I can say about the book
is that the author does not hide its shortcomings.
On the contrary, it actually advertises them (Preface, p. v):
"This book uses a procedural or non-object-oriented approach
to learning how to program in C++. ...
Topics excluded are object-oriented programming, classes,
inheritance, unions, functions and operator overloading,
virtual functions, polymorphism and related items."
Let me add that the term "template" appears once in the text
and once in the index,
but not in the sense you would expect it in a C++ book.
The author claims that the book stresses
"... programming for business applications." (page iii).
The following text, taken from page v, explains something
about the author idea of business programming:
"Essentially, local variables are used to build applications
... for retail sales. Global variables, on the other hand,
are often used to construct corporate applications
that are developed and maintained by in-house programmers."
I am sure that regular visitors of ACCU reviews
already know what should be said about global variables.
However, for the sake of novices let me cite Marshal Cline,
the author of "C++ FAQs":
"Global variables: Just Say No!"
and, regarding naming conventions,
"The names for global data begin with //"
Let me conclude by briefly mentioning that almost
every program example in the book is preceded
by flow-charts describing its activities.
The program example mentioned above is preceded by five pages
full of thirteen flow-charts.
It is not that flow-charts are evil, but they are dated
and used only at the very low-level programming.
Modern modeling languages like State-Charts or UML,
together with pseudo-code for low-level activities
are more appropriate for contemporary programming tasks.
The excessive use of flow-charts gave me the feeling
that I was reading a book about programming in Basic
that was translated to C++.
Not recommended.
Books in Hebrew
Meir Kelech:
Data Structures implemented in C and C++ Opus, 2001.
(March 1st, 2006)
- P.329:
Implementation of operator+ for Matrix
is over 60 lines long (not including comments).
Above all, it returns Matrix*,
which is a design error (the fact that the author
wants to prevent a copy of a Matrix is not an excuse
- he should have sought a different solution).
- P.213-215:
When implementing a binary-tree in C++, node
is implemented as a struct without methods.
Leaving aside whether its structure should be public
(it should not - think of making it an AVL-tree),
not using methods leaves the implementation in a C-style.
- P.213 onward:
The author uses throw false
in variouse places.
I do not ignore the fact
that he never throws true
but The main thing is that he completely misses
the idea of exceptions.
- P.217:
The function removeRightChild()
is implemented so that:
- It throws an exception (yes, false)
in case the child is NULL,
which is, at least, questionable.
- It copies
the right child as a temporary subtree,
then removes the original, and then
returns by value
a(nother) copy of the removed subtree.
(not enough space for smilies, sorry)
- P.232:
The implementation of following function exhibits
poor knowledge of programming, even at the level of C.
class Student
{
.....
bool operator== (const student &std) const
{
if (id == std.id)
return true;
return false;
}
.....
};
- P.237:
Here is an implementation of binarySearchTree::insert()
Apart from not compiling this code, you can see that
the author does not care about appropriate knowledge
of operator new and about exceptions.
There are more questionable issues here . . .
void binarySearchTree::insert(node* &root, nodeValue new_value)
{
if (root == NULL)
{
root = new node(new_value, NULL, NULL);
if (!root)
throw false;
}
else if (root->value > new_value)
insert(root->LChild, new_node);
else
insert(root->RChild, new_node);
}
Lichtman & Rash:
The Complete Guide to the C Language May, 1997.
- P.31 (and throughout the book):
The book uses void main()
- P.48, It refers to float, double,
but not to long double.
Using float may
confuse novices.
- P.49, It refers to C data-types on PC only.
"typedef unsigned int twobytes;"
can only mislead.
- P.51: Regarding naming of variables it says
"... in the majority of compilers only 6 to 8
first characters will be recognized ..."
- K&R2 states that for identifiers with internal linkage
at least first 31 characters are significant
(and external linkage is not relevant
at that point of the book).
ISO/ANSI-C tends to make the number even higher.
- P.53, "b. In case of many global variables ..."
Instead of recommending to avoid using global variables.
- P.57: Regarding the operator %
(and operator /), it does not mention
what happens in the case of negative operands.
- K&R2 states (p.41): "The direction of truncation
for / and the sign of the result
for % are machine-dependent
for negative operands, ..."
- P.71: "... the prefix incrementing operator,
executes the increment first, and then ..."
- P.112,
int r;
float f, pie; /* No initializations */
r = 3;
pie = 3.1415927;
/* More digits than are guaranteed for float */
- P.131: int my_array[10] =
{0,0,0,0,0,0,0,0,0,0};
- The book does not know that partially initialized arrays
will be initialized to 0 (See K&R2 4.9 - p.86, A8.7 - p.219).
- P.150: There is a #define ROW 5
but 30 is a magic number.
- Chapter 7, Designing a Program,
gives an example where main()
calls do_what('+',a,b)
that calls add(a,b)
that return a+b; .
- I wish to meet the student that will understand the
deep and very important issues of Top-Down Design
and Design for Correctness from that example.
It is my opinion that this chapter should not have been
written at all.
- P.185: It says that extern defines variables
(but it only declares - except when no definition is available).
- P.229: Pointers to functions - old style function definition.
- P.265: #include <alloc.h>
Not standard (old style).
- P.299: (Regarding dynamic memory allocation) it says
"If we do not test [the value returned from
dynamic memory allocation], we will step on other
[unexpected] areas [of memory]."
-
This is simply incorrect (since malloc() (etc.)
returns NULL on failure).
- P.300: "size_t
is a Bourland constant" - Mmmm... So simple.
- P.327: To my opinion, a poor implementation of
Hanoi().
Y. Nativ:
Learning C 2nd ed. Hod-Ami pub.
- All over (pp. 191, 193):
The book uses void main()
- The following two are
enough to disqualify a book about C
:
- Using magic numbers instead of
using #define (e.g, pp. 191, 193).
- Using the library function gets()
instead of fgets() (e.g, p. 109).
- P. 83:
No test for successful scanf()
- P. 258:
Describing the function fscanf()
without even a slight reference to its returned value.
Alon Manor: The C Language: Programs and Solutions
Pub: Hod-Ami.
- If you use this book as a reference in
exam, you will,
probably, NOT pass it.
Daniel Kilstein: The C Language: Exercises and Solutions
Pub: ???????.
- If you use this book as a reference for an
exam, you will,
probably, NOT pass it.
Want to know why? Keep on reading.
- Here is question #27 from Ch(7) - pointers:
Write a program that reads a string
of letters and prints, for each letter, as many asterikes (*)
as the number of occurences of this letter in the string. E.g,
A ** (two occurrences)
B *** (three occurrences)
C (none)
Here is how the distinguished
(
) author
solves the problem.
A Hint: If I had given
that problem in an exam, and you had solved it
as it is done in the book,
your grade would have become
negative.
Indeed, usually the minimal grade for a problem in my
exams is 0 (zero),
but here I would have made an exception.
Well, following comments from my colleagues, I admit
I have phrased the above too harsh with respect to my students.
Indeed, a freshman, first semester students that has just
met C, does deserve more than ε
of the grade for showing some algorithmic ability.
Yet, for an author of a book, that is able to show
his ignorance more than anything else - this is inexcusable.
Alan R. Neibauer: Your First C/C++ Program 1994,
see
This one seems to be the worst C/C++ book
ever translated to Hebrew :-(among the ones I have seen ;-)
Kris Jamsa:
Rescued by C++ .
ISBN 965-361-110-0
see
U. Armon:
Introduction to Computer Science with C++ Nov. 1996.
Among the books that were originally written in Hebrew
(not translations) that I have read,
this one is the worst
(and Neibauer's is its translated companion).
(a new edition has the same errors)
- P.43 (and throughout the book):
The book uses void main(void)
- Look at Steve Summit's C-FAQ
11.14a
11.15
(C++ is the same for this).
- P.49 (and many other places): The book uses
global variables
in order to transfer arguments into functions !!!
(All of them are void f().)
- What can I say ?
See what Marshal Cline has to say in C++ FAQ Lite
Subject Index G under
Global variables: Just Say No!
- Here is a tip from Cline's book C++ FAQ:
(Excerpts from FAQ #425 about
a naming convention for identifiers)
- Class names begin with a capital letter.
- Function names begin with a lower-case letter ...
- Data member names ... have an underscore suffix.
- Names for global data
(my emphasize, Y.K) begin with
//.
(Yes, your global data should be put in a comment! Y.K.)
- P.55: Given char ch = 'A';
what will be printed by the following command:
cout << ch << ++ch << ch;
?
The book answers: "Despite the fact that printing
will be done from left to right,
the order of evaluation
[of the ch values]
is done from right to left".
[Therefore the output will be BBA].
- P.58: "i += 2
is faster than
i = i + 2".
- This is true only if you have
a retarded compiler
;-)
- P.69: It is claimed that "... in the expression
b1 || b2 && b3 || b4
the expression b2 && b3
will be evaluated first."
- The fact that the above expression will be evaluated
as if written
b1 || (b2 && b3) || b4
(because && has higher precedence
than ||)
has nothing to do with order of evaluation.
In fact, the subexpression b1
will always be evaluated first because of the
sequential nature of operator ||
(which is related to the short circuit phenomenon).
- P.127: "Initializing a two-dimensional array
using the { {...}, {...}, ...} idiom
is equivalent to initializing it using the
{...} idiom".
- Try to initialize his example of c[][2]
both ways, and then use the same two initializations
for c[][3], and you will see
that they are NOT equivalent.
- P.247: "... using global variables is not so desirable,
because if there are 100 functions in the file,
all of them can modify their values."
- Too late to tell the reader, after all his examples
with global variables !!!
- Who writes 100 functions in a single file ???
- P.267 onward: Showing just the simple C-style structures.
No classes, no member functions, no OOP.
- P.270: Using global variables struct vector.
Using File *
instead of fstream.
- P.300: Uses the C function gets()
"... the only one that inputs spaces ..."
- Forget the C++ input functions ;-)
What about the C function
fgets() that is
MUCH safer ???
Y. Gerber: C++ as Mother Tongue Jan. 1995
(I have not found a later edition).
-
In many cases main() is defined as implicitly
returning int, but in many other cases
it is defined explicitly as returning void.
- Look at Steve Summit's C-FAQ
11.14a
11.15
(C++ is the same for this).
- P.11: Wrong definitions for various types
(e.g, short is said to always be
of size 2 bytes: "2 bytes guaranteed").
See also P.30 - an int is two bytes.
- The ONLY things that are guaranteed by the standard
(stating informally):
- A minimum range for type short -
which is equivalent to having AT LEAST
two bytes in size.
- A minimum range for type long -
which is equivalent to having AT LEAST
four bytes in size.
- sizeof(short)
<= sizeof(int)
<= sizeof(long).
In addition, the intention is that
type short will be strictly shorter
than type long
(see K&R2, p.36).
- P.13: It uses float all over the book.
- P.28: Operator precedence: Parentheses as punctuation marks
(for grouping sub-expressions) - at the
top level of the table - are NOT AN OPERATOR.
The operator :: is missing.
- P.30: The C style casting
(float)x (which is
a depreciating feature in C++,
and is always a sign of a poor C++ style) is taught.
- At least, it should have been taught as
float(x), if not as
static_cast<float>(x).
-
P.98-101: A class rect (representing rectangles)
is defined and used, as the concluding example
of the chapter introducing classes.
As a C++ problem
at an exam, I gave the following question:
Find the conceptual
errors (not bugs) in the following code example
(a Xerox copy of the code was supplemented).
I will not
bother you
with the code itself
(a better copy),
but, are you interested in reading
the errors I could find there (there may be more ;-) ?
(or copy from here)
C++ as a Mother Language
------------------------
By Yitzhak Gerber
pp. 98 - 101: "the final version"
-----------------------------------
List of Errors (not ordered by importance):
(0) No #ifndef protection against multiple inclusion
(it may be argued that it's irrelevant here).
(i) Make the scaling type a `typedef', for easy modification
(too early for `templates', in the book).
(ii) Long functions inside class (inline),
but short functions - outside
(in the book, inlining discussed just before).
(iii) Assignments at Ctors [should initialize data members].
(iv) "Magic Numbers" in code [should use `enum' values].
(v) Clumsy code at Ctor
[redundant criticism, if avoids code dup].
(vi) Code duplication at Ctor and set_a() and set_b()
[extract the common parts as independent functions].
(vii) Error response is too harsh (exit())
[use ILLEGAL values - too early for exceptions].
(viii) Error messages go to `cout' and not to `cerr'.
(ix) Inspector methods are not `const' [make them `const'].
(x) BAD METHOD NAMING: _a/_b
[instead of length/width/height].
(xi) BAD METHOD NAMING: set_/get_
[instead of function overloading].
(xii) Horrifying coding style at rect::area(), rect::perimeter().
(xiii) rect::show() is bound to `cout' only
[use `ostream' argument].
(xiv) Could have used `operator<<'
(though, too early in the book).
(xv) main() implicitly returns `int' (a syntax error in C++)
[make it explicit].
(xvi) No initializations for `z', `s' at main()
[switch declarations order, and initialize].
(xvii) Code duplication in main()
[exercise all rectangles at a single function].
(xviii) main() should be on a separate file
[separate from "rect1.cpp"].
(xix) File "rect1.h" is not self contained
[#include <stdlib.h> and <iostream.h>].
(xx) Horrible indentation.
(xxi) #include <process.h> is non-standard.
(xxii) All printings are of '\n', not even a single `endl'.
(xxiii) Loop variables should be declared inside loops (at show()).
(xxiv) Private part is better put at the bottom of the class.
Copyright (c) 1999 - 2003 by Yechiel M. Kimchi
I planned to add more here (for pp. 100 - 240), but I am fed up with it
- P.247: There is a three-page function (yes, 3 pages - 109 lines)
chess::move(int x, int y)
which recursively solves the Knight-Tour problem.
This is how it can be rewritten in 32 lines:
chess::move(int x, int y)
{
static const int
row_ind[] = {-2, -1, +1, +2, +2, +1, -1, -2},
col_ind[] = {+1, +2, +2, +1, -1, -2, -2, -1},
cases = sizeof(row_ind)/sizeof(row_ind[0]);
// .... 9 lines
for (int i = 0; i < cases; ++i) {
int new_row = x + row_ind[i],
new_col = y + col_ind[i];
if (check(new_row, new_col))
{
board[new_row][new_col] = ++num;
if (num == 64) return (1);
if (move(new_row, new_col))
return(1);
else
{
board[new_row][new_col] = 0;
num--;
}
}
}
return (0);
}
I have left some of the bad style intact (for you to judge).
Evidently, a book that does not show this simple method for
overcoming irregularities in loops cannot teach you C++
as a Mother Tongue !!
P.250: Here comes the function
chess::check(int x, int y)
that is written as follows:
chess::check(int x, int y)
{
if (x>=8 || x<0 || y>=8 || y<0 || board[x][y]>0)
return(0);
else
return(1);
}
- Without changing the internal structure
of the class chess (which I would),
this is how I would have written
these last two functions:
class chess {
enum {ROWS = 8, COLS = 8, SIZE = ROWS*COLS};
int board[ROWS][COLS]; // No magic numbers
//.... the rest of the class ....
};
bool // Boolean type is returned (and not implicit int)
chess::check(int row, int col)
{
return row < ROWS && row >= 0 // No magic numbers
&& col < COLS && col >= 0
&& board[row][col] == 0; // No if, no else
}
bool // Boolean type is returned (and not implicit int)
chess::move(int row, int col)
{
static const int
row_ind[] = {-2, -1, +1, +2, +2, +1, -1, -2},
col_ind[] = {+1, +2, +2, +1, -1, -2, -2, -1},
cases = sizeof(row_ind)/sizeof(row_ind[0]);
// .... 9 lines
for (int i = 0; i < cases; ++i) {
const int new_row = row + row_ind[i],
new_col = col + col_ind[i];
if (check(new_row, new_col)) { // Improved indentation
board[new_row][new_col] = ++num;
if (num == SIZE) return true; // No magic number
if (move(new_row, new_col)) return true; // No else
board[new_row][new_col] = 0;
--num;
}
}
return false;
}
- P.274: Given the definitions (on pages 272, 273)
class square{
float a;
// The rest of the class
};
class rectangle: public square{
float b;
// The rest of the class
};
It claims that "[rectangle] can be written
in a way that shows the origin of the definitions:"
class rectangle {
float square::a;
float rectangle::b;
// The rest of the class
};
- Here it uses a depreciating construct
(it should have used the using directive).
In this particular case it is obviously wrong, since
square::a is private.
In fact, this style is not for "showing the origin
of the definitions", but for the rare cases
that someone wants to alter the accessibility level.
Regarding data-members, it is (not only) my view that
they should always be private,
and therefore their accessibility level can never change.
- P.274: One of the Notes says:
"If square::show()
had been given different parameters
than rectangle::show() is given,
then they would become practically two different functions,
and therefore, rectangle would have
two overloaded functions named show()
..."
- Let's see how many errors are here:
(i)
These two function ARE different, as they are now.
(ii)
Since rectangle::show() IS OVERRIDING
square::show(),
it seems as if rectangle has
a single function show().
(iii)
OVERRIDING a non-virtual function is usually
a design error.
(iv)
Even if these two functions were declared
with different interface,
still rectangle::show()
would have been HIDING square::show().
Therefore, rectangle still have
a single function rectangle::show()
(as it has now),
where the other one is only accessible
as square::show() (as it is now).
See what Marshal Cline says about hiding
base-class functions:
C++FAQ#21.1,
C++FAQ#23.3.
- P.487: If it deals with the function scanf()
(which is
not recommended
for C++,
and is even riskier than its counter-part
output function printf()) - at least it should
teach how to use its returned value.
In addition, the description of the format-string
is so misleading that it should be considered wrong.
More to come.
Enjoy.
e-mail:
mailto.html
A few References:
- [K&R2] B. Kernighan & D. Ritchie:
The C programming Language,
2nd. ed., 1988, Prentice Hall.
- S. Summit:
C Programming FAQs,
1996, Addison-Wesley Longman.
- B. Stroustrup:
The C++ Programming Language,
3rd ed., 1997, Addison-Wesley Longman.
- S. Lippman & J. Lajoie:
C++ Primer ,
3rd ed., 1998, Addison-Wesley Longman.
- M. Cline & G. Lomow:
C++ FAQs,
1995, Addison-Wesley Longman.
- S. Meyers:
Effective C++,
2nd. ed., 1997, Addison-Wesley Longman.
Go to:
More References
Choosing a Textbook
C++ Bad Books
Yechiel Home Page
Israel Fights Terror
This page has been visited
times since 1998/4/12.
Copyright © 1998-2006 by Yechiel M. Kimchi. All rights reserved.
http://www.cs.technion.ac.il/users/yechiel/CS/BadBooksC+C++.html
Created: 1998/4/12
Last updated: 2012/10/0 9:50 IST
CopyRight Notice:
Copying this page, or part of its (textual) content,
using any kind of medium, form or format,
is strictly prohibited unless a written permission was given by the author.
You are allowed to print this page for personal use only.
You are allowed to create any number of links to this page,
or to any part thereof.
You are kindly asked (but not obliged) to
inform me
about these links and their (URL) locations.