C++ inline String formatting and numeric conversion
Asked Answered
E

7

5

C# has a nice static method

String.Format(string, params string[]);

that returns a new string with the formatting and values that are provided. Is there an equivalent in C++?

The reason is because I'm using log4cxx and want to take advantage of the macros like

LOG4CXX_DEBUG( logger, expr );

that uses short-circuit evaluation so that expr is never evaluated if the log level DEBUG is not enabled.

Currently, in C++, I do it like this:

CString msg;
msg.Format( formatString, values... );

LOG4CXX_INFO( _logger, msg );

which is defeating the purpose since I have to allocate and format the string first so there isn't nearly as efficiency coming out of the short-circuit logic.

There's a similar problem when trying to do simple logging with numerical values. This, won't compile:

LOG4CXX_DEBUG( _logger, "the price is " + _some-double_);

So I end up having to write something like this:

CString asStr;
asStr.Format( "%d", _some-double_ );
LOG4CXX_DEBUG( _logger, "the price is " + asStr );

which again defeats the purpose.

I'm not at all a C++ expert so I'm hoping more knowledgeable people can help.

Edmonds answered 19/8, 2009 at 5:17 Comment(0)
S
9

log4cxx accepts stream like parameters, so you can write, for example:

LOG4CXX_DEBUG( _logger, "the price is " << price );
Sorbose answered 19/8, 2009 at 5:43 Comment(0)
R
4

You can fall back to C and use sprintf

printf(stderr,"The Error(%d) happened(%s)\n",error,errmsg(error));

Boost also has a format.

// iostream with boost::format
std::cerr << boost::format("The Error(%d) happened(%s)\n") % error % errmsg(error);

If you want to shortcut

logger && (std::cerr << Stuff); // Where Stuff can be your boost::format
Reyreyes answered 19/8, 2009 at 5:48 Comment(0)
R
3

Using the standard libraries, there is no way to produce a formatted string without some type of memory allocation on your part. The C++ string class does not have a "format" function per se, so you must use a stringstream object in order to concatenate numbers with text, but that would involve allocating the object. Looking at C functions like sprintf, you need to allocate a char array beforehand since sprintf does not allocate any memory itself.

That said, even if there existed a static function such as "string::format" I doubt you would get much of a speed advantage over allocating a stringstream object yourself and manipulating it, given that the static function would most likely be doing the same things in the background in any event.

Radarman answered 19/8, 2009 at 5:35 Comment(1)
I should add though that, given you will have to allocate at least some memory, I would take the sprintf/char array route, since it's much faster to allocate a POD array over an object.Radarman
V
3

My favorite way to do inline formating is with the boost.format library. For example:

#include <boost/format.hpp>
using namespace boost;

LOG4CXX_INFO( _logger, str(format("cheese it %i, %g") % 1234 % 1.3) );

It's very handy for using variable arguments in logging and macro functions.

Valdez answered 19/8, 2009 at 5:49 Comment(0)
K
2

Either use the boost format library or else handcode your own little version (like make_string here).

Kenton answered 19/8, 2009 at 6:30 Comment(0)
C
0

This is not strictly what you asked but a different solution, your main problem appeared to be the extra work when not in debug mode.

You could just do this

    #ifdef _DEBUG
    CString msg;
    msg.Format( formatString, values... );
    #endif
    LOG4CXX_INFO( _logger, msg );
Calliope answered 21/1, 2022 at 4:27 Comment(0)
H
0

If you are using Microsoft CString class, you probably want to use this helper:

CString FormatV(LPCTSTR pszFormat, ...);

CString FormatV(LPCTSTR pszFormat, ...)
{
   ASSERT(pszFormat != NULL);
   va_list args;
   va_start(args, pszFormat);
   CString str;
   str.FormatV(pszFormat, args);
   va_end(args);
   return str;
}

LOG4CXX_DEBUG( _logger, FormatV("the price is %d", price));

For standard strings, there is std::format since C++20.

Heymann answered 30/3, 2022 at 12:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.