Ich sehe keinen Grund, warum boost :: lexical_cast eine Leistungsbeeinträchtigung hätte (aber ein Stringstream ist sicherlich langsamer).
Zifre
7
boost :: lexical_cast wird gestreamt.
TimW
1
Man kann im Allgemeinen nicht sagen, dass sie mit einer Leistungsstrafe verbunden sind, denke ich. Überlegen Sie, was passiert, wenn Sie kurz davor eine Filmnummer haben. Der Benutzer müsste sehr schnell tippen (rly jon skeet like), um jemals zu bemerken, dass die Millisekunden lexical_cast langsamer sind :) Das heißt, ich glaube, es gibt Aufgaben, bei denen lexical_cast einfach zu viel Leistung saugt :)
Johannes Schaub - litb
3
Was macht das :: vor atof () für diese Lösung? Was muss es sein, um dort zu sein?
Sivabudh
4
@ShaChris Da ich sicherstellen möchte, dass ich die atof-Funktion aus dem globalen Namespace verwende.
TimW
104
Die Standardbibliothek (C ++ 11) bietet die gewünschte Funktionalität mit std::stod:
std::string s ="0.6"
std::wstring ws ="0.7"double d = std::stod(s);double dw = std::stod(ws);
Im Allgemeinen für die meisten anderen Grundtypen siehe <string>. Es gibt auch einige neue Funktionen für C-Strings. Sehen<stdlib.h>
Ich mag diese Lösung, aber es scheint, dass sie nur aus C ++ 11 stammt. Also nicht auf meinem SDK verfügbar.
pamplemousse_mk2
Es ist schön zu wissen, dass das C ++ - Standardkomitee dies hinzugefügt hat. ostringstreaman sich war einfach zu lang, um zu tippen, geschweige denn zu verwenden ..
Bobobobo
4
Für Floats (wie in der Frage gestellt, die ich bei Google durch Eingabe von "c ++ string to float" gefunden habe) sollte man std :: stof verwenden.
Étienne
1
Nur ein Hinweis, dass dies Ausnahmen auslösen kann: std :: invalid_argument (wenn die Konvertierung fehlgeschlagen ist) std :: out_of_range (wenn außerhalb des Bereichs)
Jason Doucette
2
Käufer aufgepasst, hängt vom aktuellen Gebietsschema ab.
Danke, es funktioniert. Aber es ist eine Frage für mich: Warum funktioniert mein Code nicht?
Max Frai
2
@Johannes Schaub: Basierend auf ADL könnte er genauso gut haben, dass die Verwendungsdefinitionen und das, was er tatsächlich verwendet, wahrscheinlich eine große Anzahl von Standardelementen in den Geltungsbereich bringen werden. Außerdem ist lexical_cast wahnsinnig langsam, also keine +1 von mir.
Eine nette Funktion von boost :: lexical_cast ist die Fehlerbehandlung. Wenn eine Konvertierung fehlschlägt, wird eine Ausnahme ausgelöst:try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
Semjon Mössinger
Um genauer zu sein, verwenden Sie catch ( boost::bad_lexical_cast const& err ), um die Ausnahme abzufangen.
Semjon Mössinger
14
Sie können std :: stringstream verwenden:
#include<sstream>#include<string>template<typename T>
T StringToNumber(const std::string& numberAsString){
T valor;
std::stringstream stream(numberAsString);
stream >> valor;if(stream.fail()){
std::runtime_error e(numberAsString);throw e;}return valor;}
Ähm, du denkst also, boost :: lexical_cast hat eine schreckliche Oberfläche, nicht wahr? Schau dir die Antwort von stefanB an! Boost macht das Gleiche.
Kirsche40
@ kirsche40 Scheint eine gute Alternative für Leute zu sein, die noch keine Abhängigkeiten mit Boost haben (das Verknüpfen mit Boost, nur um einen std :: string in Zahlen umzuwandeln, ist ein bisschen übertrieben!)
Jean-Philippe Jodoin
@ JEan-Phillippe Jodiun Ich antwortete auf einen jetzt gelöschten Kommentar, in dem jemand Boost empfohlen hat. Mir ist bewusst, dass Boost die meiste Zeit übertrieben ist. Übrigens ist die Verwendung von Boost seit einiger Zeit auf "neuere" Compiler beschränkt. Ältere Projekte können Boost nicht verwenden. Zum Beispiel hängt ASIO stark von C ++ 11-Funktionen wie std :: addressof ab, was es für C ++ 98 / C ++ 03-Compiler völlig wertlos macht. IMHO, als das Projekt begann, war es die Absicht von Boost, neue "standardisierte" Funktionen für ältere Compiler-Versionen bereitzustellen ... :-(
kirsche40
10
Ja, mit einer lexikalischen Besetzung. Verwenden Sie einen Stringstream und den Operator << oder verwenden Sie Boost, sie haben ihn bereits implementiert.
Ihre eigene Version könnte folgendermaßen aussehen:
template<typename to,typename from>to lexical_cast(from const&x){
std::stringstream os;
to ret;
os << x;
os >> ret;return ret;}
Hinweis: boost :: lexical_cast löst eine Ausnahme aus, sodass Sie darauf vorbereitet sein sollten, damit umzugehen, wenn Sie einen ungültigen Wert übergeben. Versuchen Sie, eine Zeichenfolge ("xxx") zu übergeben.
Ungültige Antwort, woher wissen Sie, dass der in num gespeicherte Wert tatsächlich eine gültige Gleitkommazahl ist? Sie überprüfen nicht den Rückgabetyp von sscanf, scheint ein MS-Codierungsstil zu sein.
1
Diese Antwort sichert litb in Ihren Kommentaren. Ich habe den tiefen Verdacht, dass Sie das Ergebnis einfach nicht richtig anzeigen.
Mir war genau das Gleiche einmal passiert. Ich habe einen ganzen Tag lang versucht herauszufinden, warum ich einen schlechten Wert in ein 64-Bit-Int bekommen habe, nur um herauszufinden, dass printf das zweite Byte ignoriert. Sie können nicht einfach einen 64-Bit-Wert an printf übergeben, wie es ein int ist.
Ich benutze printf nicht, um Ergebnisse zu sehen ... Und ich benutze diesen Wert, um die Deckkraft des Fensters festzulegen, und mein Fenster ist voll transparent, also ist der Wert 0.
Max Frai
1
Die C ++ 11-Methode besteht darin, std :: stod und std :: to_string zu verwenden. Beide funktionieren in Visual Studio 11.
Warum atof()funktioniert die ursprüngliche Frage nicht? Die Tatsache, dass sie doppelt besetzt ist, macht mich misstrauisch. Der Code sollte nicht ohne kompiliert werden #include <stdlib.h>, aber wenn die Umwandlung hinzugefügt wurde, um eine Kompilierungswarnung zu lösen, atof()wird sie nicht korrekt deklariert. Wenn der Compiler davon ausgeht, dass atof()ein int zurückgegeben wird, löst das Casting die Konvertierungswarnung, führt jedoch nicht dazu, dass der Rückgabewert als double erkannt wird.
#include<stdlib.h>#include<string>...
std::string num ="0.6";double temp = atof(num.c_str());
Sie möchten Boost lexical_cast sowieso nicht für String <-> Gleitkomma. Diese Untergruppe von Anwendungsfällen ist die einzige Gruppe, für die Boost durchweg schlechter ist als die älteren Funktionen - und sie haben im Grunde alle ihre Fehler dort konzentriert, da ihre eigenen Leistungsergebnisse eine 20-25-fach langsamere Leistung zeigen als die Verwendung von sscanf und printf für solche Konvertierungen.
Google es selbst. boost :: lexical_cast kann etwa 50 Konvertierungen verarbeiten. Wenn Sie diejenigen mit Gleitkommazahlen ausschließen, ist dies genauso gut oder besser als die offensichtlichen Alternativen (mit dem zusätzlichen Vorteil, dass für alle diese Vorgänge eine einzige API vorhanden ist). Aber bringen Sie Schwimmer mit und es ist wie wenn die Titanic in Bezug auf die Leistung auf einen Eisberg trifft.
Die alten, dedizierten str-> double-Funktionen können alle 10000 Parses in etwa 30 ms (oder besser) durchführen. lexical_cast benötigt ungefähr 650 ms, um den gleichen Job zu erledigen.
Gebietsschema unabhängige Zeichenfolge zu verdoppeln (Dezimaltrennzeichen immer '.')
Fehlererkennung, wenn die Zeichenfolgenkonvertierung fehlschlägt
Meine Lösung (verwendet die Windows-Funktion _wcstod_l):
// string to convert. Note: decimal seperator is ',' here
std::wstring str = L"1,101";// Use this for error detectionwchar_t* stopString;// Create a locale for "C". Thus a '.' is expected as decimal separatordouble dbl = _wcstod_l(str.c_str(),&stopString, _create_locale(LC_ALL,"C"));if(wcslen(stopString)!=0){// ... error handling ... we'll run into this because of the separator}
HTH ... ich habe ziemlich lange gebraucht, um zu dieser Lösung zu gelangen. Und ich habe immer noch das Gefühl, dass ich nicht genug über String-Lokalisierung und so weiß ...
Antworten:
Für mich ist es eine gültige C ++ - Syntax, um einen String in ein Double zu konvertieren.
Sie können dies mit dem Stringstream oder boost :: lexical_cast tun, aber diese sind mit einer Leistungsbeeinträchtigung verbunden.
Ahaha du hast ein Qt Projekt ...
Zusätzlicher Hinweis:
Wenn die Eingabedaten a sind
const char*
,QByteArray::toDouble
sind sie schneller.quelle
Die Standardbibliothek (C ++ 11) bietet die gewünschte Funktionalität mit
std::stod
:Im Allgemeinen für die meisten anderen Grundtypen siehe
<string>
. Es gibt auch einige neue Funktionen für C-Strings. Sehen<stdlib.h>
quelle
ostringstream
an sich war einfach zu lang, um zu tippen, geschweige denn zu verwenden ..Lexikalische Besetzung ist sehr nett.
quelle
try { ... boost::lexical_cast ... } catch (std::exception const& err) { //handle excpetion }
catch ( boost::bad_lexical_cast const& err )
, um die Ausnahme abzufangen.Sie können std :: stringstream verwenden:
Verwendung:
quelle
Ja, mit einer lexikalischen Besetzung. Verwenden Sie einen Stringstream und den Operator << oder verwenden Sie Boost, sie haben ihn bereits implementiert.
Ihre eigene Version könnte folgendermaßen aussehen:
quelle
Sie können die lexikalische Besetzung verwenden:
Hinweis: boost :: lexical_cast löst eine Ausnahme aus, sodass Sie darauf vorbereitet sein sollten, damit umzugehen, wenn Sie einen ungültigen Wert übergeben. Versuchen Sie, eine Zeichenfolge ("xxx") zu übergeben.
quelle
Wenn Sie nicht den gesamten Boost ziehen möchten, gehen Sie zu
strtod(3)
from<cstdlib>
- es wird bereits ein Double zurückgegeben.Ausgänge:
Warum funktioniert atof () nicht ... auf welcher Plattform / auf welchem Compiler bist du?
quelle
Ich hatte das gleiche Problem unter Linux
Es klappt.
quelle
quelle
Diese Antwort sichert litb in Ihren Kommentaren. Ich habe den tiefen Verdacht, dass Sie das Ergebnis einfach nicht richtig anzeigen.
Mir war genau das Gleiche einmal passiert. Ich habe einen ganzen Tag lang versucht herauszufinden, warum ich einen schlechten Wert in ein 64-Bit-Int bekommen habe, nur um herauszufinden, dass printf das zweite Byte ignoriert. Sie können nicht einfach einen 64-Bit-Wert an printf übergeben, wie es ein int ist.
quelle
Die C ++ 11-Methode besteht darin, std :: stod und std :: to_string zu verwenden. Beide funktionieren in Visual Studio 11.
quelle
Warum
atof()
funktioniert die ursprüngliche Frage nicht? Die Tatsache, dass sie doppelt besetzt ist, macht mich misstrauisch. Der Code sollte nicht ohne kompiliert werden#include <stdlib.h>
, aber wenn die Umwandlung hinzugefügt wurde, um eine Kompilierungswarnung zu lösen,atof()
wird sie nicht korrekt deklariert. Wenn der Compiler davon ausgeht, dassatof()
ein int zurückgegeben wird, löst das Casting die Konvertierungswarnung, führt jedoch nicht dazu, dass der Rückgabewert als double erkannt wird.sollte ohne Warnungen funktionieren.
quelle
Anstatt Boost in die Gleichung zu ziehen, können Sie Ihre Zeichenfolge (vorübergehend) als
char[]
und verwendensprintf()
.Aber wenn Sie Boost trotzdem verwenden, ist das natürlich kein allzu großes Problem.
quelle
Sie möchten Boost lexical_cast sowieso nicht für String <-> Gleitkomma. Diese Untergruppe von Anwendungsfällen ist die einzige Gruppe, für die Boost durchweg schlechter ist als die älteren Funktionen - und sie haben im Grunde alle ihre Fehler dort konzentriert, da ihre eigenen Leistungsergebnisse eine 20-25-fach langsamere Leistung zeigen als die Verwendung von sscanf und printf für solche Konvertierungen.
Google es selbst. boost :: lexical_cast kann etwa 50 Konvertierungen verarbeiten. Wenn Sie diejenigen mit Gleitkommazahlen ausschließen, ist dies genauso gut oder besser als die offensichtlichen Alternativen (mit dem zusätzlichen Vorteil, dass für alle diese Vorgänge eine einzige API vorhanden ist). Aber bringen Sie Schwimmer mit und es ist wie wenn die Titanic in Bezug auf die Leistung auf einen Eisberg trifft.
Die alten, dedizierten str-> double-Funktionen können alle 10000 Parses in etwa 30 ms (oder besser) durchführen. lexical_cast benötigt ungefähr 650 ms, um den gleichen Job zu erledigen.
quelle
Mein Problem:
Meine Lösung (verwendet die Windows-Funktion _wcstod_l):
HTH ... ich habe ziemlich lange gebraucht, um zu dieser Lösung zu gelangen. Und ich habe immer noch das Gefühl, dass ich nicht genug über String-Lokalisierung und so weiß ...
quelle