Binäres Auslesen von Zahlen funktioniert nicht richtig
-
Hi,
Ich habe ein Problem. Ich habe mit folgendem Code 5 Integer in eine Datei geschrieben. Das funktioniert auch:
#include <iostream> #include <fstream> #include <conio.h> #include <cstdlib> #include <ctime> #include <string> using namespace std; int main() { srand(time(NULL)); fstream stream; int amountOfNumbers=5; string fileName="zahlen.bin"; stream.open(fileName.c_str(), ios::out|ios::binary); if(stream.good()) { cout<<"\nIn Datei geschrieben(vor Sortieren):\n"; for(int i=0; i<amountOfNumbers; ++i) { int random=rand()%21; stream.write((char*)&random, sizeof(int)); cout<<random<<", "; } stream.close(); } else { cout<<"Konnte Zahlen nicht in Datei schreiben. Programm wird geschlossen!"; getch(); return 1; }Und mit diesem Code lese ich die Zahlen aus (funktioniert aber leider nicht). Er folgt direkt nach dem Schreibepart:
stream.open(fileName.c_str(), ios::in|ios::binary); if(stream.good()) { stream.clear(); //TODO: Geht's auch ohne? cout<<"\nAus Datei gelesen(vor Sortieren):\n"; while(stream.eof()==false) { int zahl; stream.read((char*)&zahl, sizeof(int)); cout<<zahl<<"("<<stream.tellg()<<"), "; } stream.close(); } else { cout<<"Konnte Zahlen nicht in Datei schreiben. Programm wird geschlossen!"; getch(); return 1; }Beides habe ich in ein Programm geschrieben.
Wenn ich jetzt Zahlen reinschreibe und auslese, liest er immer die letzte Zahl doppelt aus und tellg() teilt auch mit, dass die Adresse der doppelt ausgelesen Zahl ungültig ist, obwohl ich doch mit .EOF() das Fehlerflag auslese. Weiß jemand eine einfache Lösung?
-
Immer der gleiche Logikfehler bei Anfängern. Schlechtes Lehrbuch? Du machst:
1. Auf Fehler prüfen
2. Fehleranfällige Aktion durchführen
3. Daten von 2. Auswerten
4. Zurück zu 1.Rate mal, was wohl passiert, wenn 2. schief geht (bei dir passiert das am Dateiende).
Daher:
1. Fehleranfällige Aktion (Lesen)
2. Prüfen.
3. Verarbeiten
4. Zurück zu 1.
In C++ meistens geschrieben alswhile(Leseaktion) verarbeiten;außerdem solltest du nochmal dringend überdenken, weiter mit dem Lehrwerk zu arbeiten, aus dem du dein falsches Schema hast. Darf ich fragen, welches das ist?
-
Danke SeppJ für deine schnelle Antwort.
Schule, 2. Ausbildungslehrjahr Fachinformatiker Fachrichtung Anwendungsentwicklung.
-
Dann herzlichen Glückwunsch zu einem Lehrer, der sein Fach nicht beherrscht.
Klappt's denn, wenn du es änderst? Denk dran, dass read, wie fast alle Streamoperationen) eine Referenz auf den Stream selber zurück gibt. Das heißt du brauchst dir jetzt keinen abzubrechen mit if und break, sondern wirklich nur
while(stream.read((char*)&zahl, sizeof(int))) cout<<zahl<<"("<<stream.tellg()<<"), ";(Ich hoffe, die Klammern passen, habe hier im Editfenster keine Klammerhervorhebung)
-
Hat geklappt. Ich hab einfach mal 'ne Referenz bemüht. Aber eine Frage habe ich noch: Inwiefern wird denn ein Stream, also der Rückgabewert von read() oder write() auf true oder false bewertet, dass ich es eonfach als Bedingung verwenden kann?
-
Jeder (?) Stream hat einen operator bool, mit dem sich der Stream in einen bool konvertieren lässt, der dann nichts weiter als den Rückgabewert von good() zurückliefert. Könntest also mWn auch
while((stream.read(...)).good());schreiben.
-
ich sollte immer vorher in der Referenz nachschauen...
Edit: ist anscheinend nur bei C++11 so, bei den vorherigen Versionen wird es wohl zu void* konvertiert, bzw. zu etwas anderem, was sich wie bool verhält
-
Der Tobi schrieb:
Jeder (?) Stream hat einen operator bool, mit dem sich der Stream in einen bool konvertieren lässt,
Streng genommen ist es ein Operator, der eine void*-Konvertierung durchführt. Etwas ärgerlich, da man somit auch versehentlich einen Stream in einem Kontext benutzen kann, in dem ein Zeiger erwartet wird, ohne eine Fehlermeldung zu erhalten.