std :: ssortingng formatage comme sprintf

Je dois formater std::ssortingng avec sprintf et l’envoyer dans le stream de fichiers. Comment puis-je faire ceci?

Vous ne pouvez pas le faire directement, car vous n’avez pas access en écriture au tampon sous-jacent (jusqu’à ce que C ++ 11; voir le commentaire de Diesortingch Epp). Vous devrez d’abord le faire dans une chaîne de caractères, puis le copier dans une chaîne std ::

  char buff[100]; snprintf(buff, sizeof(buff), "%s", "Hello"); std::ssortingng buffAsStdStr = buff; 

Mais je ne sais pas pourquoi vous n’utiliseriez pas simplement un stream de chaînes? Je suppose que vous avez des raisons spécifiques de ne pas simplement faire ceci:

  std::ossortingngstream ssortingngStream; ssortingngStream << "Hello"; std::string copyOfStr = stringStream.str(); 

C ++ 11 solution qui utilise vsnprintf() interne:

 #include  // For va_start, etc. std::ssortingng ssortingng_format(const std::ssortingng fmt, ...) { int size = ((int)fmt.size()) * 2 + 50; // Use a rubric appropriate for your code std::ssortingng str; va_list ap; while (1) { // Maximum two passes on a POSIX system... str.resize(size); va_start(ap, fmt); int n = vsnprintf((char *)str.data(), size, fmt.c_str(), ap); va_end(ap); if (n > -1 && n < size) { // Everything worked str.resize(n); return str; } if (n > -1) // Needed size returned size = n + 1; // For null char else size *= 2; // Guess at a larger size (OS specific) } return str; } 

Une approche plus sûre et plus efficace (je l’ai testée et plus rapide):

 #include  // For va_start, etc. #include  // For std::unique_ptr std::ssortingng ssortingng_format(const std::ssortingng fmt_str, ...) { int final_n, n = ((int)fmt_str.size()) * 2; /* Reserve two times as much as the length of the fmt_str */ std::unique_ptr formatted; va_list ap; while(1) { formatted.reset(new char[n]); /* Wrap the plain char array into the unique_ptr */ strcpy(&formatted[0], fmt_str.c_str()); va_start(ap, fmt_str); final_n = vsnprintf(&formatted[0], n, fmt_str.c_str(), ap); va_end(ap); if (final_n < 0 || final_n >= n) n += abs(final_n - n + 1); else break; } return std::ssortingng(formatted.get()); } 

fmt_str est passé par valeur pour être conforme aux exigences de va_start .

REMARQUE: La version “plus sûre” et “plus rapide” ne fonctionne pas sur certains systèmes. Par conséquent, les deux sont toujours répertoriés. De même, “plus rapide” dépend entièrement de ce que l’étape de préallocation est correcte, sinon le strcpy rend plus lent.

En utilisant C ++ 11 std::snprintf , cela devient une tâche facile et sûre. Je vois beaucoup de réponses sur cette question qui ont apparemment été écrites avant C ++ 11 et qui utilisent des longueurs de tampons et des variables fixes, ce que je ne recommanderais pas pour des raisons de sécurité, d’efficacité et de clarté.

 #include  #include  #include  #include  using namespace std; //Don't if you're in a header-file template ssortingng ssortingng_format( const std::ssortingng& 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 ssortingng( buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside } 

L’extrait de code ci-dessus est sous licence CC0 1.0 .

Explication ligne par ligne:

Objectif: Ecrire dans un caractère char* en utilisant std::snprintf , puis convertir cela en une std::ssortingng .

Tout d’abord, nous déterminons la longueur souhaitée du tableau de caractères.

De cppreference.com :

Valeur de retour

[…] Si la chaîne résultante est tronquée en raison de la limite de buf_size, la fonction renvoie le nombre total de caractères (non compris le null-octet final) qui aurait été écrit si la limite n’était pas imposée.

Cela signifie que la taille souhaitée est le nombre de caractères plus un , de sorte que le caractère NULL-Termator se place après tous les autres caractères et qu’il peut être coupé à nouveau par le constructeur de chaînes. Ce problème a été expliqué par @ alexk7 dans les commentaires.

