From printf to C++ formatting

  • Thread starter Steven T. Hatton
  • Start date
S

Steven T. Hatton

OK, I take back the nasty stuff I said about printf. At least until I see a
similarly concise way of writing this using C++ formatters. I want to
convert the following to something I can put onto a C++ std::eek:stream:

printf( " [%2x] %-20s %-8.8s %08x %06x %02x %-3.3s %02x %04x %02x\n",
i,
std::string( pSec->GetName() ).substr( 0, 20 ).c_str(),
SectionTypes( pSec->GetType() ).c_str(),
pSec->GetAddress(),
pSec->GetSize(),
pSec->GetEntrySize(),
SectionFlags( pSec->GetFlags() ).c_str(),
pSec->GetLink(),
pSec->GetInfo(),
pSec->GetAddrAlign() );

One option I've looked at, and may come back to, is the Boost.Format
library. For now, I want to see if I can find a reasonably elegant way of
using the C++ format manipulators. Does anybody have a systematic approach
to this kind of situation?
 
M

Maxim Yegorushkin

Steven said:
OK, I take back the nasty stuff I said about printf. At least until I see a
similarly concise way of writing this using C++ formatters. I want to
convert the following to something I can put onto a C++ std::eek:stream:

printf( " [%2x] %-20s %-8.8s %08x %06x %02x %-3.3s %02x %04x %02x\n",
i,
std::string( pSec->GetName() ).substr( 0, 20 ).c_str(),
SectionTypes( pSec->GetType() ).c_str(),
pSec->GetAddress(),
pSec->GetSize(),
pSec->GetEntrySize(),
SectionFlags( pSec->GetFlags() ).c_str(),
pSec->GetLink(),
pSec->GetInfo(),
pSec->GetAddrAlign() );

One option I've looked at, and may come back to, is the Boost.Format
library. For now, I want to see if I can find a reasonably elegant way of
using the C++ format manipulators. Does anybody have a systematic approach
to this kind of situation?

With C++ io manipulators it would look ugly and much more error-prone
then a simple format string. The only trouble with printf is that it's
not type safe and it requires experience to know its pitfalls and use
it safely.

C++ standard streams and formatting are really clumsy.
 
E

Earl Purple

Maxim said:
With C++ io manipulators it would look ugly and much more error-prone
then a simple format string. The only trouble with printf is that it's
not type safe and it requires experience to know its pitfalls and use
it safely.

C++ standard streams and formatting are really clumsy.

That's why you can use boost::format which has the advantages of printf
and uses printf formatting, but also doesn't have the disadvantages of
the lack of type-safety and extensibility. (Extensibility in the type
of streams, not the type of data that can be given a formatting code).

(You can always extend your own objects to produce strings, of
different formats if required).
 
E

Earl Purple

Steven said:
OK, I take back the nasty stuff I said about printf. At least until I see a
similarly concise way of writing this using C++ formatters. I want to
convert the following to something I can put onto a C++ std::eek:stream:

printf( " [%2x] %-20s %-8.8s %08x %06x %02x %-3.3s %02x %04x %02x\n",
i,
std::string( pSec->GetName() ).substr( 0, 20 ).c_str(),
SectionTypes( pSec->GetType() ).c_str(),
pSec->GetAddress(),
pSec->GetSize(),
pSec->GetEntrySize(),
SectionFlags( pSec->GetFlags() ).c_str(),
pSec->GetLink(),
pSec->GetInfo(),
pSec->GetAddrAlign() );

One option I've looked at, and may come back to, is the Boost.Format
library. For now, I want to see if I can find a reasonably elegant way of
using the C++ format manipulators. Does anybody have a systematic approach
to this kind of situation?

In this particular instance though you have a lot of calls to pSec. Now
you might want to keep this a free function rather than a member
function, and maybe the class is not your own.

However it is inflexible as you can only output to the console or
wherever the console is redirected to. Also are you always going to
output to this particular format or are you going to modify it? And
remember type-safety - if, for example, you allow users to pick their
own format string so they can output in different formats, and their
format string doesn't comply with your function, then it will still
compile beautifully but could go "bang!" when you run it.

pSec is obviously a pointer to something, and it can't be NULL, and
presumably it only reads and the class it reads from is const-correct
so I'd change from a pointer to a const reference.

Next, if you really feel you must output then use sprintf - at least
here you know how big a buffer you need, so then you can get your
function to return what you have constructed converting it to a
std::string. (But I would go with boost::format).

Alternatively, your function could take an ostream& parameter and
return it. If the user wants a string they will use ostringstream. If
this is the only way you are ever going to format the object then you
may as well make this

std::eek:stream & operator<<( std::eek:stream &, const Section & );

Assuming Section is the name of your class. (As the first element i is
probably unrelated you would stream that in separately).
 
P

__PPS__

If I were you I'd use boost.format :)

here's how:
#include <boost/format.hpp>

class pSec_Class {
...
...
friend std::eek:stream& opeartor<<
(std:eek:stream& os, const pSec_Class &x){
static boost::format frmt("your %1% format %2% string .?"
"some other vars?..");
os << frmt % x.GetType().c_str() % x.GetSize(); // ...
return os;
}
};

....
std::cout << *pSec << std::endl;
 
S

Steven T. Hatton

__PPS__ said:
If I were you I'd use boost.format :)

here's how:
#include <boost/format.hpp>

class pSec_Class {
...
...
friend std::eek:stream& opeartor<<
(std:eek:stream& os, const pSec_Class &x){
static boost::format frmt("your %1% format %2% string .?"
"some other vars?..");
os << frmt % x.GetType().c_str() % x.GetSize(); // ...
return os;
}
};

