Wie konvertiere ich ein Double in einen String in C ++?


171

Ich muss ein Double als String speichern. Ich weiß, dass ich es verwenden kann, printfwenn ich es anzeigen möchte, aber ich möchte es nur in einer Zeichenfolgenvariablen speichern, damit ich es später in einer Karte speichern kann (als Wert , nicht als Schlüssel ).


2
Eine Frage zur Beantwortung Ihrer Frage: Warum speichern Sie den doppelten Wert in einer Zeichenfolge, um ihn in einer Karte zu speichern? Verwenden Sie das string-ified double als Schlüssel? Wenn nicht, warum nicht das Doppelte so lassen, wie es ist?
Matt McClellan

1
Interessanter Punkt. Die Verwendung eines Double als Kartenschlüssel kann jedoch mit Gefahren verbunden sein, da genaue Vergleiche mit Gleitkommawerten immer möglich sind. Durch die Indizierung einer Zeichenfolgendarstellung wird das Problem vermieden.
Fred Larson

2
Warum überhaupt konvertieren? Speichern Sie es als Double in der Karte und vermeiden Sie die Konvertierung von und nach.
EvilTeach

3
Das klingt immer noch nach einem Aufruf für Objekte. Eine Gewerkschaft würde funktionieren. Jeweils das Objekt, um verschiedene Werte darin einzufügen und es selbst validieren zu lassen.
EvilTeach

2
Ich habe nur eine Reihe von Name / Wert-Paaren in einer Datei. Es werden keine Objekte benötigt.
Bill the Lizard

Antworten:


183

Der Boost (tm) Weg:

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

Der Standard C ++ Weg:

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

Hinweis : Vergessen Sie nicht#include <sstream>


3
Ich denke, boost :: lexical_cast ist so ziemlich die Standard-C ++ - Methode, nur gut verpackt für Sie. Übrigens, litb, Sie haben einen kleinen Tippfehler - "boot: lexical_cast".
Fred Larson

2
boost :: lexical_cast ist nicht nur ein einfacher Wrapper um den Stringstream-Code. Viele der Konvertierungsroutinen werden inline implementiert. Laut den Leistungsmessungen am Ende dieser Seite ( boost.org/doc/libs/1_47_0/libs/conversion/lexical_cast.htm ) ist boost :: lexical_cast schneller als die Verwendung von Stringstreams und in den meisten Fällen schneller als scanf / printf
Ferruccio

1
@ Ferr wer hat gesagt, es sei ein einfacher Wrapper? Und vielen Dank für den Link bereitstellt, habe ich eigentlich habe glaube , es war mehr oder weniger ein einfaches Wrapper :)
Johannes Schaub - litb

27
Vergiss nicht #include <sstream>für den c ++ Weg :)
VladL

3
Wenn Sie dies nicht tun #include <sstream>, wird aus Gründen der Dokumentation die Fehlermeldung "Unvollständiger Typ ist nicht zulässig" angezeigt.
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);

1
Ihr C ++ - Weg funktioniert nicht, da operator <<er std::ostream&eher a als a zurückgibt stringstream&.
Konrad Rudolph

Es scheint, dass meine Stringstreams etwas rostig sind, ich bevorzuge die alten C-Wege. Jetzt behoben (hoffe ich).
Adam Rosenfield

Ihr C-Code hat mich zuerst abgeworfen. Ich habe Sie immer noch dafür gestimmt, dass Sie die richtigen Alternativen angegeben haben.
Bill the Lizard

2
Gegenstimme für die Aufnahme des C-Weges. scheint mir einfach so viel sauberer zu sein.
Nealon

11
Upvoted für den C ++ 11 Weg. Ich bin neu in C ++ und habe nicht bemerkt, dass es eine to_stringFunktion gibt. Ich verwende Microsoft Visual C ++ 2013.
Trevor Sullivan

123

Der Standard C ++ 11 Weg (wenn Sie sich nicht für das Ausgabeformat interessieren):

#include <string>

auto str = std::to_string(42.5); 

to_stringist eine neue Bibliotheksfunktion, die in N1803 (r0), N1982 (r1) und N2408 (r2) " Simple Numeric Access " eingeführt wurde. Es gibt auch die stodFunktion, den Rückwärtsgang durchzuführen.

Wenn Sie ein anderes Ausgabeformat als möchten "%f", verwenden Sie die Methoden snprintfoder ostringstream, wie in anderen Antworten dargestellt.


3
Oh ja Baby. to_string und stod arbeiten beide in Visual Studio 11.
BSalita

