[Effective-cpp] Item 2: The String Formatters of Manor Farm, Part 1: sprintf

Balog Pal pasa at lib.hu
Sun Oct 31 08:26:27 EST 2004


----- Original Message -----
From: "Paul Grenyer" <paul at paulgrenyer.co.uk>

> > No length safety is a prblem everyone shall be aware.
>
> Shall or should? :-)

Guess tohse paying attention shall the rest should.  Or somethig like that.
:->

> Have you read the item? This is all covered.

No, my book is sheduled to arrive mid-november, till then I folloow gotw and
the discussion -- I found no gotw on this topic, did I miss it?.

> > There are tamed versions, like MFC's CString::Format().  It uses the
same
> > format string and argument row, just the result goes to a handled memory
> > block.  The library calculates the needed length and it never overflows.
>
> This is a nice clean list. Don't go mentioning things like the MFC. ;-)

The point is such wraper can be written or an existing solution can be put
to use.

> > This point is very narrow that way.  sprintf is a ... taking function.
In
> > C++ such functions are rare, and I observed the programmers are growing
> > unaware of its nature.
>
> That is probably a good thing. Are there any C++ functions that do use
...?
> Or is it only functions inheritted from C?

I'm 99% sure C++ has no genuine ... functions, just inherits the C elements.
But the inherited is a first class citizen -- and not to be abandoned
without good reason.

> More to the point, does anyone really like CString?

I do. :)  Interesting, I could talk a whole day about problems with MFC, but
CString is just a good thing there, well designed in interface and works
well in the field too.  I used like a dozen different string classes in my
life, then going greenfield I tend to pick CString among them.

> Also, I don't think it
> is really relevant to the discussion as it is non-standard (hmmm...that
> kinds counts boost::lexical_cast out too, but at least it works on
multiple
> platforms).

This is an accu/C++ duscussion, not c.s.c++. IMHO we shall talk about what
is good to use and what is bad -- standard has some edge but something
getting in doesn't mean it is good too.   Especially std::string  looks more
like a monster.
Though string discussion is really beyond thos thread -- we can take it to
clcm.

> > To avoid the ...-related problems I created a set of type-converter
> > functions and every argument is passed through them.  The functions just
> do
> > an implicit cast, the catch is they know the proper target type.
>
> (snip)
>
> Wow! Why not just use std::stringstream?

That probably belongs to the next topic -- but why not discuss it. :)

First, my post was not about "use this" but more "*if* you pick that road
better walk *that* way".  The urge to cover holes puts them under
spotlights, and certainly make people think alternatives.

streams are one such alternative.  i personally liked streams right from my
first meeting C++ -- certainly those were ARM streams and iostream.h not the
current ones. And I use them too -- when the output goes to a stream
directly.
They are good and easy to use -- but only as long as you need no heavy
formatting.

It is possible to explain the stream I want the item formatted as "%08X" but
that would need a full line of arcane manipulators -- and some of them even
works "sticky", dragging a new set of problems.

So instead of manipulators I use microformatters. I call microformatters a
family of funcitons of form

String ToString(TYPE item, FORMATDESC format = def [, more format] );

with a library defining lots of such functions for the builtin types, then
anyone can add more stuff for the UDTs.  String is ceratinly the string
class used in the envoronment, the format desc can be the same used in
sprintf (const char *) or a series of native format descriptors.

So at the end of the day you use the stream without stream-specific
formatters, just dumping items where it is okey, or ToString(item)-s where
format is needed.

And that could be used with stringstream the same way -- but what is the
point? If I want a string as a result, it emegres pretty well just using
operator + on the same elements.  I found the code is more readable that
way.


Another property of using the stream way is what Attila already mentioned --
it scatters the result.  What may or may not be a problem depending on what
you do.  Eg. when the code creates a WHERE part for an sql statement, it is
IMHO way more readable to see

filter.Format(" keycol = %d and ( datecol >= '%s' or daycol = %d  ) ",  ...)

than the alternative assembled the stream way.  Though messing up the
arguments is possible, my experience shows more problems with messing up the
*literal* part of the string. ;-)  Also when you just read the code looking
for some spots, his way serves better.





More information about the Effective-cpp mailing list