IStringStream/StringStream zur nummerischen Umwandlung
-
Hallo!
Ich bin neu hier. Fange gerade einen Kurs "Engine Programming" an und programmiere dafür ein Minigolf Spiel mit C++ und OpenGL. Das nur als Rahmendaten zu mir. Ich werde hier jetzt wahrscheinlich öfter zu finden sein
Nun habe ich gerade ein sehr merkwürdiges Verhalten von istringstreams und stringstreams festgestellt. Die erste Frage wäre "Was ist der Unterschied zwischen den beiden?"
Fangen wir mit den IStringStreams an:
Wenn ich also einen String erst als Float ausgebe und dann als Int bekomme ich:44.4
-858993460Warum wird der Int nicht mehr gefüllt?
Hier der Code:
//Code zum sofort Kopieren und selber Kompilieren #include <iostream> #include <sstream> using namespace std; int main( void ) { string string2int; istringstream istr; int int4string; float float4string; string2int = "44.4"; istr.str( string2int); istr >> float4string; cout << float4string << '\n'; istr.str( string2int); istr >> int4string; cout << int4string << '\n'; return 0; }
Wenn ich erst den Int und dann den Float schreibe bekomme ich:
44
44.4Hier der Code:
//Code zum sofort Kopieren und selber Kompilieren #include <iostream> #include <sstream> using namespace std; int main( void ) { string string2int; istringstream istr; int int4string; float float4string; string2int = "44.4"; istr.str( string2int); istr >> int4string; cout << int4string << '\n'; istr.str( string2int); istr >> float4string; cout << float4string << '\n'; return 0; }
Wieso funktioniert es in der einen Richtung und nicht in der anderen? Das zerstört meine Annahme, dass der Stream nach der Benutzung erst in irgendeiner Weise gesäubert werden muss, damit er wieder benutzt werden kann?
Für die StringStreams mache ich es nicht so ausführlich (einfach die IStringStreams in StringStreams umschreiben).
Die erste Konvertierung (erst Float dann Int) gibt das selbe Ergebniss wie bei den IStringStreams.
Die Zweite (also erst Int dann Float) liefert:
44
0.444Allerdings habe ich hier
strstr << string2int;
benutzt.
Wenn ich auf ".str()" umstelle entsteht genau das gleich Ergebniss wie bei den IStringStreams.
Inwiefern arbeitet also der überladene Operator "<<" anders als ".str()"?So und jetzt kommt ihr
Mir ist das gerade zu hoch
Ich würde mich freuen, wenn jemand hier sein Wissen mit mir teilen könnte...Viele Grüße!
-
lol ... Sieht echt lustig aus, wie die Fehler entstehen und dabei ist die Lösung so einfach. Also, ich lache über die Fehler nicht über dich, damit wir uns verstehen
Also, zu deinen Fragen:
1. Unterschied zwischen
stringstream
undistringstream
.stringstream
besteht aus einem Input- und einem Outputstream. Man kann also Daten lesen und schreiben.istringstream
besteht dagegen nur aus einem Inpustream (lesen) undostringstream
(den gibt es auch noch) ist nur ein Outputstream (schreiben). Kurz als Code:std::stringstream ss; std::istringstream iss; std::ostringstream oss; std::string temp; ss << "Test"; // Compiler - OK ss >> temp; // Compiler - OK iss << "Test"; // Compiler - FEHLER iss >> temp; // Compiler - OK oss << "Test"; // Compiler - OK oss >> temp; // Compiler - FEHLER
Wenn man also nur einen Input- oder nur einen Outputstream verwenden muss, kann man überflüssige Funktionen fallen lassen. Das führt nicht unbedingt zu einem Geschwindigkeitsgewinn, könnte aber Fehlersicherheit liefern, damit man nicht plötzlich irgendwo schreibt, obwohl man eigentlich nur lesen wollte.
2. Erklärung was in deinem ersten Beispiel (
istringstream
, float -> int) passiert://Code zum sofort Kopieren und selber Kompilieren #include <sstream> #include <iostream> int main() { std::string string2int; std::istringstream istr; // istr wird initialisiert und die Fehler auf 0 gesetzt. int int4string; float float4string; string2int = "44.4"; istr.str(string2int); istr >> float4string; // der Float wird gelesen, 44.4. Das Ende des Streams wird erreicht. EOF-Flag wird gesetzt. cout << float4string << '\n'; istr.str(string2int); // Input verändern, Fehlerflags bleiben bestehen. Stream glaubt immer noch, er sei am Ende. istr >> int4string; // Fehler! int4string wird mit nichts überschrieben. cout << int4string << '\n'; // uninitialisierter int wird ausgegeben. return 0; }
Einfach vor dem zweiten
istr.str(string2int);
noch einistr.clear();
hinsetzen.3. Erklärung was in deinem zweiten Beispiel (
istringstream
, int -> float) passiert://Code zum sofort Kopieren und selber Kompilieren #include <sstream> #include <iostream> int main() { std::string string2int; std::istringstream istr; // istr wird initialisiert und die Fehler auf 0 gesetzt. int int4string; float float4string; string2int = "44.4"; istr.str(string2int); istr >> int4string; // Der int wird gelesen, es bleibt im stream noch ein ".4". cout << int4string << '\n'; istr.str(string2int); // ".4" wird durch "44.4" ersetzt. istr >> float4string; cout << float4string << '\n'; // Alles war erfolgreich. Ein Fehler wurde nie ausgelöst. return 0; }
4. Erklärung was in deinem dritten Beispiel (
stringstream
, float -> int) passiert:
Es passiert das gleiche, wie im ersten Beispiel. EOF Flag wird gesetzt und nicht gelöscht.5. Erklärung was in deinem vierten Beispiel (
stringstream
, int -> float) passiert. Womöglich wirst du es nun bereits erahnen://Code zum sofort Kopieren und selber Kompilieren #include <sstream> #include <iostream> int main() { std::string string2int; std::stringstream str; // istr wird initialisiert und die Fehler auf 0 gesetzt. int int4string; float float4string; string2int = "44.4"; str.str(string2int); str >> int4string; // Der int wird gelesen, es bleibt im stream noch ein ".4". cout << int4string << '\n'; str << string2int; // An ".4" wird "44.4" angehängt, neu haben wir ".444.4". str >> float4string; // Wir lesen ".444" aus und es bleibt ".4" übrig. cout << float4string << '\n'; // 0.444 wird ausgegeben. // Alles war erfolgreich. Ein Fehler wurde nie ausgelöst. // Allerdings ist der Output, wohl nicht das, was man wollte. return 0; }
Ich hoffe das hilft weiter!
C++ Referenz: http://www.cplusplus.com/reference/
Grüssli
-
Hallo Dravere,
danke dir erstmal für die schnelle Antwort!
Lach ruhig - wer den Schaden hat usw. ...Also:
zu 1.)
Das leuchtet mir ein mit den In- respektive Output streams. Allerdings benutze ich ja in meinemistringstream
Beispielistringstream.str( "string" )
um einen String "einzulesen" und gleichzeitigistringstream >> "int"
um seinen Inhalt auszugeben. Bezieht sich die Beschränkung also nur auf die<< >>
Operatoren?zu 2.)
Das ist sehr verständlich - Danke! (Ich hatte zwischendurch das.clear()
auch schon mal drin, aber es ging bei "Trial and Error" irgendwie verloren)zu 3.)
Auch klar - habe mir gerade angeschaut, dass ich mitstringstream::seekg
auch einfach den Get-Pointer auf Null hätte setzten können.zu 4.)
Keine weiteren Fragen.zu 5.)
Hätte ich also statt dem<<
Operator (heißt der nicht Shift Operator?)stringstream::str()
benutzt, wäre wieder das gleich wie in 3.) rausgekommen?!Also nochmal vielen Dank, deine Antwort war sehr akurat und genau das, was ich mir erhofft (allerdings nicht notgedrungen auch erwartet) habe.
Grüße aus Kopenhagen!
-
Schakai schrieb:
Lach ruhig - wer den Schaden hat usw. ...
Du musst die Fehler auslachen, damit sie sich verziehen, sonst haben sie freude dich zu quälen ... oder so ähnlich
Schakai schrieb:
Allerdings benutze ich ja in meinem
istringstream
Beispielistringstream.str( "string" )
um einen String "einzulesen" und gleichzeitigistringstream >> "int"
um seinen Inhalt auszugeben. Bezieht sich die Beschränkung also nur auf die<< >>
Operatoren?Naja, es ist nicht wirklich ein einlesen. Du ersetzt den Inhalt, mit dem angegebenen. Es ist daher eher eine Art von Setter.
Also ja, diese Beschränkung bezog sich nur auf die Operatoren << und >>.Schakai schrieb:
Hätte ich also statt dem
<<
Operator (heißt der nicht Shift Operator?)stringstream::str()
benutzt, wäre wieder das gleich wie in 3.) rausgekommen?!Korrekt und zwar zu beidem.
stringstream::str()
ersetzt den Inhalt imstringstream
, der Operator << dagegen, fügt es nur am Ende an, ist also eine Art von Append.
Der Operator <<, bzw. >>, heisst Shiftoperator. Allerdings ist das manchmal ein wenig verwirrend, erst recht bei den Streams, wo dieser Operator überladen ist für andere Zwecke.Schakai schrieb:
Also nochmal vielen Dank, deine Antwort war sehr akurat und genau das, was ich mir erhofft (allerdings nicht notgedrungen auch erwartet) habe.
Gerngeschehen.
Grüssli