2017-08-10 3 views
0

Je pense à proposer ce qui suit comme une alternative à sprintf/snprintf dans notre projet.strprintf - Cette implémentation est-elle sûre et portable?

La motivation est d'éliminer le besoin de penser à la taille des tampons et de conserver autant de commodité que possible.

std::string strprintf(const char *fromat, ...) 
{ 
    std::string s; 
    s.resize(128); // best guess 
    char *buff = const_cast<char *>(s.data()); 

    va_list arglist; 
    va_start(arglist, fromat); 
    auto len = vsnprintf(buff, 128, fromat, arglist); 
    va_end(arglist); 

    if (len > 127) 
    { 
     va_start(arglist, fromat); 
     s.resize(len + 1); // leave room for null terminator 
     buff = const_cast<char *>(s.data()); 
     len = vsnprintf(buff, len+1, fromat, arglist); 
     va_end(arglist); 
    } 
    s.resize(len); 
    return s; // move semantics FTW 
} 

Ce code présente-t-il des problèmes inhérents?

Exemple d'utilisation:

auto s = strprintf("Hello %d world", 777); 
+0

* "commodité de l'original" * - C'est très discutable. – StoryTeller

+0

Il semble techniquement correct, mais pas très performant si le tampon dépasse votre limite de taille 128. Il appelle à nouveau vsnprintf, rendant la fonction deux fois plus longue. Vous devez peser entre la commodité et la performance ici. De plus, la chaîne que vous renvoyez sera à nouveau copiée, ce qui aura une incidence supplémentaire sur les performances. – Freakyy

+0

La valeur de retour a une sémantique de déplacement, il ne devrait donc pas y avoir d'autre copie. – CplusPuzzle

Répondre

0

s'avère qu'il ya déjà beaucoup de discussions sur ce ici:

std::string formatting like sprintf

Subjectivement, ma version semble encore plus concise que la plupart des choses là-bas, mais il est fonctionnellement identique à une partie de la solution proposée sur ce fil.