I'm trying to format a binary array: char* memblock
to a hex string.
When I use the following:
fprintf(out, "0x%02x,", memblock[0]);
I get the following output:
0x7f,
When I try to use boost::format
on an ofstream like so:
std::ofstream outFile (path, std::ios::out); //also tried with binary
outFile << (boost::format("0x%02x")%memblock[0]);
I get a weird output like this (seen in Vi): 0x0^?
.
What gives?
Given that the character for 0x7f
is CTRL-?, it looks like it's outputting the memblock[0]
as a character rather than a hex value, despite your format string.
This actually makes sense based on what I've read in the documentation. Boost::format
is a type-safe library where the format specifiers dictate how a variable will be output, but limited by the actual type of said variable, which takes precedence.
The documentation states (my bold):
Legacy printf format strings:
%spec
wherespec
is aprintf
format specification.
spec
passes formatting options, like width, alignment, numerical base used for formatting numbers, as well as other specific flags. But the classical type-specification flag ofprintf
has a weaker meaning in format.It merely sets the appropriate flags on the internal stream, and/or formatting parameters, but does not require the corresponding argument to be of a specific type. e.g. : the specification
2$x
, meaning "print argument number 2, which is an integral number, in hexa" for printf, merely means "print argument 2 with stream basefield flags set to hex" for format.
And presumably, having the field flag set to hex doesn't make a lot of sense when you're printing a char
, so it's ignored. Additionally from that documentation (though paraphrased a little):
The
type-char
does not impose the concerned argument to be of a restricted set of types, but merely sets the flags that are associated with this type specification. Atype-char
ofp
orx
means hexadecimal output but simply sets the hex flag on the stream.
This is also verified more specifically by the text from this link:
My colleagues and I have found, though, that when a
%d
descriptor is used to print achar
variable the result is as though a%c
descriptor had been used -printf
andboost::format
don't produce the same result.
The Boost documentation linked to above also explains that the zero-padding 0
modifier works on all types, not just integral ones, which is why you're getting the second 0
in 0x0^?
(the ^?
is a single character).
In many ways, this is similar to the problem of trying to output a const char *
in C++ so that you see a pointer. The following code:
#include <iostream>
int main() {
const char *xyzzy = "plugh";
std::cout << xyzzy << '\n';
std::cout << (void*)xyzzy << '\n';
return 0;
}
will produce something like:
plugh
0x4009a0
because the standard libraries know that C-style strings are a special case but, if you tell them it's a void pointer, they'll give you a pointer as output.
A solution in your specific case may be just to cast your char
to an int
or some other type that intelligently handles the %x
format specifier:
outFile << (boost::format("0x%02x") % static_cast<int>(memblock[0]));