Comment convertir un double en chaîne en C ++?

171

J'ai besoin de stocker un double sous forme de chaîne. Je sais que je peux l'utiliser printfsi je voulais l'afficher, mais je veux juste le stocker dans une variable de chaîne afin que je puisse le stocker dans une carte plus tard (comme valeur , pas comme clé ).

Bill le lézard
la source
2
Une question pour répondre à votre question: pourquoi stockez-vous la valeur double dans une chaîne pour la stocker dans une carte? Allez-vous utiliser le double string-ified comme clé? Sinon, pourquoi ne pas laisser le double tel quel?
Matt McClellan
1
Point intéressant. Cependant, l'utilisation d'un double comme clé de carte peut être dangereuse, comme le sont toujours les comparaisons exactes sur les valeurs à virgule flottante. L'indexation sur une représentation sous forme de chaîne évite le problème.
Fred Larson
2
Pourquoi le convertir du tout? Stockez-le dans la carte en tant que double et évitez la conversion vers et depuis.
EvilTeach
3
Cela ressemble toujours à un appel d'objets. Un syndicat fonctionnerait. Chacun de l'objet pour y insérer diverses valeurs et le faire valider lui-même.
EvilTeach
2
Je n'ai qu'un tas de paires nom / valeur dans un fichier. Il n'appelle pas d'objets.
Bill the Lizard

Réponses:

183

La manière boost (tm) :

std::string str = boost::lexical_cast<std::string>(dbl);

La manière standard C ++ :

std::ostringstream strs;
strs << dbl;
std::string str = strs.str();

Remarque : n'oubliez pas#include <sstream>

Johannes Schaub - litb
la source
3
Je pense que boost :: lexical_cast EST à peu près la méthode C ++ standard, juste bien emballée pour vous. BTW, litb, vous avez une petite faute de frappe là-dedans - "boot: lexical_cast".
Fred Larson
2
boost :: lexical_cast n'est pas simplement un simple wrapper autour du code stringstream. De nombreuses routines de conversion sont implémentées en ligne. Selon les mesures de performances au bas de cette page ( boost.org/doc/libs/1_47_0/libs/conversion/lexical_cast.htm ), boost :: lexical_cast est plus rapide que l'utilisation de chaînes de caractères et, dans la plupart des cas, plus rapide que scanf / printf
Ferruccio
1
@Ferr qui a dit que c'était un simple emballage? Et merci d'avoir fourni le lien, je pensais en fait que c'était plus ou moins un simple wrapper :)
Johannes Schaub - litb
27
ne pas oublier #include <sstream>pour la manière c ++ :)
VladL
3
Pour des raisons de documentation, si vous ne le faites pas #include <sstream>, vous obtiendrez une erreur "type incomplet n'est pas autorisé".
Trevor Sullivan
194
// The C way:
char buffer[32];
snprintf(buffer, sizeof(buffer), "%g", myDoubleVar);

// The C++03 way:
std::ostringstream sstream;
sstream << myDoubleVar;
std::string varAsString = sstream.str();

// The C++11 way:
std::string varAsString = std::to_string(myDoubleVar);

// The boost way:
std::string varAsString = boost::lexical_cast<std::string>(myDoubleVar);
Adam Rosenfield
la source
1
Votre méthode C ++ ne fonctionnera pas car operator <<renvoie a std::ostream&plutôt que a stringstream&.
Konrad Rudolph
Il semble que mes chaînes de chaînes sont un peu rouillées, je préfère les anciennes méthodes C. Corrigé maintenant (j'espère).
Adam Rosenfield
Votre code C m'a mis au rebut au début. Je vous ai toujours voté pour avoir donné des alternatives correctes.
Bill the Lizard
2
vote favorable pour inclure la voie C. me semble tellement plus propre.
Nealon
11
J'ai voté pour la méthode C ++ 11. Je suis nouveau en C ++ et je ne savais pas qu'il y avait une to_stringfonction. J'utilise Microsoft Visual C ++ 2013.
Trevor Sullivan
123

La méthode Standard C ++ 11 (si vous ne vous souciez pas du format de sortie):

#include <string>

auto str = std::to_string(42.5); 

to_stringest une nouvelle fonction de bibliothèque introduite dans N1803 (r0), N1982 (r1) et N2408 (r2) " Simple Numeric Access ". Il existe également la stodfonction pour effectuer l'opération inverse.

Si vous souhaitez avoir un format de sortie différent de celui "%f", utilisez les méthodes snprintfou ostringstreamcomme illustré dans d'autres réponses.

KennyTM
la source
3
Oh oui bébé. to_string et stod fonctionnent tous les deux dans Visual Studio 11.
BSalita
Oh mon bébé ... to_string ne semble pas fonctionner dans VisualStudio 2010): Ça, ou je ne sais pas ce que je fais (très possible)
chessofnerd
1
Cela devrait être plus élevé, car c'est plus moderne!
gsamaras
1
Existe-t-il un moyen pour que cette fonction n'ajoute pas plus de décimales que nécessaire? Quand je convertis le double, 8.0cela me donne la corde "8.000000", tout "8"irait parfaitement bien.
HelloGoodbye le
1
Cela ne fonctionne pas pour les petits nombres ... par exemple: 1e-9produit0.000000
user3728501
24