Oh liebes Baby ... to_string scheint in VisualStudio 2010 nicht zu funktionieren): Das, oder ich weiß nicht, was ich tue (sehr gut möglich)
chessofnerd

1
Dies sollte höher sein, da es moderner ist!
Gsamaras

1
Gibt es eine Möglichkeit, mit dieser Funktion nicht mehr Dezimalstellen als erforderlich hinzuzufügen? Wenn ich das Double konvertiere 8.0, bekomme ich den String "8.000000", während "8"das vollkommen in Ordnung wäre.
HelloGoodbye

1
Dies funktioniert nicht für kleine Zahlen ... zB: 1e-9produziert0.000000
user3728501

24

Wenn Sie C ++ verwenden, vermeiden Sie sprintf. Es ist un-C ++ y und hat mehrere Probleme. Stringstreams sind die Methode der Wahl, vorzugsweise wie in Boost.LexicalCast gekapselt , was ganz einfach möglich ist:

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

Verwendung:

string s = to_string(42.5);

24

Sie können std :: to_string in C ++ 11 verwenden

double d = 3.0;
std::string str = std::to_string(d);

Meine Zahlen waren wirklich klein und std::to_string()gaben einfach 0,000000 zurück und nicht in wissenschaftlicher Form.
erfan

11

sprintfist in Ordnung, aber in C ++ ist die bessere, sicherere und auch etwas langsamere Art der Konvertierung stringstream:

#include <sstream>
#include <string>

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

Sie können auch Boost.LexicalCast verwenden :

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

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

In beiden Fällen strsollte "453.23"danach sein. LexicalCast bietet einige Vorteile, da es sicherstellt, dass die Transformation abgeschlossen ist. Es verwendet stringstreams intern.


10

Ich würde mir die C ++ String Toolkit Libary ansehen . Habe gerade eine ähnliche Antwort an anderer Stelle gepostet. Ich habe es sehr schnell und zuverlässig gefunden.

#include <strtk.hpp>

double pi = M_PI;
std::string pi_as_string  = strtk::type_to_string<double>( pi );


6

Das Problem mit lexical_cast ist die Unfähigkeit, die Genauigkeit zu definieren. Wenn Sie ein Double in eine Zeichenfolge konvertieren, möchten Sie dies normalerweise ausdrucken. Wenn die Genauigkeit zu hoch oder zu gering ist, wirkt sich dies auf Ihre Ausgabe aus.



4

Heh, ich habe das gerade geschrieben (ohne Bezug zu dieser Frage):

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

/* rest of the code */

2

Vielleicht möchten Sie meinen vorherigen Beitrag auf SO lesen. (Makroversion mit einem temporären Ostringstream-Objekt.)

Für die Aufzeichnung: In meinem eigenen Code bevorzuge ich snprintf (). Mit einem char-Array auf dem lokalen Stapel ist es nicht so ineffizient. (Nun, vielleicht, wenn Sie die Arraygröße überschritten und eine Schleife durchgeführt haben, um dies zweimal zu tun ...)

(Ich habe es auch über vsnprintf () verpackt. Aber das kostet mich eine Typprüfung. Yelp, wenn Sie den Code wollen ...)


2

Schauen Sie sich an sprintf()und Familie.


2
Ich habe printf erwähnt, weil beim Googeln eine Reihe von Artikeln aufgetaucht sind, die besagen, dass Sie von einem Double in einen String konvertieren sollen, den Sie printf verwenden. Sie gehen davon aus, dass Sie nur drucken können, was in meinem Fall falsch ist.
Bill the Lizard

warum wählst du -1? Ich finde Sprintf gut. @BilltheLizard, Sprint druckt etwas auf einen char * not-Bildschirm. Jemand, der mit der c-Methode geantwortet hat, hat immer noch viel Stimmen bekommen.
Weltterminator

2

Normalerweise müssen Sie für diese Operationen die Funktionen ecvt, fcvt oder gcvt verwenden:

/* 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   

Als eine Funktion:

void double_to_char(double f,char * buffer){
  gcvt(f,10,buffer);
}

0

Sie könnten einen kompakteren Stil ausprobieren:

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

0

Verwenden Sie to_string().
Beispiel:

#include <iostream>   
#include <string>  

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

  return 0;
}

Führen Sie es selbst aus: http://ideone.com/7ejfaU
Diese sind ebenfalls verfügbar:

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

0

Mit dieser Funktion können Sie alles in alles konvertieren:

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

Verwendung :

std::string str = to(2.5);
double d = to<double>("2.5");
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.