Jez Higgins

Freelance software grandad
software created
extended or repaired


Follow me on Mastodon
Applications, Libraries, Code
Talks & Presentations

Hire me
Contact

Older posts are available in the archive or through tags.

Feed

Thursday 15 August 2019 The Forest Road Reader, No 2.24 : STinC++ - charcount

STinC++ rewrites the programs in Software Tools in Pascal using C++

After devoting six pages to bootstrapping copy, Kernighan and Plauger give their next program, charcount, six sentences of setup. Of those six, three of them are an exhortation to just hang on and trust them

If you can’t think offhand why anyone would want to merely count the characters in something, don’t worry. This is a book on tool building, remember, and tools work best in combination. Applications will occur soon enough.

charcount.pas
procedure charcount;
var
    nc : integer;
    c : character;
begin
    nc := 0;
    while (getc(c) <> ENDFILE) do
        nc := nc + 1
    putdec(nc, 1);
    putc(NEWLINE);
end;

In their copy program, they established they could read a character at a time from the standard input. For charcount, it’s straightforward to modify the loop to keep a count of those characters.

Hmm. I was feeling smug about not having a loop in my implementation at all. Perhaps I’ll have to revisit the whole business?

I chose to treat the standard input as a sequence, and consequently was able to lean entirely on a function provided by C++'s standard library. Copying a sequence from one place to another is merely one of a number of operations the standard library provides. Another is std::distance(InputIt first, InputIt last), a function which returns the number of hops you need to advance from first to last.

In this case, passing in our istreambuf_iterators it gives us the count of characters available on standard input. Again, the standard library provides exactly what’s needed.

charcount.cpp
#include "charcount.h"

#include <algorithm>
#include <iostream>
#include <iterator>

namespace stiX {
    size_t charcount(std::istream &in) {
        return std::distance(
                std::istreambuf_iterator<char>(in),
                std::istreambuf_iterator<char>()
        );
    }
}

While distance maybe isn’t the best name, once you’re familiar with it this implementation is about as minimal and clear as it can be. Again, I’ve avoided an explicit loop, nor have I had to come up with any variable names. Even in a program as brief as charcount Kernighan and Plauger’s version has a comprehension overhead. Their variable c is, essentially, redundant. It’s only there so they can call the getc primitive. The variable we really need to be paying attention to is nc. However, because Pascal requires variables to declared ahead of the procedure body, all variables initially appear to be equally important. It’s a small thing here, but the larger the procedure the bigger a barrier it can be.

Rather than have the charcount function write directly to the output, as Kernighan and Plauger did, I chose to return the count from the function and deal with the output higher up. In turn, this makes our test and executable drivers extremely plain.

test driver
void verifyCharCount(std::string input)
{
    std::istringstream is(input);

    auto count = stiX::charcount(is);

    REQUIRE(count == input.size());
}
main
int main() {
    std::cout << stiX::charcount(std::cin) << std::endl;
}

Source code

Source code for this program, indeed the whole project, is available in the stiX GitHub repository. charcount is program 2 of Chapter 1.

Library References

Endnotes

This whole endeavour relies Software Tools in Pascal and Software Tools, both by Brian W Kernighan and PJ Plauger. I love these books and commend them to you. They’re both still in print, but there are plenty of second-hand editions floating round.

For this project I’ve been trying out JetBrain’s CLion, which so far has been pretty great. CLion uses CMake to build projects. My previous flirtations with CMake, admittedly many years ago, weren’t a huge success. Not so this time - it’s easy to use and works a treat.

The test harness I’m using is Catch. I’ve been aware of Catch pretty much since it was first released, but this is my first time really using it. I like it and will use it again.


Tagged code, and software-tools-in-c++


Jez Higgins

Freelance software grandad
software created
extended or repaired

Follow me on Mastodon
Applications, Libraries, Code
Talks & Presentations

Hire me
Contact

Older posts are available in the archive or through tags.

Feed