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

Bill die Eidechse
quelle
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>

Johannes Schaub - litb
quelle
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);
Adam Rosenfield
quelle
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.

kennytm
quelle
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);
Konrad Rudolph
quelle
24

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

double d = 3.0;
std::string str = std::to_string(d);
Yochai Timmer
quelle
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.

coppro
quelle
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 );
DannyK
quelle
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.


quelle
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 */
Vinko Vrsalovic
quelle
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 ...)

Mr.Ree
quelle
2

Schauen Sie sich an sprintf()und Familie.

Darron
quelle
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);
}
Ingo
quelle
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(); 
Alexis Sánchez Tello
quelle
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);
Rika
quelle
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");
Sam Mokari
quelle