Software Tools: Counting Lines

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?

Software Tools: Counting Characters

The ability to count characters (or words or lines) is incredibly useful – especially if you are working in a text-based scripting environment (like Linux). Having a simple tool to do that would be especially helpful. What would a character-counting tool look like?

# charcount - count characters in standard input
  character getc
  character c
  integer nc
	
  nc = 0
  while (getc(c) != EOF)
    nc = nc + 1
  call putdec(nc, 1)
  call putc(NEWLINE)
  stop
end

This is Ratfor again. Why don’t we use a real language? (Ahem! Ratfor is a REAL language!) Because by using a simple language like this, we can show how these functions work in a very simple and understandable way. From there, it’s easy enough to convert it to Java or Python or whatever language you want.

So here are some noteworthy points about the code above:

First, we introduce the character data type. What’s the difference between a character and an integer? For the purposes of the book, it’s just a documentation thing. A character has a specific use. It is used to read and write character text data. Integers are used to count things. So just like the NEWLINE is a special name for a specific, system-dependent value, a character is a specific name for a value with a specific purpose.

Next, we call the putdec() function. That is a special function (which we’ll define later) that takes a numeric value as the first parameter, formats it in a character string the size of the second parameter, and outputs it to the “standard output”. It does this by using the putc() function (as we’ll see later). So we’re already taking advantage of the software tools we’ve built already.

Finally we notice that there is a separate call to putc() to write out the NEWLINE character. That seems like a waste. Why would we do that? If we want to write multiple numbers on the same line, we can’t have putdec() inserting newlines. So we keep the function simple and that keeps it flexible. And it all hangs together in such a simple, clever way!

It’s like it was designed to be that way!