...
std::cout << *pSec << std::endl;

I probably should have worked through using the Boost.Format library. It
started looking a bit obscure when I tried to write it all out. What I
ended up doing was using brute force and C++ manipulators. It's not too
terribly ugly. I did create an operator<<() similar to what you show
above. Once I realized that there are two different things called `hex',
one being std::hex, and the other being ios_base::hex, and that one is a
value while the other is a function, things became much easier. That is a
gotch from hell. I couldn't figure out, for the life of me, why the
manipulator was not changing the format, but, instead, simply printing as a
numerical value.
 
P

__PPS__

As far as I remember boost.format supports printf-like syntax. Probably
you can do like this:
static boost format frmt("printf-like string");
....
read docs for boost.format
 
P

Pierre Couderc

Steven T. Hatton a écrit :
OK, I take back the nasty stuff I said about printf. At least until I see a
similarly concise way of writing this using C++ formatters. I want to
convert the following to something I can put onto a C++ std::eek:stream:

printf( " [%2x] %-20s %-8.8s %08x %06x %02x %-3.3s %02x %04x %02x\n",
i,
std::string( pSec->GetName() ).substr( 0, 20 ).c_str(),
SectionTypes( pSec->GetType() ).c_str(),
pSec->GetAddress(),
pSec->GetSize(),
pSec->GetEntrySize(),
SectionFlags( pSec->GetFlags() ).c_str(),
pSec->GetLink(),
pSec->GetInfo(),
pSec->GetAddrAlign() );

One option I've looked at, and may come back to, is the Boost.Format
library. For now, I want to see if I can find a reasonably elegant way of
using the C++ format manipulators. Does anybody have a systematic approach
to this kind of situation?

Is not your purpose vain?
Formatting has been well done once with printf specifications.
I do not think that C++ formatters are intended to replace printf
formatting, but to allow a quick not-so-well formatted output.
But if you want to well control printing, it is easier to turn back to
printf-like formatting.
Please note that it is what MS has done with its CString::Format()
Anyway, what seems to me missing is a bridge between printf-like
formatting and <string>.
 
S

Steven T. Hatton

Pierre said:
Steven T. Hatton a écrit :
OK, I take back the nasty stuff I said about printf. At least until I
see a similarly concise way of writing this using C++ formatters. I want
to convert the following to something I can put onto a C++ std::eek:stream:

printf( " [%2x] %-20s %-8.8s %08x %06x %02x %-3.3s %02x %04x %02x\n",
i,
std::string( pSec->GetName() ).substr( 0, 20 ).c_str(),
SectionTypes( pSec->GetType() ).c_str(),
pSec->GetAddress(),
pSec->GetSize(),
pSec->GetEntrySize(),
SectionFlags( pSec->GetFlags() ).c_str(),
pSec->GetLink(),
pSec->GetInfo(),
pSec->GetAddrAlign() );

One option I've looked at, and may come back to, is the Boost.Format
library. For now, I want to see if I can find a reasonably elegant way
of
using the C++ format manipulators. Does anybody have a systematic
approach to this kind of situation?

Is not your purpose vain?
Formatting has been well done once with printf specifications.
I do not think that C++ formatters are intended to replace printf
formatting, but to allow a quick not-so-well formatted output.
But if you want to well control printing, it is easier to turn back to
printf-like formatting.
Please note that it is what MS has done with its CString::Format()
Anyway, what seems to me missing is a bridge between printf-like
formatting and <string>.

But how do you use printf with std::eek:stream? The biggest obstacle I've
found with the C++ formatters is that there is no way that I am aware of to
truncate with them.
 
R

Richard Herring

Pierre Couderc said:
Steven T. Hatton a écrit :
OK, I take back the nasty stuff I said about printf. At least until I see a
similarly concise way of writing this using C++ formatters. I want to
convert the following to something I can put onto a C++ std::eek:stream:
printf( " [%2x] %-20s %-8.8s %08x %06x %02x %-3.3s %02x %04x
%02x\n",
i,
std::string( pSec->GetName() ).substr( 0, 20 ).c_str(),
SectionTypes( pSec->GetType() ).c_str(),
pSec->GetAddress(),
pSec->GetSize(),
pSec->GetEntrySize(),
SectionFlags( pSec->GetFlags() ).c_str(),
pSec->GetLink(),
pSec->GetInfo(),
pSec->GetAddrAlign() );
One option I've looked at, and may come back to, is the Boost.Format
library. For now, I want to see if I can find a reasonably elegant way of
using the C++ format manipulators. Does anybody have a systematic approach
to this kind of situation?

Is not your purpose vain?
Formatting has been well done once with printf specifications.
I do not think that C++ formatters are intended to replace printf
formatting, but to allow a quick not-so-well formatted output.

I don't see why that should be. You may not like the syntax, but they
allow pretty much the same degree of control as the printf family.

Something that C++ streams support which printf doesn't is the principle
that a class should know best how to format itself. of course it's not
true for all classes, but when it does apply it's a way of working with
the available tools instead of trying to work around them. Compare the
example above with this:

cout << *pSec;
But if you want to well control printing, it is easier to turn back to
printf-like formatting.
Please note that it is what MS has done with its CString::Format()

I wouldn't offer *that* as a paradigm of progressive software
development ;-)
 
H

Howard

But how do you use printf with std::eek:stream? The biggest obstacle I've
found with the C++ formatters is that there is no way that I am aware of
to
truncate with them.
--


You could use sprintf to put it in a char array, then put that on the
stream.

(I'd still rather use the streams directly, under control of the class
instead of external to it like your example, though.)

-Howard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top