Kurze Frage, Kurze Antwort

coder111

Mitglied
ifstream (input file stream) liest Dateien ein, ofstream schreibt raus.
Ich verstehe nicht, was damit gemeint ist.
---------------------------------------------------------------------------------------------------------

In den Kommentaren stehen ein paar Fragen zur Dateiverarbeitung.
C++:
 string dateiname = "Testdatei";
    ofstream datei(dateiname);
    datei << "geschriebener Text.\nZweite Zeile!\n"; // Was macht diese Zeile? Was macht der << operator?
    datei.close();

    // Lesen derselben Datei und Anzeige der Zeilen
    ifstream quelle(dateiname); // Objekt für Eingabestrom
    cout << "Der Inhalt von " << dateiname << " ist:\n";
    while (quelle.good())
    {
        // Was machen die nächsten 3 Zeilen?
        // Wozu die Variable zeile?
        // Warum wird in der while Schleife nicht auf endoffile geprüft?
        // Obwohl quelle ein ifstream ist (also Lesevorgang) wird zeile in quelle kopiert (also ein Schreibvorgang) ?
        string zeile;
        getline(quelle, zeile); // Zeile lesen
        cout << zeile << '\n';
    }
    // Datei wird am Programmende automatisch geschlossen.
---------------------------------------------------------------------------------------------------------

Wenn man ios::binary nicht verwenden würde, dann wären nur Textdateien kopierbar.
Welche Art von Textdateien wären mit ios::binary auch noch kopierbar?
C++:
ifstream quelle(dateiname, ios::binary);
---------------------------------------------------------------------------------------------------------

Wann sollte man nach dem close() auch ein clear() verwenden?
---------------------------------------------------------------------------------------------------------

Hätte man hier auch mit getline() kopieren können?
C++:
char ch;
while (quelle.get(ch)) {
ziel.put(ch); // zeichenweise kopieren
}
---------------------------------------------------------------------------------------------------------
 
Zuletzt bearbeitet:

sheel

I love Asm
Gleich vorneweg: Diese Streamklassen sind nicht wirklich toll, zB. weil sie sich für viele Missverständisse anbieten, und für komplexere Dateiverarbeitung ziemlich nutzlos sind.

Ich verstehe nicht, was damit gemeint ist.
ifstream ist dazu da, den Inhalt einer Datei (auf der Festplatte oder sonstwo) in Variablen deines Programms zu übertragen. ofstream macht umgekehrt Variableninhalte zu Dateien.

Zu der Frage wegen << : ofstream ist eine Klasse, also ein in sich abgeschlossenes Ding mit eigenen Variablen und Funktionen (eine Funktion ist zB. close, wie man die aufruft siehst du ja im Code). Da ofstram ja in Dateien schreiben soll, wäre auch eine Funktion write sinnvoll, der man einen Wert zum Schreiben übergeben kann....
Vorerst unabhängig davon: C++ weiß, wie man zB. 1+1 addiert. Aber was ist, wenn man zwei Klassenvariablen mit Plus addieren will? Rein technisch gesehen ist das (manchmal) möglich; eine Klasse kann für so Operatoren wie Plus Funktionen festlegen, die dafür aufgerufen werden sollen. Für datei+1 (mit ofstream datei) wird also keine mathematische Addition gemacht, sondern eine bestimmte Funktion von datei aufgerufen; zumindest falls ofstream eine Plusfunktion hätte (hat es nicht). Was es aber hat ist eine Funktion für <<, weil der Erfinder von ofstream gedacht hat, es wäre doch toll << statt.write zu schreiben. (Seufz). ... Kurz, es ist nur eine komische Schreibweise für eine ganz normale Funktion. (Btw., cout ist auch so ein Ding, mit seinem <<)

Was machen die nächsten 3 Zeilen?
Eine Zeile aus der Datei lesen (die Funktion getline ist eine Möglichkeit dafür), und dann ausgeben.
Wozu die Variable zeile?
Damit man den Wert, den getline einliest, speichern kann und dann ausgeben kann?
Obwohl quelle ein ifstream ist (also Lesevorgang) wird zeile in quelle kopiert (also ein Schreibvorgang) ?
Zeile wird nicht in Quelle kopiert. Warum diese Annahme?

