tags:

views:

95

answers:

2

If I wanted to output a fixed width hex number with 4 digits on a stream, I would need to do something like this:

cout << "0x" << hex << setw(4) << setfill('0') << 0xABC;

which seems a bit long winded. Using a macro helps:

#define HEX(n) "0x" << hex << setw(n) << setfill('0')

cout << HEX(4) << 0xABC;

Is there a better way to combine the manipulators?

+4  A: 

Why a macro - can't you use a function instead?

void write4dhex(ostream& strm, int n)
{
    strm << "0x" << hex << setw(4) << setfill('0') << n;
}
KenE
+1 and no macros pls! KTHX
+12  A: 

Avoid the macros when you can! They hide code, making things hard to debug, don't respect scope, etc.

You can use a simple function as KenE provided. If you want to get all fancy and flexible, then you can write your own manipulator:

#include <iostream>
#include <iomanip>
using namespace std;

ostream& hex4(ostream& out)
{
    return out << "0x" << hex << setw(4) << setfill('0');
}

int main()
{
    cout << hex4 << 123 << endl;
}

This makes it a little more general. The reason the function above can be used is because operator<< is already overloaded like this: ostream& operator<<(ostream&, ostream& (*funtion_ptr)(ostream&)). endl and some other manipulators are also implemented like this.

If you want to allow the number of digits to be specified at runtime, we can use a class:

#include <iostream>
#include <iomanip>
using namespace std;

struct formatted_hex
{
    unsigned int n;
    explicit formatted_hex(unsigned int in): n(in) {}
};

ostream& operator<<(ostream& out, const formatted_hex& fh)
{
    return out << "0x" << hex << setw(fh.n) << setfill('0');
}

int main()
{
    cout << formatted_hex(4) << 123 << endl;
}

If the size can be determined at compile-time, however, might as well just use a function template [thanks to Jon Purdy for this suggestion]:

template <unsigned int N>
ostream& formatted_hex(ostream& out)
{
    return out << "0x" << hex << setw(N) << setfill('0');
}

int main()
{
    cout << formatted_hex<4> << 123 << endl;
}
+1 I would prefer a manipulator to a free function, since it seems to better convey the intent. To make it fully generic, write it as a template `hex<N>`.
Jon Purdy
@Jon good call! I have edited the post accordingly to include that as a possibility.
I believe what you've typed in your first example doesn't work. You need to write `hex4(cout) << 123 << endl;`.
rlbond
@rlbond that's also why the third example works (we're passing a function address to a function pointer argument as the right operand for operator<<). The second example, using a class/struct, doesn't have an operator<< already overloaded for us, however, and that's why we have to define an overloaded operator<< for that one.
Wow, I learned something new! Thanks! I think you should add that explanation to your answer :)
rlbond
@rlbond you're welcome! :-) I added it to the answer; thanks for the suggestion!