Je dois formater std::string
avec sprintf
et à l'envoyer en fichier stream. Comment puis-je faire cela?
Réponses
Trop de publicités?Vous ne pouvez pas le faire directement, parce que vous n'avez pas accès en écriture à la sous-jacentes de la mémoire tampon. Vous aurez à faire en premier dans un c-string, puis copiez-la dans un std::string:
char buff[100];
sprintf(buff, "%s", "Hello");
std::string buffAsStdStr = buff;
Mais je ne suis pas sûr pourquoi vous ne vous contentez pas d'utiliser une chaîne de stream? Je suis en supposant que vous avez des raisons de ne pas tout simplement faire ceci:
std::ostringstream stringStream;
stringStream << "Hello";
std::string copyOfStr = stringStream.str();
#include <stdarg.h> // for va_start, etc
std::string string_format(const std::string fmt, ...) {
int size = ((int)fmt_str.size()) * 2 + 50; // use a rubric appropriate for your code
std::string str;
va_list ap;
while (1) { // maximum 2 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 (o/s specific)
}
return str;
}
EDIT: un moyen plus sûr et plus efficace (je l'ai testé et il est plus rapide) approche:
#include <stdarg.h> // for va_start, etc
#include <memory> // for std::unique_ptr
std::string string_format(const std::string fmt_str, ...) {
int final_n, n = ((int)fmt_str.size()) * 2; /* reserve 2 times as much as the length of the fmt_str */
std::string str;
std::unique_ptr<char[]> 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::string(formatted.get());
}
Le fmt_str est passé par valeur conforme aux exigences de va_start.
REMARQUE: le plus sûr et le plus rapide de la version ne fonctionne pas sur certains systèmes. Par conséquent, les deux sont toujours répertoriés. Aussi, "plus vite" dépend entièrement de la preallocation étape étant correcte, sinon la fonction strcpy le rend plus lent.
Si vous souhaitez utiliser un format de chaîne de caractères, essayez de Boost.Format.
J'ai écrit mon propre en utilisant vsnprintf elle retourne la chaîne au lieu d'avoir à créer mon propre tampon.
#include <string>
#include <cstdarg>
//missing string printf
//this is safe and convenient but not exactly efficient
inline std::string 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;
}
De sorte que vous pouvez l'utiliser comme
std::string mystr = format("%s %d %10.5f", "omg", 1, 10.5);
Si vous voulez seulement un printf syntaxe (sans faire appel à printf vous-même), ont un oeil à Stimuler Format.