Warum wird in der while Schleife nicht auf endoffile geprüft?
Beim Lesen von Dateien gibts drei Situationen: Es funktioniert, die Datei ist aus, und es ist irgendein Fehler aufgetreten (von denen es mehr als genug gibt). Wenn man prüft, ob die Datei noch nicht aus ist, ist das keine Garantie, dass der nächste Lesevorgang funktioniert. Und das will man hier ja eigentlich wissen, ob die Datei aus ist ist nebensächlich.
Aber auch der derzeitige Code ist nicht ideal. Wenn bisher kein Fehler aufgetreten ist, wird die Schleife weitergemacht, gelesen, die neue Lesung nicht geprüft und schon ausgegeben. Wenn diese aktuelle Auslesung danebengeht hat das ganze good-prüfen nicht geholfen.
getline hat auch einen Rückgabewert, der sich als if-Bedingung eignet...
C++:
string zeile;
while(getline(quelle, zeile))
    cout << zeile << '\n';
So hängt die Schleife jetzt wirklich vom getline-Erfolg ab.
(Ob wegen was anderem als Dateiende abgebrochen wurde könnte man später prüfen und reagieren; hier ist nur mal wichtig, dass die Schleife fertig ist)

Wann sollte man nach dem close() auch ein clear verwenden?
Gar nicht. Wenn man mit dem Stream fertig ist ist das komplett egal.

Wenn man ios::binary nicht verwenden würde, dann wären nur Textdateien kopierbar.
...
Eine "Textdatei" ist eine grauenhafte Erfindung, die Generationen von Programmieranfängern falsche Sachen einlernen lässt (mich auch, während der Schulzeit).
...
a) Eine Datei besteht aus Bytes, jedes Byte (übliche Definition 8 bit) hat ein Nummernwert zwischen 0 und 255 (inkl.)
b) Das sind nur Nummern, man braucht etwas, um Buchstaben zu haben. Deswegen gibt es Tabellen (und auch komplexere Zuordnungssysteme), die zB. sagen A ist 65 usw. (das selber ist ein sehr großes Thema, hier egal). Außer Buchstaben haben auch Satzzeichen Nummern, auch Ziffern (nicht die selben wie der Wert, die sichtbare Zahl 1 hat also nicht Tabelleneintrag 1), und ein paar unleserliche Zeichen für technische Gründe, auch Sonderfälle wie "Zeilenwechsel" ...
c) und das ist alles, was es in Dateien gibt. Nummern, die man auch als Zeichen verstehen kann, manchmal lesbarer Text und manchmal aber auch nicht. So gesehen könnte man eine Datei, die lesbaren text enthält, Textdatei nennen, aber das ist leider nicht alles.

Normalerweise werden die Byte von der Datei unverändert von/zu Programmvariablen übertragen. Bis zB. die Firma Microsoft irgendwann hergegangen ist und sich gedacht hat, in Windows und ein paar Programmen davon müssen wir das ändern. Es wurde ein zweiter Modus eingeführt, wie Dateien geöffnet werden können, das normale haben sie Binärdatei genannt, und das zweite Textdatei.
Binärdateien verhalten sich wie gesagt normal, und Textdateien ändern die Zeilenumbrüche (nicht mehr und nicht weniger): Ein Zeilenwechsel ist normalerweise Bytenummer 10. Beim Schreiben von Programm zu Datei macht Windows für "Textdateien" zwei Byte draus, 13 10. Umgekehrt werden beim Einlesen die zwei Byte 13 10 nur als 10 ins Programm gegeben. Grund gibt es dafür keinen wirklichen, außer dass sie es so machen wollten. (Der Fairness halber muss gesagt sein, dass Apple auch Blödsinn mit Zeilenumbrüchen gemacht hat, aber immerhin keine zwei Byte).
Kurz, wenn man die Datei wirklich so haben will, wie sie ist, nimmt man den Binärmodus. Wenn es aber darum geht, Zeilen einzeln zu behandeln, und man will nicht immer das 13-Byte codemäßig entfernen (das readline von Windows tut das nicht), ist der Textmodus angenehmer (da wird die 13 eben rausgefiltert, noch vor readline usw. dazu kommen)

(Auf Linux usw.usw. ist das alles kein Problem. ios::binary gibt es zwar, es macht aber keinen Unterschied ob man das angibt oder nicht)
 

coder111

Mitglied
Die Variable wert ist eine Konstante, also ein ncht änderbarer Wert. Bei jedem Schleifendurchlauf wird aber der Wert überschrieben.
Das ist doch dann keine Konstante mehr?

C++:
for(const double& wert : einVector){
    cout << wert << "\n";
}
 

sheel

I love Asm
Hi

Denkst du das nur (dass der Wert überschrieben wird) oder ist das bei einem echten Programm irgendwie beobachtbar?
 

sheel

I love Asm
Ja. cout gibt den Wert nur aus und ändert nichts daran.

Falls das Problem die Schleife ist, in jedem Durchgang bekommt man eine ganze neue wert-Variable (die dann const ist, bis es sie am Ende vom Durchgang nicht mehr gibt)