C++: Umwandeln von String in Double

OP #6307760
Lesenswert?

Hallo zusammen,
welche Variante zur Konvertierung von String in Double ist in modernem 
C++ zu bevorzugen?
1
[....]
2
double value;
3

4
// Variante 1: String Stream
5
std::stringstream( "1234" ) >> value;
6

7
// Variante 2: Standard-Funktion
8
value = std::stod( "1234" );
9
[....]

Viele Grüße.
#6307789
Lesenswert?

Dennis S. schrieb:
> Thomas R. schrieb:
>> value = atof(test.c_str());
> Das wäre eine weitere von vielen Varianten. Warum nutzt du diese? Ich
> persönlich habe "atof" und Varianten schon länger aus meinem Code
> verbannt.

atof() enthält keinerlei Möglichkeit zu erkennen, ob ein Fehler 
aufgetreten ist.  Wenn, dann sollte man strtod() verwenden. Aber warum 
dann nicht gleich std::stod(), das direkt mit einem std::string umgehen 
kann?
Gast #6307808
Lesenswert?

Dennis S. schrieb:
> welche Variante zur Konvertierung von String in Double ist in modernem
> C++ zu bevorzugen

Na, from_chars natürlich.

Ist so modern, das können die meisten Compiler noch nicht.

All diese Funktionen gehen aus strtod zurück, also besser die direkt 
verwenden. Das erspart wrpaaer die nichts anderes tun als Errorwerte 
umzuformatieren. Es sri denn, man will genau dss, eine exception statt 
einem error-code.

ABER: all diese Funktionen führen zu defekten Programmen.
1
value = std::stod( "12.4" );
geht kaputt, sobald dss Progrsmm nicht mehr in locale US läuft, sondern 
in locale DE. Weil dann ein , erwartrt wird. Also entweder vorher das 
locale setzen, oder diese Funktionen ganz meiden.
#6307813
Lesenswert?

MaWin schrieb:
> ABER: all diese Funktionen führen zu defekten Programmen.value =
> std::stod( "12.4" );
> geht kaputt, sobald dss Progrsmm nicht mehr in locale US läuft, sondern
> in locale DE. Weil dann ein , erwartrt wird.

Das ist nicht "kaputt", sondern an die vom Benutzer eingestellte 
Landes-Konvention angepasst. Wenn man das nicht will:

> vorher das locale setzen

Immerhin kann man das da. Ich hatte letztens das umgekehrte Problem: Auf 
dem Rechner ist en_US als locale eingestellt gewesen, aber es sollten 
.csv-Files erstellt werden, die später von Excel eingelesen werden 
sollen. Leider funktioniert das in der deutschen Version von Excel nur, 
wenn in den .csv-Files ein Komma als Dezimaltrennzeichen verwendet wird. 
Der Import-Dialog bietet auch keine Möglichkeit, was anderes 
auszuwählen. Das würde ich dann tatsächlich als "kaputt" bezeichnen.
Gast #6307906
Lesenswert?

MaWin schrieb:
> All diese Funktionen gehen aus strtod zurück, also besser die direkt
> verwenden. Das erspart wrpaaer die nichts anderes tun als Errorwerte
> umzuformatieren. Es sri denn, man will genau dss, eine exception statt
> einem error-code.
>
> ABER: all diese Funktionen führen zu defekten Programmen.value =
> std::stod( "12.4" );
> geht kaputt, sobald dss Progrsmm nicht mehr in locale US läuft, sondern
> in locale DE. Weil dann ein , erwartrt wird. Also entweder vorher das
> locale setzen, oder diese Funktionen ganz meiden.

Deshalb habe ich mir für so etwas eine eigene Funktion geschrieben, die 
den Dezimaltrenner in der Defaulteinstellung ignoriert und das Komma in 
einen Punkt umwandelt. Die Umwandlung in die Zahl erfolgt dann mit einer 
Funktion die nicht mit den Lokalen arbeitet, sondern als Trenner den in 
der Programmierspache üblichen Dezimaltrenner Punkt benutzt.
Die Funktion kann auch mit den gelegentlich verwendeten 
Tausendertrennzeichen umgehen.
#6307929
Lesenswert?

Zeno schrieb:
> Die Funktion kann auch mit den gelegentlich verwendeten Tausendertrennzeichen
> umgehen.

Das passt nicht so ganz zu dem:

> Deshalb habe ich mir für so etwas eine eigene Funktion geschrieben, die
> den Dezimaltrenner in der Defaulteinstellung ignoriert und das Komma in
> einen Punkt umwandelt.

Im Englischen wird das Komma als Tausender-Trennzeichen verwendet.

Aber warum überhaupt soviel Umstand, nur um nicht die locale setzen zu 
müssen?
Moderator #6307952
Lesenswert?

Dennis S. schrieb:
> Gilt das auch für die String Stream-Variante?

Auch std:: stringstream richtet sich nach der eingestellten Locale.
Diese ist aber – unabhängig von den Benutzereinstellungen – beim
Programmstart immer "C", d.h. das Dezimaltrennzeichen ist der Punkt. Das
ändert sich erst, wenn du bspw. mit std::locale::global explizit etwas
anderes vorgibst.

Vorsicht ist geboten bei einigen GUI-Frameworks, die automatisch die
Benutzereinstellungen übernehmen.


Rolf M. schrieb:
> Aber warum überhaupt soviel Umstand, nur um nicht die locale setzen zu
> müssen?

Er möchte wahrscheinlich, dass sein Programm Eingaben sowohl in "C" als
auch in "de" verarbeiten kann (wobei das wegen der Tausendertrennzeichen
auch nicht zuverlässig funktionieren kann).

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren