Kurze Frage , Kurze Antwort
-
Again, kurze Frage zum "zeichen für zeichen" einlesen :
char buffer[20] std::ifstream datei("test.txt", std::ios_base::in); for (int i = 0; i < ...){ buffer[i] = datei.get(); //oder datei.get(buffer[i]); }
Egal, oder ist eine Verison vorzuziehen?
-
Nachtrag:
oder wenn ich die Länge des Textes weiß, Variante 3:
char *cp = new char [len] ; datei.getline(cp, len);
-
int_type get();
- Reads one character and returns it if available. Otherwise, returns Traits::eof() and sets failbit and eofbit.
basic_istream& get(char_type& ch);
- Reads one character and stores it to ch if available. Otherwise, leaves ch unmodified and sets failbit and eofbit. Note that this function is not overloaded on the types signed char and unsigned char, unlike the formatted character input operator>>.
- liefert dir im Fehlerfall eof zurück, 2) ändert im Fehlerfall buffer[i] nicht.
Ich würde 2) verwenden, weil man dann einfach schön den Stream prüfen kann.
if (!datei.get(buffer[i])) error();
-
cpp_beg schrieb:
Nachtrag:
oder wenn ich die Länge des Textes weiß, Variante 3:
char *cp = new char [len] ; datei.getline(cp, len);
Vorausgesetzt du verwendest ordentliches RAII und kein new.
-
Ich check das mit dem RAII nicht ganz. Hab mir den Wikipedia Artikel schon durchgelesen, aber wie wäre das in oben geannten Bspl. angewandt?
-
beg_offl schrieb:
Ich check das mit dem RAII nicht ganz. Hab mir den Wikipedia Artikel schon durchgelesen, aber wie wäre das in oben geannten Bspl. angewandt?
Zum Beispiel mit dem Nutzen von std::vector oder std::unique_ptr<char[]>.
-
Nathan schrieb:
int_type get();
- Reads one character and returns it if available. Otherwise, returns Traits::eof() and sets failbit and eofbit.
basic_istream& get(char_type& ch);
- Reads one character and stores it to ch if available. Otherwise, leaves ch unmodified and sets failbit and eofbit. Note that this function is not overloaded on the types signed char and unsigned char, unlike the formatted character input operator>>.
- liefert dir im Fehlerfall eof zurück, 2) ändert im Fehlerfall buffer[i] nicht.
Ich würde 2) verwenden, weil man dann einfach schön den Stream prüfen kann.
if (!datei.get(buffer[i])) error();
Würde dann folgendes Reichen um eine Datei Zeichen für Zeichen einzulesen? Das ist Fehlerprüfungstechnisch etwas dünn oder??
std::fstream orig("orig.txt", std::ios_base::in); char c; while( orig.get(c) ){ std::cout << c; }
-
Solte ich EOF evtl. mit einbauen?
while( orig.get(c) ){ if ( c != EOF) { //??? std::cout << c; } else.... }
-
beg_offl schrieb:
Solte ich EOF evtl. mit einbauen?
Nein, c kann nie EOF sein.
Die erste Version ist absolut richtig und deckt alle Fehler ab.
-
Ähm ja, c sollte dann natürlich ein INT sein.
Also brauch ich gar keine Abfragen mehr auf EOF machen?
-
Noch ne Frage, wie werte ich eine Schreibaktion mit write aus?
datei.write(reinterpret_cast <char*>(&myInt), sizeof(myInt); ??? if !(????);
Ich werd jetzt aus der Refernz nicht schlau, da steht bei Return Value "*this" . Ok ich weiß das "this" ein Zeiger aufs Objekt ist oder so (Ich bin noch nicht soweit mit Lernen), aber ledier ist kein Bspl. dabei wie ich das auswerten könnte....
-
beg_ok schrieb:
Also brauch ich gar keine Abfragen mehr auf EOF machen?
Nathan schrieb:
Die erste Version ist absolut richtig und deckt alle Fehler ab.
Typische Leseschleifen in C++ gehen so:
Leseoperationen auf Streams geben (bis auf ganz wenige Ausnahmen) immer den Stream selbst als return-Wert zurück. Dadurch kann man einerseits mehrere Leseoperationen nacheinander schalten:cin >> wert1 >> wert2 >> wert3;
Da passiert folgendes:
cin >> wert1
wird durchgeführt. Der Rückgabewert davon ist wieder cin (oder genauer: Eine Referenz darauf), also bleibtcin >> wert2 >> wert3;
übrig. Dann das ganze nochmal und es bleibtcin >> wert3;
übrig. Und dann das ganze nochmal, und der Rückgabewert des gesamten Ausdrucks ist also am Ende nurcin
. Wozu ist das noch gut? Nun, die Streams kann man auch zu Wahrheitswerten konvertieren (also zu Werten, wie sie von if, while, for, usw. verarbeitet werden). Dabei gilt: Ist irgendein Fehlerflag des Streams gesetzt (unter anderem kann das EOF sein, aber auch alle anderen Fehler werden so markiert), dann kommtfalse
raus, ansonsten - das heißt, wenn der Stream einsatzbereit ist - kommttrue
raus. Man kann so also ganz einfach prüfen, ob eine Leseaktion erfolgreich war:if (cin >> wert1 >> wert2 >> wert3) // Lesen war erfolgreich else // Es gab einen Fehler
(Man denke da dran, dass, wenn die erste Aktion,
cin >> wert1
, bereits fehlschlug, alle weiteren Aktionen auf dem Stream automatisch fehlschlagen, bis die Fehlerflags ge-clear
-ed wurden. Es passiert also nichts komisches mit wert2 oder wert3.)Üblicherweise hat man ja auch mehrere Leseaktionen in einer Schleife, da geht das dann genau so:
while (cin >> wert) { verarbeite(wert); }
Da werden so lange Werte gelesen und verarbeitet, bis ein Fehler auftritt. Das kann beispielsweise das Erreichen des Dateiendes sein. Und ganz wichtig: Im Fehlerfall wird der Schleifenkörper gar nicht mehr ausgeführt, es werden also nur korrekt gelesene Werte verarbeitet. Man sieht oft in schlechten Lehrbüchern:
while(!cin.eof()) { cin >> wert; verarbeite(wert); }
Das ist, wie du nun hoffentlich erkennst, doppelt falsch. Erstens fängt es nicht alle Fehler ab, weil nur auf eof geprüft wird (im Falle anderer Fehler hätte man also eine Endlosschleife) und zweitens wird selbst nach Auftreten von EOF noch einmal ein wert verarbeitet, obwohl er gar nicht korrekt gelesen wurde! Merke: Der Fehlerzustand tritt erst ein, dann wenn eine Leseaktion fehlschlägt, nicht wenn die nächste Leseaktion fehlschlagen könnte. Bloß weil die letzte Leseaktion den Lesezeiger direkt vor dem Ende einer Datei positioniert hat, ist das noch so lange nicht EOF, bis nicht versucht wurde, über das Ende der Datei zu lesen. Der Computer kann schließlich nicht wissen, ob jemals eine solche Aktion stattfinden wird und vorschnell Alarm schlagen.
Diese Dinge sollten in jedem guten Anfängerbuch erklärt werden (Minus der Erklärung, was man nicht tun sollte). Es ist daher erschreckend, dass du das nicht weißt und lässt mich an der Qualität deines Lehrstoffs zweifeln. Ganz schlimm wäre es, wenn dort sogar die falsche Variante demonstriert wird. Dann sollte das Buch direkt in den Mülleimer wandern.
Noch zwei kleine Anmerkungen:
-Stattwhile
werden oft auch andere Schleifentypen, zum Beispielfor
benutzt.while
ist nur ein Beispiel.
-Der kleine Aufsatz über Fehlerzustände und wann sie eintreten (nach dem Fehler!), gilt so in allen Sprachen, die von C abstammen (C++, Java, viele mehr) und in vielen anderen Sprachen. Manchmal trifft man Leute, die sagen, dass es in C anders wäre. Das stimmt nicht! Das ist fast nur bei einigen altertümlichen Lehrsprachen der Fall, wie Pascal oder frühen BASIC-Dialekten. Die Leute, die das verbreiten, haben also das letzte Mal ihre Programmierkenntnisse in den 1980ern aufgefrischt (oder haben von Leuten gelernt, für die das gilt).P.S.: Das alles gilt natürlich ebenso für Schreibaktionen, wenn man tatsächlich mal prüfen möchte, ob diese erfolgreich waren.
-
Danke, gute Erklärung
Zum Buchstoff : Ich arbe mit dem C++ Primer, da habe ich über EOF noch nicht wirklich was gefunden, kommt erst ziemlich weit hinten, aber ich bastle mal wieder davor schon etwas rum.
Ausserdem hab ich noch The C++ Programming Language von Bjarne S. aber die deutsche Version. (Finde das Buch nicht so den Hit. , aber es "ging billig her" ).Auf jeden Fall hab ich gestern noch das C++ Kochbuch erhalten und siehe an :
void loadCSV(istream& in, vector<vector<string>*>& data) { vector<string>* p = NULL; string tmp; while (!in.eof( )) { getline(in, tmp, '\n'); // Hole die nächste Zeile p = new vector<string>( );
=> ist jetzt nur ein freigewähltes Beispiel, aber die while(! .eof) Abfrage kommt da relativ häufig vor.
-
cpp_beginner schrieb:
=> ist jetzt nur ein freigewähltes Beispiel, aber die while(! .eof) Abfrage kommt da relativ häufig vor.
Das ist ein schlechtes Buch, und nicht nur wegen dem eof.
-
Daran siehst, du dass der Primer und der Stroustrup was taugen und das C++-Kochbuch in den Müll gehört*. Das sieht man noch an mehr Punkten aus dem Beispiel: Zeiger auf vector? Ungekapseltes new? 3 dicke Fehler auf 6 Zeilen!
*: Das ist kein dummer Spruch, das ist wörtlich gemeint und mein voller Ernst. Meinetwegen auch als Türstopper oder Briefbeschwerer. Aber es gehört nicht gelesen und auch nicht weiterverkauft, außer vielleicht an deine Feinde.
-
Ungekapseltes new?
Wie meinst du das?
-
beg__ schrieb:
Ungekapseltes new?
Wie meinst du das?
Lies einfach ein gutes Buch. Ich jedenfalls habe keine Lust, dir jeden Mist, den du irgendwo aufgeschnappt hast, einzeln auszutreiben. Weißt du was Kapselung ist? Falls nein -> Grundlagen. Weißt du was new ist? Falls nein -> Gut so
. Falls du weißt was beides ist, kannst du dann erraten, was wohl ein ungekapseltes new ist?
-
Am Besten Du schreibst mal ein Buch.
Mit Kapselung verbinde ich jetz eher was in Richtung Klassen.
New wird in allen von Dir als vorhin als "gut" bewerteten Büchern mal so wie im obrigen Beispiel verwendet. Also nicht gekapselt.
-
Sollte man cin.sync oder eher cin.ignore verwenden?
In unseren Uni Unterlagen wird meistens cin.sync verwendet...?
-
Üblicherweise hat man ja auch mehrere Leseaktionen in einer Schleife, da geht das dann genau so:
while (cin >> wert) { verarbeite(wert); }
Kann ich das auf Dateioperationen genauso übernehmen?
Bspl:
std::fstream fp("test.txt", std::ios_base::in); std::string buffer; char c; while (fp.get(c)){ buffer.push_back(c); }
MÜsste passen oder? Wenn fp.get nichts mehr liefert wird schleife nicht ausgeführt... Kann man das so machen oder eher schlecht?