At the outset Kernighan and Plauger present their readers with a user defined type
character which is defined as
type
character = -1..127; { ASCII, plus ENDFILE }
The only purpose of type character is to defeat Pascal strong typing by mapping the ASCII character set onto a subset of integers. I do not think this is a good idea. K&P apparently do not like strong typing. I disagree. I believe that strong typing is a virtue, not a vice, therefore all the programs which I present will use Pascal’s type
char, not character.
Having established type character K&P then define two constants
const
ENDFILE = -1;
NEWLINE = 10; { ASCII value }
DOS uses chr(26) for end of file and chr(13) for end of line. If I have occasion to use either ENDFILE or NEWLINE they will be defined accordingly (as char, not integer).
K&P then define two "primitive" functions:
getc and
putc. More precisely
function getc(var c : integer) : integer ;
and its inverse
function putc(c : integer) ;
getc and putc serve as K&Ps basic input/output functions. Why
Read and
Write are not adequate is never made clear. getc and putc simply serve to force an unneeded C-like syntax onto Pascal. (Kernighan is credited with being the co-inventor of C.) I see no need for getc and putc. For an experienced Pascal programmer they not only generate more code but work againse K&P’s declared objective (on the cover of the book) to make programs "...clean, easy to read,..." This is an issue which I have given much thought. The programs I present will not use getc or putc.
To illustrate my reservations about getc and putc consider
copy, the first program K&P present. Copy duplicates the function of the DOS copy command and as such is merely academic, tutorial or pedagogic (choose your own adverb). Here's their version:
{ Copyright (C) 1981 by Bell Laboratories, Inc., and Whitesmiths Ltd. }
{ copy -- copy input to output }
procedure copy;
var
c : character;
begin
while (getc(c) <> ENDFILE) do
putc(c)
end;
First note that this is a procedure, not a program. The reason for this is not made clear until the end of the book.
while (getc(c) <> ENDFILE) do
To an experienced Pascal programmer this line works against the objective of creating readable code. Too much is happening on one line, and it’s not even happening left to right (or top to bottom); it’s happening inside out. getc is the first thing executed (on the inside) and then a logical test is made. K&P are trying to force C syntax onto Pascal. Yes, this is a criticism of C and I’m not the first to make it.
Here's my version:
Program Kopy ;
{
Kopy -- copy input to output
}
Var
Ch : Char ;
begin { Kopy }
while NOT eof do begin
Read (Ch) ;
Write (Ch)
end
end. { Kopy }
Notes:
It's a program, not a procedure.
It's called
Kopy, not copy. I don't want my program to collide with the DOS command copy.
The first line of executable code
while NOT eof do begin
will be familiar to Pascal programmers, an old friend. Readability is enhanced by familiarity.
What happens when Kopy encounters the end of line? End of line in DOS is a combination of a carriage return {Chr(13)} followed by a line feed {Chr(10)}. It is a virtue of Turbo Pascal that, if one ignores (does not test for) end of line, it will return chr(13) and chr(10) in turn.
Eoln is actually a test that returns TRUE whenever the next (unread) character in the stream is a carriage return. Kopy does not test for eoln. There’s no need.