Forum: PC-Programmierung C++: Umwandeln von String in Double


von Dennis S. (eltio)


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.

von Thomas R. (r3tr0)


Lesenswert?

Nutze dazu eigentlich immer atof

double value;
string test = "test";

value = atof(test.c_str());

von Sven K. (quotschmacher)


Lesenswert?

Thomas R. schrieb:
> value = atof(test.c_str());

das sieht mir stark nach c++ aus...


https://www.reddit.com/r/Cplusplus/comments/2m1cjo/is_there_any_benefit_associated_with_using/ 
da steht auch schon was dazu (also zur thread-frage, nicht zur nutzung 
von c-methoden)

von Dennis S. (eltio)


Lesenswert?

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.

Sven K. schrieb:
> das sieht mir stark nach c++ aus...
Das ist für C++ natürlich auch völlig in Ordnung! ;-) Der Link trifft 
das Thema glaube ich ganz gut, vielen Dank.

von Rolf M. (rmagnus)


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?

von MaWin (Gast)


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.

von Rolf M. (rmagnus)


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.

von Dennis S. (eltio)


Lesenswert?

MaWin schrieb:
> Das erspart wrpaaer die nichts anderes tun als Errorwerte umzuformatieren.
Wenn man in C++ programmiert ist das in den meisten Fällen durchaus 
gewollt.

MaWin schrieb:
> Also entweder vorher das
> locale setzen, oder diese Funktionen ganz meiden.
Gilt das auch für die String Stream-Variante?

von Zeno (Gast)


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.

von Rolf M. (rmagnus)


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?

von Yalu X. (yalu) (Moderator)


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

: Bearbeitet durch Moderator
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.