string ist bei Ausgabe mit printf (null)
-
Nein, benutze in C++
std::coutfür die Standardausgabe.printf()kommt aus C und kommt nur mit skalaren Typen zurecht. Ausserdem ist es durch die fehlende Typsicherheit recht fehleranfällig, wenn man nicht genau weiss, was man macht.
-
Ah, danke!
string hallo = "ichbineinstring"; char str[20] = "ichbinaucheinstring"; printf("%s",str); printf("\n"); cout << hallo << endl; getchar();So ist besser

-
PeterFragt schrieb:
Ah, danke!
string hallo = "ichbineinstring"; char str[20] = "ichbinaucheinstring"; printf("%s",str); printf("\n"); cout << hallo << endl; getchar();So ist besser

nicht wirklich...
using namespace std; const char str[] = "....."; cout << str << endl;bb
-
Ja. Und da es normalerweise keinen Grund gibt, sich mit
printf()rumzuschlagen, kannst du auch fürchar*den C++-Streamstd::coutnehmen. Dieser funktioniert nämlich genauso und erkennt im Gegensatz zuprintf()seinen Argumenttyp, du brauchst also kein"%s".
-
Verstehe, danke!
-
Und falls du doch mal für irgendeine Funktion einen char* auf deinen std::string brauchst (soll schon mal vorkommen), dann nimm wie gesagt die Methode c_str, also "hallo.c_str()" (so würde es auch mit printf klappen)...
-
ich behalts im Hinterkopf
-
string z = "lutsch0r!"; printf( "%s", z.c_str());
-
PeterFragt schrieb:
ich behalts im Hinterkopf
aber behalts mit const char* und nicht char* im hinterkopf ^^
braucht man aber eigtl nur für C-APIsbb
-
unskilled schrieb:
braucht man aber eigtl nur für C-APIs
Nö. Wie konstruierst du z.B. ein std::fstream-Objekt?

(In der Praxis benutzt man std::fstream natürlich nach Möglichkeit ohnehin nicht.)
-
audacia schrieb:
...
hab ja extra "eigentlich" geschrieben - ist ja nicht so, dass ich nicht daran gedacht hätte
danke ^^bb
-
Manchmal hat man ja auch mit C-APIs (oder C++-APIs, die trotzdem C-Strings verwenden) zu tun. Kann man sich nicht immer aussuchen, daher ist es auch gut, zu wissen was man in dem Fall mit seinen std::string's machen muss...
-
audacia schrieb:
Nö. Wie konstruierst du z.B. ein std::fstream-Objekt?

Das sollte doch im kommenden Standard angepasst werden.
audacia schrieb:
(In der Praxis benutzt man std::fstream natürlich nach Möglichkeit ohnehin nicht.)
Wie?
-
Nexus schrieb:
audacia schrieb:
(In der Praxis benutzt man std::fstream natürlich nach Möglichkeit ohnehin nicht.)
Wie?
Na du solltest natürlich fprintf/fscanf benutzen! Wusstest du das etwa nicht?

