Last time we counted characters. The next logical thing is to count lines. Let’s look at the code to do that:
# linecount - count lines in standard input
character getc
character c
integer nl
while (getc(c) != EOF)
if ( c == NEWLINE)
nl = nl + 1
call putdec(nl, 1)
call putc(NEWLINE)
stop
end
We have a NEWLINE constant that represents a standard character for the system running the program. Using that keeps it portable.
We also introduce the idea of using “==” for a comparison to differentiate the operator from the single “=” which is used for assignment. This makes it easier to catch ourselves accidentally doing an assignment when we expected to do a comparison. In Java it’s not even allowed, so the compiler catches it for us!
We continue to use getc() and putc() as fundamental building blocks that handle system input and output. This allows us to use any input or output without worrying about the implementation. We just check one character at a time. Such a powerful design!
How do we make sure it’s working properly? Our first thought is to test for boundary conditions: a file with no lines, and a file with one line. If these are handled properly, the general case should be handled automatically.
So for an empty file, it won’t make it into the while statement, and since the nl counter is initialized to zero, it returns the correct answer.
For a file with one line, it will find that one line once. The counter will be properly incremented, and it will return the correct answer.
Is it overkill to test a tiny program like this? No, it’s called prudence. Good habits. If you get in the habit of thinking about boundary conditions when putting together a program, you’ll write more robust programs.
This book (and this series) is all about developing the proper habits to write great code, so pay attention to the little things. They matter.
Question for the reader: what if the file doesn’t end with a NEWLINE? How should that be treated?