Ensuite, nous allouons un nouveau tableau de caractères et l’affectons à un std::unique_ptr . Cela est généralement conseillé, car vous ne devrez plus le delete manuellement.

Notez que ce n’est pas un moyen sûr d’allouer un unique_ptr avec des types définis par l’utilisateur car vous ne pouvez pas désallouer la mémoire si le constructeur lève une exception!

Après cela, nous pouvons bien entendu utiliser snprintf pour son utilisation prévue et écrire la chaîne formatée dans le char[] et ensuite créer et renvoyer une nouvelle std::ssortingng partir de celle-ci.


Vous pouvez voir un exemple en action ici .


Si vous souhaitez également utiliser std::ssortingng dans la liste des arguments, consultez cette liste .


Informations supplémentaires pour les utilisateurs Visual Studio :

Comme expliqué dans cette réponse , Microsoft a renommé std::snprintf en _snprintf (oui, sans std:: _snprintf . MS le définit en outre comme obsolète et conseille d’utiliser plutôt _snprintf_s , cependant _snprintf_s n’acceptera pas que le tampon soit nul ou plus petit que la sortie formatée et ne calculera pas la longueur des sorties si cela se produit. Donc, pour se débarrasser des avertissements de dépréciation lors de la compilation, vous pouvez insérer la ligne suivante en haut du fichier qui contient l’utilisation de _snprintf :

 #pragma warning(disable : 4996) 

boost::format() fournit la fonctionnalité souhaitée:

A partir du format synchrone des librairies Boost:

Un object de format est construit à partir d’une chaîne de format et reçoit ensuite des arguments via des appels répétés à l’opérateur%. Chacun de ces arguments est ensuite converti en chaînes, qui sont à leur tour combinées en une chaîne, en fonction de la chaîne de format.

 #include  cout << boost::format("writing %1%, x=%2% : %3%-th try") % "toto" % 40.23 % 50; // prints "writing toto, x=40.230 : 50-th try" 

Malheureusement, la plupart des réponses ici utilisent des varargs qui sont insortingnsèquement peu sûrs, sauf si vous utilisez quelque chose comme l’atsortingbut format de GCC qui ne fonctionne qu’avec des chaînes de format littéral. Vous pouvez voir pourquoi ces fonctions ne sont pas sûres dans l’exemple suivant:

 std::ssortingng format_str = "%s"; ssortingng_format(format_str, format_str[0]); 

ssortingng_format est une implémentation de la réponse d’Erik Aronesty. Ce code comstack, mais il va probablement tomber en panne lorsque vous essayez de l’exécuter:

 $ g++ -Wall -Wextra -pedantic test.cc $ ./a.out Segmentation fault: 11 

Il est possible d’implémenter un printf sécurisé et de l’étendre pour formater std::ssortingng utilisant des modèles (variadic). Cela a été fait dans la bibliothèque fmt , qui fournit une alternative sûre à sprintf retournant std::ssortingng :

 std::ssortingng format_str = "The answer is %d"; std::ssortingng result = fmt::sprintf(format_str, 42); 

fmt garde la trace des types d’argument et si le type ne correspond pas à la spécification de format, il n’y a pas d’erreur de segmentation, juste une exception.

Disclaimer : Je suis l’auteur de cette bibliothèque.

Si vous souhaitez uniquement une syntaxe de type printf (sans appeler vous-même printf), consultez le format Boost .

J’ai écrit mon propre en utilisant vsnprintf afin qu’il retourne une chaîne au lieu d’avoir à créer mon propre tampon.

 #include  #include  //missing ssortingng printf //this is safe and convenient but not exactly efficient inline std::ssortingng format(const char* fmt, ...){ int size = 512; char* buffer = 0; buffer = new char[size]; va_list vl; va_start(vl, fmt); int nsize = vsnprintf(buffer, size, fmt, vl); if(size<=nsize){ //fail delete buffer and try again delete[] buffer; buffer = 0; buffer = new char[nsize+1]; //+1 for /0 nsize = vsnprintf(buffer, size, fmt, vl); } std::string ret(buffer); va_end(vl); delete[] buffer; return ret; } 

Vous pouvez donc l'utiliser comme

 std::ssortingng mystr = format("%s %d %10.5f", "omg", 1, 10.5); 

[edit ’17 / 8/31] Ajout d’une version modélisée variadique ‘vtspf (..)’:

 template const std::ssortingng type_to_ssortingng(const T &v) { std::ossortingngstream ss; ss << v; return ss.str(); }; template const T ssortingng_to_type(const std::ssortingng &str) { std::issortingngstream ss(str); T ret; ss >> ret; return ret; }; template void vtspf_priv(std::ssortingng &s) {} template void vtspf_priv(std::ssortingng &s, H h, P...p) { s+=type_to_ssortingng(h); vtspf_priv(s, p...); } template std::ssortingng temp_vtspf(P...p) { std::ssortingng s(""); vtspf_priv(s, p...); return s; } 

qui est en fait une version délimitée par des virgules (à la place) des << -operators parfois gênants, utilisés comme ceci:

 char chSpace=' '; double pi=3.1415; std::ssortingng sWorld="World", str_var; str_var = vtspf("Hello", ',', chSpace, sWorld, ", pi=", pi); 

[edit] Adapté pour utiliser la technique dans la réponse d'Erik Aronesty (ci-dessus):

 #include  #include  #include  //============================================================================= void spf(std::ssortingng &s, const std::ssortingng fmt, ...) { int n, size=100; bool b=false; va_list marker; while (!b) { s.resize(size); va_start(marker, fmt); n = vsnprintf((char*)s.c_str(), size, fmt.c_str(), marker); va_end(marker); if ((n>0) && ((b=(n0) && ((b=(n 

[réponse précédente]
Une réponse très tardive, mais pour ceux qui, comme moi, aiment le «sprintf»: j'ai écrit et j'utilise les fonctions suivantes. Si vous l'aimez, vous pouvez élargir les options en% pour mieux les adapter au sprint; ceux qui s'y trouvent actuellement suffisent à mes besoins. Vous utilisez ssortingngf () et ssortingngfappend () comme vous le feriez avec sprint. Rappelez-vous simplement que les parameters pour ... doivent être des types POD.

 //============================================================================= void DoFormatting(std::ssortingng& sF, const char* sformat, va_list marker) { char *s, ch=0; int n, i=0, m; long l; double d; std::ssortingng sf = sformat; std::ssortingngstream ss; m = sf.length(); while (i 

Pour formater std::ssortingng de manière ‘sprintf’, appelez snprintf (arguments nullptr et 0 ) pour obtenir la longueur de tampon nécessaire. Ecrivez votre fonction en utilisant le modèle C ++ 11 variadic comme ceci:

 #include  #include  #include  template< typename... Args > std::ssortingng ssortingng_sprintf( const char* format, Args... args ) { int length = std::snprintf( nullptr, 0, format, args... ); assert( length >= 0 ); char* buf = new char[length + 1]; std::snprintf( buf, length + 1, format, args... ); std::ssortingng str( buf ); delete[] buf; return std::move(str); } 

Comstackr avec le support C ++ 11, par exemple dans GCC: g++ -std=c++11

Usage:

  std::cout << string_sprintf("%g, %g\n", 1.23, 0.001); 

Voici ce que fait Google: SsortingngPrintf (Licence BSD)
et facebook le fait de la même façon: SsortingngPrintf (Apache License)
Les deux fournissent un SsortingngAppendF pratique également.

Mes deux cents sur cette question très populaire.

Pour citer la page de manuel des fonctions de type printf :

En cas de retour réussi, ces fonctions renvoient le nombre de caractères imprimés (à l’exclusion de l’octet nul utilisé pour terminer la sortie des chaînes).

Les fonctions snprintf () et vsnprintf () n’écrivent pas plus que des octets de taille (y compris l’octet nul final (‘\ 0’)). Si la sortie a été tronquée en raison de cette limite, la valeur de retour est le nombre de caractères (à l’exclusion de l’octet nul final) qui aurait été écrit dans la chaîne finale si suffisamment d’espace était disponible. Ainsi, une valeur renvoyée de taille ou plus signifie que la sortie a été tronquée.

En d’autres termes, une implémentation saine de C ++ 11 doit être la suivante:

 #include  #include  template  std::ssortingng fmt (const std::ssortingng &fmt, Ts... vs) { char b; size_t required = std::snprintf(&b, 0, fmt.c_str(), vs...) + 1; // See comments: the +1 is necessary, while the first parameter // can also be set to nullptr char bytes[required]; std::snprintf(bytes, required, fmt.c_str(), vs...); return std::ssortingng(bytes); } 

Ca marche assez bien 🙂

Les modèles Variadic ne sont pris en charge que dans C ++ 11. La réponse de pixelpoint montre une technique similaire utilisant des styles de programmation plus anciens.

Il est étrange que C ++ ne soit pas disponible. Ils ont récemment ajouté to_ssortingng() , ce qui à mon avis est un grand pas en avant. Je me demande s’ils vont append un opérateur .format à la std::ssortingng finalement …

modifier

Comme le fait remarquer alexk7, la valeur de retour de std::snprintf nécessite un std::snprintf , car nous avons besoin d’espace pour l’octet \0 . Intuitivement, sur la plupart des architectures qui ne disposent pas du +1 , l’entier required sera partiellement remplacé par un 0 . Cela se produira après l’évaluation de required tant que paramètre réel pour std::snprintf , de sorte que l’effet ne devrait pas être visible.

Ce problème pourrait cependant changer, par exemple avec l’optimisation du compilateur: que se passe-t-il si le compilateur décide d’utiliser un registre pour la variable required ? C’est le genre d’erreurs qui entraînent parfois des problèmes de sécurité.

Basé sur la réponse fournie par Erik Aronesty:

 std::ssortingng ssortingng_format(const std::ssortingng &fmt, ...) { std::vector str(100,'\0'); va_list ap; while (1) { va_start(ap, fmt); auto n = vsnprintf(str.data(), str.size(), fmt.c_str(), ap); va_end(ap); if ((n > -1) && (size_t(n) < str.size())) { return str.data(); } if (n > -1) str.resize( n + 1 ); else str.resize( str.size() * 2); } return str.data(); } 

Cela évite d’avoir à jeter const du résultat de .c_str() qui était dans la réponse d’origine.

 template std::ssortingng ssortingng_format(const char* fmt, Args... args) { size_t size = snprintf(nullptr, 0, fmt, args...); std::ssortingng buf; buf.reserve(size + 1); buf.resize(size); snprintf(&buf[0], size + 1, fmt, args...); return buf; } 

Utiliser C99 Snprintf et C ++ 11

 inline void format(ssortingng& a_ssortingng, const char* fmt, ...) { va_list vl; va_start(vl, fmt); int size = _vscprintf( fmt, vl ); a_ssortingng.resize( ++size ); vsnprintf_s((char*)a_ssortingng.data(), size, _TRUNCATE, fmt, vl); va_end(vl); } 

ssortingng n’a pas ce dont vous avez besoin, mais std :: ssortingngstream le fait. Utilisez un ssortingngstream pour créer la chaîne, puis extrayez la chaîne. Voici une liste complète des choses que vous pouvez faire. Par exemple:

 cout.setprecision(10); //ssortingngstream is a stream like cout 

vous donnera 10 décimales de précision lors de l’impression d’un double ou d’un flottant.

Vous pourriez essayer ceci:

 ssortingng str; str.resize( _MAX_PATH ); sprintf( &str[0], "%s %s", "hello", "world" ); // optionals // sprintf_s( &str[0], str.length(), "%s %s", "hello", "world" ); // Microsoft // #include  // snprintf( &str[0], str.length(), "%s %s", "hello", "world" ); // c++11 str.resize( strlen( str.data() ) + 1 ); 

Testé, réponse à la qualité de la production

 #include  #include  #include  // requires at least C++11 const std::ssortingng vformat(const char * const zcFormat, ...) { // initialize use of the variable argument array va_list vaArgs; va_start(vaArgs, zcFormat); // reliably acquire the size // from a copy of the variable argument array // and a functionally reliable call to mock the formatting va_list vaArgsCopy; va_copy(vaArgsCopy, vaArgs); const int iLen = std::vsnprintf(NULL, 0, zcFormat, vaArgsCopy); va_end(vaArgsCopy); // return a formatted ssortingng without risking memory mismanagement // and without assuming any comstackr or platform specific behavior std::vector zc(iLen + 1); std::vsnprintf(zc.data(), zc.size(), zcFormat, vaArgs); va_end(vaArgs); return std::ssortingng(zc.data(), iLen); } #include  #include  #include  // demonstration of use int main() { std::time_t t = std::time(nullptr); std::cerr << std::put_time(std::localtime(& t), "%D %T") << " [debug]: " << vformat("Int 1 is %d, Int 2 is %d, Int 3 is %d", 11, 22, 33) << std::endl; return 0; } 

C’est le code que j’utilise pour le faire dans mon programme … Ce n’est rien de compliqué, mais ça fait l’affaire … Notez que vous devrez ajuster votre taille le cas échéant. MAX_BUFFER pour moi est 1024.

 std::ssortingng Format ( const char *fmt, ... ) { char textSsortingng[MAX_BUFFER*5] = {'\0'}; // -- Empty the buffer properly to ensure no leaks. memset(textSsortingng, '\0', sizeof(textSsortingng)); va_list args; va_start ( args, fmt ); vsnprintf ( textSsortingng, MAX_BUFFER*5, fmt, args ); va_end ( args ); std::ssortingng retStr = textSsortingng; return retStr; } 

A pris l’idée de la réponse de Dacav et pixelpoint . J’ai joué un peu et j’ai eu ça:

 #include  #include  #include  std::ssortingng format(const char* fmt, ...) { va_list vl; va_start(vl, fmt); int size = vsnprintf(0, 0, fmt, vl) + sizeof('\0'); va_end(vl); char buffer[size]; va_start(vl, fmt); size = vsnprintf(buffer, size, fmt, vl); va_end(vl); return std::ssortingng(buffer, size); } 

Avec une pratique de programmation saine , je pense que le code devrait suffire, mais je suis toujours ouvert à des alternatives plus sécurisées, encore assez simples et ne nécessitant pas C ++ 11.


Et voici une autre version qui utilise un tampon initial pour empêcher le second appel à vsnprintf() lorsque le tampon initial est déjà suffisant.

 std::ssortingng format(const char* fmt, ...) { va_list vl; int size; enum { INITIAL_BUFFER_SIZE = 512 }; { char buffer[INITIAL_BUFFER_SIZE]; va_start(vl, fmt); size = vsnprintf(buffer, INITIAL_BUFFER_SIZE, fmt, vl); va_end(vl); if (size < INITIAL_BUFFER_SIZE) return std::string(buffer, size); } size += sizeof('\0'); char buffer[size]; va_start(vl, fmt); size = vsnprintf(buffer, size, fmt, vl); va_end(vl); return std::string(buffer, size); } 

(Il s'avère que cette version est juste similaire à la réponse de Piti Ongmongkolkul , seulement qu’elle n’utilise pas new et delete[] , et spécifie également une taille lors de la création de std::ssortingng .

L'idée ici de ne pas utiliser new et delete[] est d'impliquer l'utilisation de la stack sur le tas car elle n'a pas besoin d'appeler des fonctions d'allocation et de désallocation, mais si elle n'est pas correctement utilisée, des systèmes peut-être anciens ou peut-être simplement vulnérables). Si cela vous préoccupe, je suggère fortement d'utiliser new et de delete[] . Note that the only concern here is about the allocations as vsnprintf() is already called with limits, so specifying a limit based on the size allocated on the second buffer would also prevent those.)

I usually use this:

 std::ssortingng myformat(const char *const fmt, ...) { char *buffer = NULL; va_list ap; va_start(ap, fmt); (void)vasprintf(&buffer, fmt, ap); va_end(ap); std::ssortingng result = buffer; free(buffer); return result; } 

Disadvantage: not all systems support vasprint

If you are on a system that has asprintf(3) , you can easily wrap it:

 #include  #include  #include  std::ssortingng format(const char *fmt, ...) __atsortingbute__ ((format (printf, 1, 2))); std::ssortingng format(const char *fmt, ...) { std::ssortingng result; va_list ap; va_start(ap, fmt); char *tmp = 0; int res = vasprintf(&tmp, fmt, ap); va_end(ap); if (res != -1) { result = tmp; free(tmp); } else { // The vasprintf call failed, either do nothing and // fall through (will return empty ssortingng) or // throw an exception, if your code uses those } return result; } int main(int argc, char *argv[]) { std::ssortingng username = "you"; std::cout << format("Hello %s! %d", username.c_str(), 123) << std::endl; return 0; } 

Very-very simple solution.

 std::ssortingng strBuf; strBuf.resize(256); int iCharsPrinted = sprintf_s((char *)strPath.c_str(), strPath.size(), ...); strBuf.resize(iCharsPrinted); 

Below slightly modified version of @iFreilicht answer, updated to C++14 (usage of make_unique function instead of raw declaration) and added support for std::ssortingng arguments (based on Kenny Kerr article )

 #include  #include  #include  #include  template  T process_arg(T value) noexcept { return value; } template  T const * process_arg(std::basic_ssortingng const & value) noexcept { return value.c_str(); } template std::ssortingng ssortingng_format(const std::ssortingng& format, Args const & ... args) { const auto fmt = format.c_str(); const size_t size = std::snprintf(nullptr, 0, fmt, process_arg(args) ...) + 1; auto buf = std::make_unique(size); std::snprintf(buf.get(), size, fmt, process_arg(args) ...); auto res = std::ssortingng(buf.get(), buf.get() + size - 1); return res; } int main() { int i = 3; float f = 5.f; char* s0 = "hello"; std::ssortingng s1 = "world"; std::cout << string_format("i=%d, f=%f, s=%s %s", i, f, s0, s1) << "\n"; } 

Sortie:

 i = 3, f = 5.000000, s = hello world 

Feel free to merge this answer with the original one if desired.

One solution I’ve favoured is to do this with sprintf directly into the std::ssortingng buffer, after making said buffer big enough:

 #include  #include  using namespace std; ssortingng l_output; l_output.resize(100); for (int i = 0; i < 1000; ++i) { memset (&l_output[0], 0, 100); sprintf (&l_output[0], "\r%i\0", i); cout << l_output; cout.flush(); } 

So, create the std::ssortingng, resize it, access its buffer directly...

Poco Foundation library has a very convenient format function, which supports std::ssortingng in both the format ssortingng and the values:

You can format C++ output in cout using iomanip header file. Make sure that you include iomanip header file before you use any of the helper functions like setprecision, setfill etc.

Here is a code snippet I have used in the past to print the average waiting time in the vector, which I have “accumulated”.

 #include #include #include #include ... cout<< "Average waiting times for tasks is " << setprecision(4) << accumulate(all(waitingTimes), 0)/double(waitingTimes.size()) ; cout << " and " << Q.size() << " tasks remaining" << endl; 

Here is a brief description of how we can format C++ streams. http://www.cprogramming.com/tutorial/iomanip.html

There can be problems, if the buffer is not large enough to print the ssortingng. You must determine the length of the formatted ssortingng before printing a formatted message in there. I make own helper to this (tested on Windows and Linux GCC ), and you can try use it.

Ssortingng.cpp: http://pastebin.com/DnfvzyKP
Ssortingng.h: http://pastebin.com/7U6iCUMa

Ssortingng.cpp:

 #include  #include  #include  #include  using ::std::ssortingng; #pragma warning(disable : 4996) #ifndef va_copy #ifdef _MSC_VER #define va_copy(dst, src) dst=src #elif !(__cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)) #define va_copy(dst, src) memcpy((void*)dst, (void*)src, sizeof(*src)) #endif #endif /// /// \breif Format message /// \param dst Ssortingng to store formatted message /// \param format Format of message /// \param ap Variable argument list /// void toSsortingng(ssortingng &dst, const char *format, va_list ap) throw() { int length; va_list apStrLen; va_copy(apStrLen, ap); length = vsnprintf(NULL, 0, format, apStrLen); va_end(apStrLen); if (length > 0) { dst.resize(length); vsnprintf((char *)dst.data(), dst.size() + 1, format, ap); } else { dst = "Format error! format: "; dst.append(format); } } /// /// \breif Format message /// \param dst Ssortingng to store formatted message /// \param format Format of message /// \param ... Variable argument list /// void toSsortingng(ssortingng &dst, const char *format, ...) throw() { va_list ap; va_start(ap, format); toSsortingng(dst, format, ap); va_end(ap); } /// /// \breif Format message /// \param format Format of message /// \param ... Variable argument list /// ssortingng toSsortingng(const char *format, ...) throw() { ssortingng dst; va_list ap; va_start(ap, format); toSsortingng(dst, format, ap); va_end(ap); return dst; } /// /// \breif Format message /// \param format Format of message /// \param ap Variable argument list /// ssortingng toSsortingng(const char *format, va_list ap) throw() { ssortingng dst; toSsortingng(dst, format, ap); return dst; } int main() { int a = 32; const char * str = "This works!"; ssortingng test(toSsortingng("\nSome testing: a = %d, %s\n", a, str)); printf(test.c_str()); a = 0x7fffffff; test = toSsortingng("\nMore testing: a = %d, %s\n", a, "This works too.."); printf(test.c_str()); a = 0x80000000; toSsortingng(test, "\nMore testing: a = %d, %s\n", a, "This way is cheaper"); printf(test.c_str()); return 0; } 

Ssortingng.h:

 #pragma once #include  #include  using ::std::ssortingng; /// /// \breif Format message /// \param dst Ssortingng to store formatted message /// \param format Format of message /// \param ap Variable argument list /// void toSsortingng(ssortingng &dst, const char *format, va_list ap) throw(); /// /// \breif Format message /// \param dst Ssortingng to store formatted message /// \param format Format of message /// \param ... Variable argument list /// void toSsortingng(ssortingng &dst, const char *format, ...) throw(); /// /// \breif Format message /// \param format Format of message /// \param ... Variable argument list /// ssortingng toSsortingng(const char *format, ...) throw(); /// /// \breif Format message /// \param format Format of message /// \param ap Variable argument list /// ssortingng toSsortingng(const char *format, va_list ap) throw(); 

I gave it a try, with regular expressions . I implemented it for ints and const ssortingngs as an example, but you can add whatever other types ( POD types but with pointers you can print anything).

 #include  #include  #include  #include  #include  static std::ssortingng formatArg(std::ssortingng argDescr, va_list args) { std::ssortingngstream ss; if (argDescr == "i") { int val = va_arg(args, int); ss << val; return ss.str(); } if (argDescr == "s") { const char *val = va_arg(args, const char*); ss << val; return ss.str(); } assert(0); //Not implemented } std::string format(std::string fmt, ...) { std::string result(fmt); va_list args; va_start(args, fmt); std::regex e("\\{([^\\{\\}]+)\\}"); std::smatch m; while (std::regex_search(fmt, m, e)) { std::string formattedArg = formatArg(m[1].str(), args); fmt.replace(m.position(), m.length(), formattedArg); } va_end(args); return fmt; } 

Here is an example of use of it:

 std::ssortingng formatted = format("I am {s} and I have {i} cats", "bob", 3); std::cout << formatted << std::endl; 

Sortie:

I am bob and I have 3 cats

this can be sortinged out. simple. really does not use nuances of the ssortingng class though.

 #include  #include  #include  #include  #include  #include  using namespace std; //--------------------------------------------------------------------- class SsortingngFormatter { public: static ssortingng format(const char *format, ...); }; ssortingng SsortingngFormatter::format(const char *format, ...) { va_list argptr; va_start(argptr, format); char *ptr; size_t size; FILE *fp_mem = open_memstream(&ptr, &size); assert(fp_mem); vfprintf (fp_mem, format, argptr); fclose (fp_mem); va_end(argptr); ssortingng ret = ptr; free(ptr); return ret; } //--------------------------------------------------------------------- int main(void) { ssortingng temp = SsortingngFormatter::format("my age is %d", 100); printf("%s\n", temp.c_str()); return 0; } 
 _return.desc = (boost::format("fail to detect. cv_result = %d") % st_result).str();