-
Nexus schrieb:
audacia schrieb:
(In der Praxis benutzt man std::fstream natürlich nach Möglichkeit ohnehin nicht.)
Wie?
Nun, die Streams sind in allen mir bekannten Implementationen langsamer als C-Streams (teilweise um Größenordnungen), und außerdem sind sie nicht moduslos, was Fehler in der Anwendung begünstigt und den korrekten Umgang massiv erschwert. Gewöhnlich ist man mit einem kleinen RAII-Wrapper um die C-Funktionen viel besser dran.
-
Okay, das kann gut sein, ich kenne die C-Funktionen aber auch zu wenig, um das genau beurteilen zu können.
Naja, ich hatte bisher eigentlich nicht viele Probleme mit
std::fstream, für meine Anwendungen reicht es. Ich finde zum Beispiel auch die Operatoren>>und<<sehr komfortabel und habe momentan nicht wirklich Lust, alle Überladungen nachzuprogrammieren.
-
Nexus schrieb:
Okay, das kann gut sein, ich kenne die C-Funktionen aber auch zu wenig, um das genau beurteilen zu können.
Man braucht die C-Funktionen nicht zu kennen, um zu sehen, daß es sich bei fstream um einen gewaltigen Designfehler handelt. Beispiele: die Existenz von fstream::good() und fstream::close().
-
audacia schrieb:
Man braucht die C-Funktionen nicht zu kennen, um zu sehen, daß es sich bei fstream um einen gewaltigen Designfehler handelt. Beispiele: die Existenz von fstream::good() und fstream::close().
Ja, die Streams sind zum Teil etwas speziell. Allerdings habe ich die bisher nicht so kritisch betrachtet, was auch daran liegen könnte, dass ich kaum Alternativen kenne.
Aber weshalb erachtest du die beiden Methoden als Designfehler? Weil sie durch andere Memberfunktionen eigentlich bereits abgedeckt sind (z.B. Dtor bei
close())?
-
audacia schrieb:
Nun, die Streams sind in allen mir bekannten Implementationen langsamer als C-Streams (teilweise um Größenordnungen), und außerdem sind sie nicht moduslos, was Fehler in der Anwendung begünstigt und den korrekten Umgang massiv erschwert.
1. Geschwindigkeit:
http://www.cplusplus.com/reference/iostream/streambuf/pubsetbuf/
Viele Implementationen haben standardmässig keinen Puffer gesetzt, weshalb sie als deutlich langsamer erscheinen. Der Puffer kann verdammt viel ausmachen.2. Moduslos:
http://www.cplusplus.com/reference/iostream/ios/exceptions/
Man kann sich über Modusänderungen sehr schnell und explizit informieren lassen.Grüssli
-
Nexus schrieb:
Aber weshalb erachtest du die beiden Methoden als Designfehler?
fstream::good(), weil es impliziert, daß ich stets manuell auf Fehler überprüfen muß. Wozu gibt es denn Exceptions?
fstream::close(), weil es das Objekt in einen Modus versetzt, in dem der Aufruf mancher Methoden nicht mehr gültig ist. Zudem steckt fstream noch in einer Vererbungshierarchie, in der es auf diese Weise das LSP verletzt.
Dravere schrieb:
2. Moduslos:
http://www.cplusplus.com/reference/iostream/ios/exceptions/
Man kann sich über Modusänderungen sehr schnell und explizit informieren lassen.Das ist nicht, was ich mit "moduslos" meine; siehe meine Ausführungen zu fstream::close().
Und daß man das Verhalten im Fehlerfalle umstellen kann, macht die Sache IMHO nur noch schlimmer, weil man dadurch ein fstream-Objekt mit noch einem Zustand behaftet, der ihn eigentlich nichts angeht. Beispiel:
void tryRead (istream& stream, ...) { stream.read (...); if (!stream.good ()) ...; // set default value } void foo (void) { std::fstream theFile ("someFile", ...); theFile.exceptions (>alles<); ... tryRead (stream, ...); // <-- }Hier verursacht der Aufruf von tryRead() unerwartetes Verhalten, da tryRead() sich auf das Standardverhalten des Streams verläßt. Korrekt müßte man tryRead() also so implementieren:
class StreamExceptionStatePreserver { private: ios_base::iostate prevState; public: StreamExceptionStatePreserver (ios& theStream, ios_base::iostate newState) : prevState (theStream.exceptions ()) { theStream.exceptions (newState); } ~StreamExceptionStatePreserver (void) { theStream.exceptions (prevState); } }; void tryRead (istream& stream, ...) { StreamExceptionStatePreserver esp (stream, >garnix<); stream.read (...); if (!stream.good ()) ...; // set default value }Ich weiß nicht, wie es dir geht, aber spätestens da schreit sämtliche mir verbliebene Intuition laut "Designfehler".
Eine Klasse, die derartige Workarounds erfordert, wird von mir i.d.R. ohnehin erst von einem adäquaten Wrapper umgeben, der die Komplexität in der Anwendung reduziert. Und wenn wir ohnehin beim Wrappen sind, können wir auch gleich die C-Funktionen wrappen, weil sie viel weniger Ballast haben und in der Praxis schlicht schneller sind, Puffer hin oder her.