Si vous utilisez C ++, évitez sprintf. C'est un-C ++ y et a plusieurs problèmes. Stringstreams est la méthode de choix, de préférence encapsulée comme dans Boost.LexicalCast qui peut être fait assez facilement:

template <typename T>
std::string to_string(T const& value) {
    stringstream sstr;
    sstr << value;
    return sstr.str();
}

Usage:

string s = to_string(42.5);
Konrad Rudolph
la source
24

Vous pouvez utiliser std :: to_string en C ++ 11

double d = 3.0;
std::string str = std::to_string(d);
Yochai Timmer
la source
Mes chiffres étaient vraiment petits et std::to_string()renvoyaient simplement 0,000000 et non sous forme scientifique.
erfan le
11

sprintfc'est bien, mais en C ++, la meilleure façon, la plus sûre et aussi légèrement plus lente de faire la conversion est avec stringstream:

#include <sstream>
#include <string>

// In some function:
double d = 453.23;
std::ostringstream os;
os << d;
std::string str = os.str();

Vous pouvez également utiliser Boost.LexicalCast :

#include <boost/lexical_cast.hpp>
#include <string>

// In some function:
double d = 453.23;
std::string str = boost::lexical_cast<string>(d);

Dans les deux cas, strdevrait être "453.23"après. LexicalCast présente certains avantages en ce sens qu'il garantit que la transformation est complète. Il utilise stringstreams en interne.

coppro
la source
10

Je regarderais la bibliothèque C ++ String Toolkit . Je viens de publier une réponse similaire ailleurs. Je l'ai trouvé très rapide et fiable.

#include <strtk.hpp>

double pi = M_PI;
std::string pi_as_string  = strtk::type_to_string<double>( pi );
DannyK
la source
7

Herb Sutter a un excellent article sur le formatage des chaînes . Je recommande de le lire. Je l'ai déjà lié sur SO.

Fred Larson
la source
1
Ce n'est pas une réponse, mais cela ferait un commentaire très utile sur la question.
Expiation limitée le
6

Le problème avec lexical_cast est l'incapacité de définir la précision. Normalement, si vous convertissez un double en chaîne, c'est parce que vous souhaitez l'imprimer. Si la précision est trop ou trop faible, cela affectera votre sortie.


la source
4

Vous pouvez également utiliser stringstream .

Firas Assaad
la source
4

Heh, je viens d'écrire ceci (sans rapport avec cette question):

string temp = "";
stringstream outStream;
double ratio = (currentImage->width*1.0f)/currentImage->height;
outStream << " R: " << ratio;
temp = outStream.str();

/* rest of the code */
Vinko Vrsalovic
la source
2

Vous voudrez peut-être lire mon article précédent sur SO. (Version macro avec un objet ostringstream temporaire.)

Pour mémoire: dans mon propre code, je préfère snprintf (). Avec un tableau char sur la pile locale, ce n'est pas si inefficace. (Eh bien, peut-être si vous avez dépassé la taille du tableau et que vous avez fait une boucle pour le faire deux fois ...)

(Je l'ai également enveloppé via vsnprintf (). Mais cela me coûte une vérification de type. Yelp si vous voulez le code ...)

Monsieur Ree
la source
2

Jetez un oeil à sprintf()et famille.

Darron
la source
2
J'ai mentionné printf parce que googler a trouvé un tas d'articles qui disent de convertir un double en une chaîne que vous utilisez printf. Ils partent du principe que la seule chose que vous pourriez faire est d'imprimer, ce qui dans mon cas est faux.
Bill the Lizard
pourquoi votez-vous -1? Je pense que le sprintf est bon. @BilltheLizard, sprint imprime quelque chose sur un écran de caractère * pas. Quelqu'un a répondu que la méthode c avait encore beaucoup de voix.
worldterminator
2

Normalement, pour ces opérations, vous devez utiliser les fonctions ecvt, fcvt ou gcvt:

/* gcvt example */
#include <stdio.h>
#include <stdlib.h>

main ()
{
  char buffer [20];
  gcvt (1365.249,6,buffer);
  puts (buffer);
  gcvt (1365.249,3,buffer);
  puts (buffer);
  return 0;
}

Output:
1365.25
1.37e+003   

En tant que fonction:

void double_to_char(double f,char * buffer){
  gcvt(f,10,buffer);
}
Ingo
la source
0

Vous pouvez essayer un style plus compact:

std::string number_in_string;

double number_in_double;

std::ostringstream output;

number_in_string = (dynamic_cast< std::ostringstream*>(&(output << number_in_double <<

std::endl)))->str(); 
Alexis Sánchez Tello
la source
0

Utilisez to_string().
exemple :

#include <iostream>   
#include <string>  

using namespace std;
int main ()
{
    string pi = "pi is " + to_string(3.1415926);
    cout<< "pi = "<< pi << endl;

  return 0;
}

lancez-le vous-même: http://ideone.com/7ejfaU
Ils sont également disponibles:

string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned long val);
string to_string (unsigned long long val);
string to_string (float val);
string to_string (double val);
string to_string (long double val);
Rika
la source
0

Vous pouvez convertir n'importe quoi en n'importe quoi en utilisant cette fonction:

template<class T = std::string, class U>
T to(U a) {
    std::stringstream ss;
    T ret;
    ss << a;
    ss >> ret;
    return ret;
};

utilisation:

std::string str = to(2.5);
double d = to<double>("2.5");
Sam Mokari
la source