myWallJSON
myWallJSON

Reputation: 9512

How to implement in C++ crossplatform snprintf?

I wonder if it is possible and how to implement in C++ crossplatform, (C99, C++0x independent ) snprintf? Is there such in boost? (I wonder about what is the C++ idiom to replace snprintf(4)?)

Upvotes: 0

Views: 1415

Answers (6)

eci
eci

Reputation: 2422

std::ostringstream or std::to_string (c++11) works as an alternative, but if you require a better performance solution without extra copies or do only have C not C++ you might need to do something else:

MSVC does not support C99 and therefore has not snprintf function but only their selfmade: _snprintf.

Differences between MSVCs _snprintf and official C99 (gcc,clang) snprintf:

Return value:

  • MSVC: return -1 if buffer size not enough to write everything (not including terminating null!)
  • GCC: return number of characters that would have been written if buffer large enough

Written bytes:

  • MSVC: write as much as possible, do not write NULL at end if no space left
  • GCC: write as much as possible, always write terminating NULL (exception: buffer_size=0)

Interesting %n subtlety: If you use %n in your code, MSVC will leave it unitialized! if it it stops parsing because buffer size is to small, GCC will always write number of bytes which would have been written if buffer would have been large enough.

So my proposal would be to write your own wrapper function mysnprintf using vsnprintf / _vsnprintf which gives same return values and writes the same bytes on both platforms (be careful: %n is more difficult to fix).

Upvotes: 0

user184968
user184968

Reputation:

Once I needed snprintf on Windows/Linux/HP-UX. I defined snprintf_safe and on Linux/HP-UX I made use of snprinf and on Windows I made use of _snprintf. I remember that _snprintf has a little bit different approach to writing '\0' if the number of bytes required to store the data exceeds the maximum allowed size. So It was necessary to handle. Anyway, it was this kind of macro:

#ifdef #WIN32
int snprintf_safe()
{
  // make use of _snprintf
}
#else
   #define snprintf_safe snprintf
#endif

Upvotes: 0

hmjd
hmjd

Reputation: 122001

std::ostringstream would be an alterntive to using snprintf:

char buf[1024];
snprintf(buf, 1024, "%d%s", 4, "hello");

Equivalent:

#include <sstream>

std::ostringstream s;
s << 4 << "hello";
// s.str().c_str(); // This returns `const char*` to constructed string.

There is also boost::lexical_cast:

std::string s = boost::lexical_cast<std::string>(4) +
                    boost::lexical_cast<std::string>("hello");

Upvotes: 6

Matthieu M.
Matthieu M.

Reputation: 299999

Since Boost was mentionned, is there anything wrong with Boost.Format ?

Upvotes: 1

zch
zch

Reputation: 15278

Yes, there is Boost Format library that supports formatting strings.

Upvotes: 2

Wes Hardaker
Wes Hardaker

Reputation: 22262

You might want to look at the Qt QString class, which provides a format function which does about what you want in a very OO sort of way. You could certainly copy and learn from it.

yes, it might be taboo to mention Qt in a question that was tagged boost, but the question seemed more generic than that.

Upvotes: 1

Related Questions