Paul's profilePaul's SpacePhotosBlogLists Tools Help

Paul's Space

September 24

Formatting to a C++ ostream

Formatting a data type in C++ using an ostream is not complicated. All that is really needed is a an appropriate operator << override. I do this a lot for debugging new programs. I'll often write an operator << overload for every type I define, even if I throw away the operator << overloads later. Let's do an example for how to do this with an enumeration. Here is an enumeration:

enum MyEnumeration {
    AValue,
    AnotherValue,
    YetAnotherValue,
};

The key is knowing what the parameters and return value need to be for the operator << override. The return value needs to be a reference to an ostream, as does the first parameter. The second parameter needs to be a const reference to the type to be formatted. (It doesn't absolutely have to be a reference. If it isn't const, you won't be able to print const's.) For MyEnumeration:

std::ostream &operator << (std::ostream &os, const MyEnumeration &en)
{
    switch (en) {
    case AValue: return os << "AValue";
    case AnotherValue: return os << "AnotherValue";
    case YetAnotherValue: return os << "YetAnotherValue";
    }
    return os << int(en) << "???"; // Wasn't really a MyEnumeration
}

Now we can print a MyEnumeration like this:

    MyEnumeration me = AnotherValue;
    std::cout << me << std::endl;

We can format any type in an alternative manner by defining a tiny class with a constructor and a friend function that is our operator << override. As an example let's see how to format unsigned integers in base 5.

class BaseFive {
    const unsigned int ui; // This and the constructor parameter could be a reference, if that would be more efficient
public:
    explicit BaseFive(const unsigned int unsignedInt) : ui(unsignedInt) { }
    friend std::ostream &operator << (std::ostream &os, const BaseFive &bf);
};

std::ostream &operator << (std::ostream &os, const BaseFive &bf)
{
    char buf[10]; // 10 is big enough for a 32-bit unsigned int

    char *bp = buf + sizeof buf;
    *--bp = '\0'; // Prepend a trailing nul character
    unsigned int ui = bf.ui;
    do { // Do one digit at a time, starting with the one's position
        *--bp = ui % 5 + '0';
        ui /= 5;
    } while (ui > 0);
    return os << bp;
}

Now we can print an unsigned int in base 5 like this:

    std::cout << BaseFive(125) << std::endl;

A more complex class can be formatted by having an appropriate friend function for our operator << override. Here are the highlights:

class SomeClass {
    ...
    friend std::ostream &operator << (std::ostream &os, const SomeClass &sc); // Add this friend
};

std::ostream &operator << (std::ostream &os, const SomeClass &sc)
{
    ... print the interesting fields in the desired way
    return os;
}

Now we can print instances of SomeClass like this:

    SomeClass aSomeClass, anotherSomeClass;
    ...
    std::cout << "aSomeClass=" << aSomeClass << " anotherSomeClass=" << anotherSomeClass << std::endl;

April 27

Explanations

Like space pictures? Don’t like to wait too long? Here you go.
http://www.youtube.com/watch?v=0CFPg1m_Umg&NR=1

Who says you can’t get good pictures with MS Paint?
http://www.youtube.com/watch?v=uk2sPl_Z7ZU&NR=1

I don’t know what it is, but if you need to know how it works this guy explains it in detail.
http://www.flixxy.com/rockwell-automation-systems.htm

March 29

Here Starts My Blog

If I had anything interesting to say, I would type it here.

 
Photo 1 of 1

Paul Scherf

Occupation
Location
Interests