C++ format 格式化字符串实现方式

C++ format 格式化字符串实现方式

2018年04月23日 10:18:03 slitaz 阅读数 8088更多

分类专栏: C++11

1.

http://stackoverflow.com/questions/2342162/stdstring-formatting-like-sprintf

You can't do it directly, because you don't have write access to the underlying buffer (until C++11; see Dietrich Epp's comment). You'll have to do it first in a c-string, then copy it into a std::string:

charbuff[100];

snprintf(buff, sizeof(buff),"%s","Hello");

std::stringbuffAsStdStr = buff;

But I'm not sure why you wouldn't just use a string stream? I'm assuming you have specific reasons to not just do this:

  std::ostringstream stringStream;

stringStream <<"Hello";

std::stringcopyOfStr = stringStream.str();

2.

https://www.zhihu.com/question/35967887/answer/125238385

3.

boost::format

4.

http://stackoverflow.com/questions/2342162/stdstring-formatting-like-sprintf

Emphasising C++11std::snprintf, this becomes a pretty easyandsafe task. I see a lotofanswersonthis question that were apparently written before the timeofC++11whichusefixed buffer lengthsandvargs, something I wouldnotrecommendforsafety, efficiencyandclarity reasons.

#include

#include

#include

#include

usingnamespacestd;//Don't if you're in a header-file

template

stringstring_format(conststd::string& format, Args ... args )

{

    size_t size = snprintf( nullptr, 0, format.c_str(), args ... ) + 1; // Extra space for '\0'

unique_ptr buf(new char[ size ] );

    snprintf( buf.get(), size, format.c_str(), args ... );

    return string( buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside

}

Line by line explanation:

Aim:Writetoa char* by using  std::snprintfandthenconvert thattoa std::string.

First, we determine the desired lengthofthe chararray.

From cppreference.com:

Return value

[...]Ifthe resultingstringgets truncated duetobuf_size limit,functionreturnsthetotalnumberofcharacters(notincluding the terminatingnull-byte)whichwouldhavebeenwritten,ifthelimitwasnotimposed.

Thismeansthatthedesiredsizeisthenumberofcharactersplusone,sothatthenull-terminatorwillsitafterallothercharactersandthatitcanbecutoffbythestringconstructoragain.Thisissuewasexplainedby@alexk7inthecomments.

Then,weallocateanewcharacterarrayandassignittoastd::unique_ptr. Thisisgenerally advised,asyou won't have to manually delete it again.

Note that this is not a safe way to allocate a unique_ptr with user-defined types as you can not deallocate the memory if the constructor throws an exception!

After that, we can of course just use snprintf for its intended use and write the formatted string to the char[] and afterwards create and return a new std::string from that.

You can see an example in action here.

Additional information for Visual Studio users:

As explained in this answer, Microsoft renamed std::snprintf to _snprintf (yes, without std::). MS further set it as deprecated and advises to use _snprintf_s instead, however _snprintf_s won't accept the buffertobe zeroorsmaller than the formatted outputandwillnotcalculate the outputs lengthifthat occurs. Soinordertoget ridofthe deprecation warnings during compilation, you can insert the following line at the topofthefilewhich contains theuseof_snprintf:

#pragma warning(disable :4996)

5.

https://github.com/fmtlib/fmt#compile-time-and-code-bloat

fmt is an open-source formatting library for C++. It can be used as a safe alternative to printf or as a fast alternative to IOStreams.

6.

https://github.com/c42f/tinyformat

tinyformat.h is a type safe printf replacement library in a single C++ header file. If you've ever wanted printf("%s", s) to just work regardless of the type of s, tinyformat might be for you. Design goals include:

Type safety and extensibility for user defined types.

C99 printf() compatibility, to the extent possible using std::ostream

Simplicity and minimalism. A single header file to include and distribute with your projects.

Augment rather than replace the standard stream formatting mechanism

C++98 support, with optional C++11 niceties

你可能感兴趣的:(C++ format 格式化字符串实现方式)