Wie Sie alle wissen, gibt es Bibliotheken, die Streams verwenden, z. B. iostream
und fstream
.
Meine Frage ist:
print
, fgets
usw. (zum Beispiel)? Sie benötigen ihre eigenen Operatoren <<
und >>
, aber alles, was sie tun, könnte in einfachen Funktionen wie oben implementiert werden, auch die Funktion
ist für mich viel lesbarer und logischer als
%Vor%Ich denke auch, dass all diese String-Abstraktionen in C ++ alle auf (weniger effiziente) Standardfunktionsaufrufe in Binärdateien kompiliert werden.
Streams haben eine bessere Typsicherheit.
Zum Beispiel kann printf("%s", a);
schrecklich falsch gehen, wenn a
eine ganze Zahl ist. cout << a;
hat dieses Problem nicht.
Ein weiteres Problem besteht darin, dass Streams den Objektorientierten Designmethoden besser entsprechen.
Zum Beispiel haben Sie eine einfache Anwendung, die eine Ausgabe schreibt und dann möchte, dass die Ausgabe in eine Datei statt in die Konsole geht. Bei C-Aufrufen müssen Sie alle Aufrufe von printf
durch Aufrufe von fprintf
ersetzen und dafür sorgen, dass FILE*
auf dem Weg erhalten bleibt. Mit Streams ändern Sie einfach die konkrete Klasse des Streams, den Sie verwenden, und das ist es, der Großteil des Codes bleibt gleich:
Zum einen ermöglicht es Ihnen, das C ++ - Objektmodell zu nutzen, um Funktionen zu erstellen, denen es egal ist, ob sie auf Standardausgabe, eine Datei oder einen Netzwerk-Socket schreiben (wenn Sie einen Netzwerk-Socket haben, der von% stammt Code%). ZB
%Vor%Und ähnlich für Eingabeströme.
Streams haben auch einen Vorteil, wenn es um die Eingabe und Ausgabe von Objekten geht. Was würde passieren, wenn Sie ein Objekt mit ostream
einlesen wollten?
Selbst wenn es einen geeigneten Spezifizierer gäbe, wie würde scanf
wissen, wie man die Mitglieder des Objekts ausfüllt? Bei C ++ - Streams können Sie scanf
überladen und
Und es wird funktionieren. Ähnliches gilt für operator<<
. Sie können also den Objektserialisierungscode an einer Stelle schreiben und müssen sich an keiner anderen Stelle darum kümmern.
C ++ - Streams sind typsicher. In C, wenn Sie sagen:
%Vor%Sie erhalten keine Fehlermeldung, obwohl die Konvertierung falsch ist.
Sie scheinen sehr grundlegende C ++ Fragen zu stellen. Welches C ++ - Lehrbuch verwenden Sie, das deckt sie nicht ab?
printf ist nicht typsicher. Die Cout-Schnittstelle ist auch allgemeiner, was eine Menge von Dingen erlaubt, die mit der printf-Version nicht verfügbar sind. Ein gutes Beispiel ist, dass Ihr Stream-Operator für Ihre Typen, wenn Sie es richtig machen, sich auf std :: ostream als Stream bezieht, nicht auf cout. So können Sie das Ziel der Ausgabe ändern, indem Sie einfach einen anderen Stream verwenden. Um dies mit printf zu tun, müssen Sie eine ganze Menge plattformabhängiger Überschreibung der Ausgabehandles durchführen.
Ich denke auch, dass all diese String-Abstraktionen in C ++ alle auf (weniger effiziente) Standardfunktionsaufrufe in Binärdateien kompiliert werden.
Denk alles was du willst. Bis Sie Ihre Annahme tatsächlich testen, wird Ihre Meinung nicht viel Gewicht haben. Außerdem müssen Sie den Abstraktionsverlust in Betracht ziehen, der in der modernen Softwareentwicklung normalerweise viel wichtiger ist.
Abgesehen davon, dass sie typsicher und polymorph sind, sind Streams portabler. Auf einigen Systemen erfordert printf mit einem langen "% d" und auf einigen Systemen "% ld".
Ein weiterer Vorteil von Streams ist, dass sie erweiterbar sind. Mit Streams können Sie Ihre benutzerdefinierten Klassen wie eingebaute Typen arbeiten lassen:
%Vor%Und jetzt können Sie ein foo genau wie alles andere ausdrucken:
%Vor%C ++ IOStreams sind lächerlich ineffizient (in den meisten Implementierungen, die ich kenne). Oft ist das kein Problem, aber wenn es ist, ist die Bibliothek im Grunde nutzlos. Es ist auch ein guter Punkt, dass die Syntax nicht intuitiv ist (und sehr, sehr ausführlich). Die Bibliothek ist komplex und unnötig schwer zu erweitern. Es ist auch nicht sehr flexibel. Im Gegensatz zu etwas wie der STL sieht IOStreams wirklich wie ein böser Traum aus. Aber es ist hier, und wir sind dran.
Der Grund, warum es hier ist, und der Grund, warum es so aussieht, ist, dass es früher entwickelt wurde, bevor C ++ eine ausgereifte Sprache war. Bevor wir jahrzehntelange Erfahrung hatten, uns zu sagen, was gutes Bibliotheksdesign ist und was nicht. Bevor jemand wirklich wusste, was die Optionen waren.
C ++ benötigte eine E / A-Bibliothek, die besser als C war. Und in einigen wichtigen Punkten sind C ++ IOStreams besser . Sie sind typsicher und erweiterbar, wie andere bereits erwähnt haben. Durch die Implementierung eines einzelnen Operators kann ich eine benutzerdefinierte Klasse ausdrucken. Das konnte mit printf
nicht gemacht werden. Ich muss mir auch keine Sorgen darüber machen, Format-Spezifizierer falsch zu bekommen und Müll wegen fehlender Typsicherheit auszudrucken.
Diese Dinge benötigt um behoben zu werden. Und hey, in den frühen Tagen waren virtuelle Funktionen und das Überladen von Operatoren die Scheiße . Es sah cool aus. Natürlich wollten Bibliotheken diese Funktionen nutzen.
Die IOStreams-Bibliothek ist ein Kompromiss zwischen:
stdio.h
Die Bibliothek erreicht nicht all dies, und ich glaube, dass wir heute mit unserer jahrzehntelangen Erfahrung mit der Sprache eine weitaus bessere Bibliothek hätten entwerfen können. Aber Mitte der 90er Jahre, als sie nach einer I / O-Bibliothek zum Hinzufügen suchten, war dies das Beste, was sie finden konnten.
In C ++ können Sie übrigens printf verwenden. Also wenn du das magst, mach weiter und benutze es.
Streams werden für viel mehr verwendet als das Schreiben von Ausgaben an die Konsole. Sie sind eine allgemeine Lösung für die Datenpufferung, die von der Bildschirmausgabe über die Verarbeitung von Dateien bis hin zu Netzwerkverkehr und Schnittstellen zu Eingabegeräten angewendet werden kann. Ihre Daten können in Streams schreiben (oder lesen), ohne sich darum zu kümmern, wohin diese Daten tatsächlich gehen.
Nehmen wir an, Sie haben ein komplexes Objekt, das Sie in die Ausgabekonsole, in eine Protokolldatei und in ein Debugging-Fenster-Popup schreiben können. Wirst du drei Funktionen schreiben, die fast genau dasselbe tun, oder wirst du eine Funktion schreiben, der du einen (y) Ausgabestrom gibst?
Eigentlich
%Vor%scheint mir viel intuitiver als
%Vor%Wenn Sie vorher nie als Druckvorlage erscheinen würden, würden Sie auf keinen Fall wissen, was das ist.
In beiden Fällen
%Vor% (in mehreren Sprachen einschließlich Python :() macht viel mehr Sinn:)
Ich benutze immer noch printf, hauptsächlich weil es einfach ist, das Ausgabeformat zu steuern.
Für mich ist Typsicherheit kein Hauptvorteil, weil es leicht vom Test abgefangen werden kann, wenn man bedenkt, dass ein konsolenbasiertes Programm wesentlich einfacher zu testen ist als UI-basierte oder webbasierte Anwendungen. Wenn Sie keinen Test durchführen, können schwerwiegendere Fehler die Kompilierzeit überbrücken.
Ich stimme auch nicht mit einem anderen Grund überein, dass der Streß von Ansprüchen aufgrund der Austauschbarkeit flexibler ist. Es entspricht der Verwendung von fprintf (fout, ...) für die Austauschbarkeit. Wenn Sie die Ausgabe umleiten müssen, verwenden Sie die Pipe. Wenn Sie in einer Bibliothek sind, warum geben Sie nicht einfach einen String zurück und lassen den Anrufer entscheiden, wohin er geht?
stringstream
ist sicherer als snprintf
/ sscanf
, weil es die Möglichkeit eines Pufferüberlaufs (auch "graceful failures") vollständig vermeidet.