on 15 November 2013
By the time of typing this (November 2013), it is obviously somewhat late for me to contribute a 'review' of this book, as the world of computing has moved on, but as it is the most disgraceful instance that I have ever encountered (in any subject field) of inadequate proof-reading, I would like belatedly to share my opinion on it with any Amazon customer who is considering buying a copy.
In 2000 I bought the following two books from SAMS publications: the book under discussion here (Teach Yourself C in 21 Days, by Peter Aitken & Bradley L. Jones, Fifth Edition, 2000, First Printing, October 1999) and Teach Yourself C++ in 21 Days, by Jesse Liberty, Third Edition, 1999, First Printing, February 1999. As regards the style and content of both books, there is a great deal to praise. My impression is that the three authors are not only skilled programmers but also experienced teachers.
Before buying these books I had already read another course about C programming, but had been confused by it. However, after reading the book by Mr Aitken & Mr Jones, I realised that the course which I had previously read had merely been explained badly, with the various concepts of C programming being introduced in the wrong order and without sufficient detail. Reading the Aitken/Jones book made the C language appear relatively simple as the authors offer a coherent and ideal introduction to the subject. One of the strongest aspects of Mr Liberty's book is that when introducing new concepts, he uses the same examples for much of the time (I refer to the "Animal" & "Cat" classes), extending them to include the new ideas which are being introduced: this is a good idea, because the reader becomes familiar with the same classes and is able to compare the similarities between the various listings, as well as the contrasts between them, to study how the listings develop in complexity. It is also clear that Mr Liberty has, despite his experience, not forgotten the difficulties which novices initially have with C++ concepts, and I welcomed the amount of detail and explanation given - a level of detail which most students need, but which they might be embarrassed to ask a teacher.
So, full marks to the authors. But the rest of this review is somewhat more critical, as it appears that something went drastically wrong in the production of both books after they were written: I am referring to the astonishing number of mistakes. I have detailed some of the worst types of mistakes below. Interestingly, an earlier version of the Aitken/Jones book contains virtually none of the mistakes that are present in the Fifth Edition. I have seen neither of the earlier editions of Mr Liberty's book, but perhaps the same would be true of his book too.
Some of the mistakes are so obvious that one wonders whether the SAMS proofreaders even attempted to check the text before publication. For example, on page 351 of Mr Liberty's book there is a diagram to illustrate the two-dimensional array "Board", which is analogous to a chess board. The chess board is illustrated correctly with 64 squares, but the array which is shown has 81 elements, which would actually represent an array such as "Board". Moreover, on page 117 of the Aitken/Jones book, figure 5.6 reproduces the wrong diagram - the one which has already been printed on page 112 in its correct context.
Why did the proofreaders not identify mistakes which occur repeatedly? The most inexplicable example of this can be seen in Mr Liberty's book on page 270, where on line 4 of listing 10.1 the word "intint" appears. One needs only an elementary knowledge of programming to realise that this is a mistake. Turn the page and one sees that on page 272, line 4 of listing 10.2 has a similar mistake, with "int" written on its own. This mistake of writing "int" for no reason at the start of a program listing also occurs on pages 282, 283, 284, 286, 287, 289, 291, 293, 294, 300 & 301 in this chapter alone! Although the above list is confined to instances of the error in Chapter 10, the problem also appears elsewhere, such as line 5 of listing 9.8 on page 248. Similarly, line 2 of the "Week 1 In Review" program on page 193 contains the absurd line "intintboolfalsetrue" which should also have been spotted.
Even if the proofreaders did not understand program code, they ought at least to have identified mistakes in the English text. There are many grammatical errors (such as omitted words) in the explanations and commentaries. This is a matter of basic literacy, such as one has the right to expect in any publication. In Mr Liberty's book, there are quiz questions at the end of Day 11 (page 339) but when one looks up the answers (page 807) one finds that the answers which are given to the Day 11 questions actually refer to the questions after Day 12. Similarly, there are quiz questions at the end of Day 12 (page 382), but the answers which are given (page 808) actually refer to the questions after Day 11.
Worse, often the questions and answers do not match at all. To take an example, there are three quiz questions on page 628 following Day 18, but when one looks up the answers on page 827, one finds six answers. Answer 1 corresponds to question 1, but the remaining five answers consist of responses to questions which were not asked on page 628, therefore questions 2 & 3 from page 628 receive no answers. This is merely one example of confusion in the question/answer sections, but there are other similar instances, not only in Mr Liberty's book, but also in the Aitken/Jones book. In general, the questions are themselves reprinted in the section devoted to the answers, and in some instances the wording is different - usually only slightly, but in other cases significantly. It would surely not have been too much to ask the proofreaders to check for consistency here.
In Mr Liberty's book, the line numbers of the program listings sometimes get mixed up with the coding itself. As an example, look at listing 5.10 on page 115: in the middle of line 9, the figure 10 is followed by a colon, although it is obviously a line number. Then, in the middle of line 15, the figure 17 is followed by a colon. Next, at the end of line 20, the figure 23 is followed by a colon. This problem is not confined to listing 5.10, as it recurs elsewhere in the book: look at line 75 of listing 20.5 at the botton of page 699, where the figure 76 followed by a colon appears inexplicably as part of a class declaration, as "class xNegative : public xsize76:". This is clearly a line number which has gone astray, because when one turns the page one finds that line 76 is missing and the next line is line 77.
I am baffled as to why parentheses are omitted so often, along with the variables and constants which they are supposed to contain. Look at page 322 of the Aitken/Jones book, where on line 10 of listing 13.8 the keyword "while" is used in isolation, whereas what was supposed to be printed was "while(1)". An identical error recurs on line 11 of listing 13.9 on page 326, and this listing is particularly inaccurate, as line 21 simply says "exit;" when presumably "exit(0)" was intended.
The example just given, missing out both the parentheses and the integer argument when using the exit function, turns out to be one of the most frequent errors in the Aitken/Jones book. To take an example, on Day 16 it happens constantly (on pages 441 & 443, four times on page 448, twice on page 452, again on page 453, three times on page 455, then again on pages 456 & 458) and in this chapter in the book we also get more examples of the keyword "while" being used without the essential parentheses and a condition (line 10 on page 437 and line 48 on page 455).
Sometimes the missing text can be confusing to the novice programmer, for example lines 12 & 16 of listing 5.2 on page 105, where what is printed is "z = half_of" which is a misprint for "z = half_of(x)" and "z = half_of(y)". Likewise, on line 20 of listing 5.5 on page 115, "f = factorial" is printed, which should clearly be "f = factorial(x)" for it to have any meaning in C.
These omissions continue throughout the book. Look at page 588, where eight lines from the top of the page "#define SQUARE *" is printed. Presumably this should read "#define SQUARE(x)*(x)", judging by the context of what is being explained. Then, on page 596, the shaded "DO/DON'T" box says "#define CUBE **" when surely it should say "#define CUBE (x)*(x)*(x)". Again, this may appear so obvious to a professional programmer that it hardly needs commenting upon, but a novice reading the book may be bewildered.
Some of the mistakes are more difficult for a novice to spot, for example, line 13 of listing 14.5 on page 340, where the line "while ((ch = getch != `\r' && x < MAX)" has a closing parenthesis missing after "getch". This mistake also occurs twice on page 337 (line 9 of listing 14.2 and line 12 of listing 14.3) and on page 339 (line 10 of listing 14.4), to name only two examples of many. The programs will not function correctly without these parentheses, and errors of this nature seriously call into question the claim made in the acknowledgements section of the book that "the text and programs in this book have been thoroughly edited and tested".
My guess is that many of the listings in this book were considered so elementary that they were written without being entered or compiled. Damning evidence for this comes on pages 322-323: compare the literal strings on lines 25 & 34 of listing 13.8 with the output printed at the top of page 323, and one sees that the phraseology is different, illustrating that this is not genuine output from the "tested" program, but merely the output which was expected. Incidentally, line 10 of this listing is also wrong, with no argument in parentheses after the "while" keyword. Many beginners will have been confused by this chapter: the section on infinite loops (page 312) begins with an example with the same omission and has a similar omission in the example at the top of page 313.
I believe that some of the programs have bugs. In the Aitken/Jones book, listing 15.11 on pages 408-409 produces the correct output but is nevertheless illogical in its design. On line 32, the user is invited to enter '1' if he wishes an alphabetical sort. However, if he enters '1', on line 69 the conditional test will evaluate as TRUE, which means that the "reverse" function will be called. At this point, the program is therefore apparently going to do exactly the opposite processing to that which the user wants! However, when one examines the reverse function coding on lines 99 - 103, one notes that it will return a positive value if the first of the two arguments passed to it is greater (in other words, if the two lines are not in alphabetical order) and this will result in a TRUE evaluation on line 75, so that an exchange will take place on lines 77 - 79. So the reverse function will put the lines in alphabetical order! Similarly, the alphabetical function puts the lines in reverse alphabetical order. So what happens is that the opposite function is called to the one which the user wants, and then whichever function is called performs the opposite processing to what it is supposed to do anyway, thus the two mistakes cancel out and ironically the program gives the impression of working perfectly!
Sometimes, the text becomes confused. For example, on page 249 of Mr Liberty's book, there is an analysis of listing 9.8. This begins by stating that "on line 10, number, squared and cubed are defined as USHORTs". Actually, they are defined simply as ints, and although I realise that in other listings USHORT is a typedef for int, this typedef is not used in listing 9.8. What appears to have happened is that there was confusion between listing 9.8 and listing 9.9 on the next page, which does indeed use the typedef USHORT. In the next paragraph, it says "it sets return Value to a simple error value", which is misleading as there is no such variable as "return Value". I realise that what is meant is "it sets Value to a simple error value and returns Value". However, the next sentence is completely wrong, as it refers to "the return value from Function( )". However, there is no such function as "Function( )" and it is "Factor ( )" which is being refered to. Later in the analysis, it says "on line 38, return Value is assigned a success value". Since "return Value" is printed in monospace font, which is used throughout the book for actual C code, this is an unambiguous suggestion that "return Value" is actually a variable, but there is no such variable, only a variable called "Value" which is returned. Immediately afterwards, it is stated that "on line 39, return Value is returned", and again, "return Value" is in monospace, implying that it is a variable. It isn't. Moreover, it is not returned on line 39 anyway, it is returned on line 40. Getting the line numbers wrong during the analysis of listings is a frequent mistake in SAMS publications, and suggests that the analyses were based on initial drafts of the programs, which were then subsequently changed without updating the analysis. It is inevitable that there will always be small oversights of this sort by any author, but it is absurd that so many mistakes have been passed by the proofreaders.
If the mistakes which I have pointed out were the only errors in the two SAMS books which I have bought, it would hardly be worth writing about them. However, the truth is that these errors are merely representative of many other similar errors, far too numerous to list here. In essence, Peter Aitken, Bradley Jones and Jesse Liberty have produced excellent books, and it is very unfortunate that these books, which have the potential to be regarded as the best teaching manuals on the market, have been spoilt by the staggering degree of incompetence of the proofreaders at SAMS publishing. The two proofreaders responsible are named in the list of credits. As even the most obvious errors have been left uncorrected, it seems obvious that neither of them made even the slightest effort to check any part of the text before publication.