Paul 的个人资料Paul's Space照片日志列表 工具 帮助

日志


    9月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;

    评论

    请稍候...
    很抱歉,您输入的评论太长。请缩短您的评论。
    您没有输入任何内容,请重试。
    很抱歉,我们当前无法添加您的评论。请稍后重试。
    若要添加评论,需要您的家长授予您相应权限。请求权限
    您的家长禁用了评论功能。
    很抱歉,我们当前无法删除您的评论。请稍后重试。
    您已超过了一天之内允许提供的评论数上限。请在 24 小时后重试。
    因为我们的系统表明您可能在向其他用户提供垃圾评论,您的帐户已禁用了评论功能。如果您认为我们错误地禁用了您的帐户,请联系 Windows Live 支持部门
    完成下面的安全检查,您提供评论的过程才能完成。
    您在安全检查中键入的字符必须与图片或音频中的字符一致。
    ScherfPaul 在此页禁用了评论功能。

    引用通告

    此日志的引用通告 URL 是:
    http://pscherf.spaces.live.com/blog/cns!3B092CB7298FDE18!194.trak
    引用此项的网络日志