520 votes

std::string mise en forme comme sprintf

Je dois formater std::string avec sprintf et à l'envoyer en fichier stream. Comment puis-je faire cela?

390voto

Doug T. Points 33360

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();

248voto

Erik Aronesty Points 2223
#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.

115voto

KennyTM Points 232647

Si vous souhaitez utiliser un format de chaîne de caractères, essayez de Boost.Format.

20voto

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);

18voto

Timo Geusch Points 16952

Si vous voulez seulement un printf syntaxe (sans faire appel à printf vous-même), ont un oeil à Stimuler Format.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X