web-dev-qa-db-fra.com

Convertir un nombre en chaîne avec une longueur spécifiée en C++

J'ai des nombres de longueur différente (comme 1, 999, 76492, etc.) et je veux les convertir tous en chaînes de même longueur (par exemple, si la longueur est 6, ces chaînes seront: '000001' , '000999', '076492'). 

En d'autres termes, j'ai besoin d'ajouter le nombre correct de zéros à gauche.

int n = 999;
string str = some_function(n,6);
//str = '000999'

Existe-t-il une fonction comme celle-ci en C++?

39
Degvik

ou en utilisant les stringstreams:

#include <sstream>
#include <iomanip>

std::stringstream ss;
ss << std::setw(10) << std::setfill('0') << i;
std::string s = ss.str();

J'ai compilé les informations que j'ai trouvées sur arachnoid.com parce que j'aime davantage la méthode de typage sans danger de iostreams. En outre, vous pouvez également utiliser ce code sur n’importe quel autre flux de sortie.

54
xtofl
char str[7];
snprintf (str, 7, "%06d", n);

Voir snprintf

13
Isak Savo

Une chose que vous pouvez souhaitez connaître est le verrouillage potentiel qui peut subsister lorsque vous utilisez l’approche stringstream. Dans la STL livrée avec Visual Studio 2008, au moins, de nombreux verrous sont retirés et publiés, car diverses informations sur les paramètres régionaux sont utilisées lors du formatage. Cela peut être ou ne pas être un problème pour vous en fonction du nombre de threads que vous avez qui pourraient convertir simultanément des nombres en chaînes ... 

La version sprintf ne prend pas de verrous (du moins selon l'outil de surveillance des verrous que je développe actuellement ...) et pourrait donc être "meilleure" pour une utilisation dans des situations concurrentes.

Je l’ai seulement remarqué parce que mon outil a récemment craché les verrous de «paramètres régionaux» parmi les plus contestés pour les verrous de mon système de serveur; cela a été un peu une surprise et peut me amener à réviser l’approche que j’ai adoptée (c’est-à-dire revenir à sprintf de stringstream) ...

8
Len Holgate

Cette méthode n'utilise ni stream ni sprintf. Outre les problèmes de verrouillage, les flux entraînent une surcharge de performances et sont vraiment excessifs. Pour les flux, la surcharge provient de la nécessité de construire le tampon Steam et le tampon de flux. Pour sprintf, le temps système provient de la nécessité d'interpréter la chaîne de format. Cela fonctionne même lorsque n est négatif ou lorsque la représentation sous forme de chaîne de n est plus longue que len . C'est la solution la plus rapide.

inline string some_function(int n, int len)
{
    string result(len--, '0');
    for (int val=(n<0)?-n:n; len>=0&&val!=0; --len,val/=10)
       result[len]='0'+val%10;
    if (len>=0&&n<0) result[0]='-';
    return result;
}
3
sep

stringstream fera l'affaire ( comme l'a souligné xtofl ). Le format Boost est un remplacement plus pratique pour snprintf.

3
PW.

Il y a plusieurs façons de le faire. Le plus simple serait:

int n = 999;
char buffer[256]; sprintf(buffer, "%06d", n);
string str(buffer);
2
Pramod

sprintf est la manière de faire cela, semblable à C, qui fonctionne aussi en C++.

En C++, une combinaison de formatage de chaîne et de sortie de flux (voir http://www.arachnoid.com/cpptutor/student3.html ) fera l'affaire.

1
Chris Johnson

Ceci est un vieux fil de discussion, mais comme fmt pourrait en faire un standard, voici une solution supplémentaire:

#include <fmt/format.h>

int n = 999;

const auto str = fmt::format("{:0>{}}", n, 6);

Notez que fmt::format("{:0>6}", n) fonctionne aussi bien lorsque la largeur souhaitée est connue au moment de la compilation. Une autre option est rappel :

#include <absl/strings/str_format.h>

int n = 999;

const auto str = absl::StrFormat("%0*d", 6, n);

Encore une fois, abs::StrFormat("%06d", n) est possible. format boost est un autre outil pour résoudre ce problème:

#include <boost/format.hpp>

int n = 999;

const auto str = boost::str(boost::format("%06d") % n);

Malheureusement, les spécificateurs de largeur variable en tant qu'arguments chaînés avec l'opérateur % ne sont pas pris en charge. Cela nécessite une chaîne de formatage (par exemple, const std::string fmt = "%0" + std::to_string(6) + "d";).

En termes de performances, le rappel et le fmt prétendent être très attrayants et plus rapides que le boost. Dans tous les cas, les trois solutions devraient être plus efficaces que les approches std::stringstream et, à l'exception de la famille std::*printf, elles ne sacrifient pas la sécurité de type.

0
lubgr