Problem mit Binärdatei lesen & virtuelle Basisklasse



  • Hi!

    Das Problem plagt mich schon seit Tagen, also hab ich mich jetzt mal dazu durchgerungen euch hier um Hilfe zu fragen, vielleicht kann mir ja jemand helfen 🙂

    Ich habe folgendes Problem, mit einer Aufgabe, die ich lösen soll.

    Objekte von der Klasse Circle (dazu gleich mehr) sollen in einer Binärdatei gespeichert werden. In einem anderen Programm soll die Datei wieder ausgelesen werden.
    Die Klasse Circle wurde abgeleitet von der Klasse DrawingObject, welche die virtuelle Methode print() enthält.
    Jetzt hab ich mir folgendes überlegt um die Datei zu schreiben und anschließend zu lesen:
    (Der erste geschriebene Satz wird vor dem Schließen der Datei mit der Anzahl der geschriebenen Objekte beschrieben.)

    void main(void)
    {
    	Circle * c[50];
    	Circle * b[50];
    	int anzahl;
    	string in;
    
    	fstream datei("C:\\tmp\\test.dat", ios::out|ios::binary|ios::in|ios::trunc);	//Datei oeffnen
    	datei.seekg(sizeof(int), ios::beg);	//ersten Satz auslassen
    	cout << "Wieviele Kreise einlesen? ( Format: ((x,y),r) ): ";
    	cin >> anzahl;
    	for (int i = 0; i < anzahl; i++){
    		cout << "Objekt Nr. " << i+1 << " eingeben: ";
    		fflush(stdin);
    		getline(cin,in);
    		c[i] = new Circle(in);
    		datei.write((char*)c[i],sizeof(Circle));	//Satz schreiben
    	}
    
    	datei.seekg(0, ios::beg);			//an Anfang der Datei zurueck
    	datei.write((char*)&i,sizeof(int));	//ersten Satz Anzahl einfuegen
    	datei.close();
    
    	//----ab hier wird ausgelesen------
    
    	fstream datei1("C:\\tmp\\test.dat", ios::out|ios::binary|ios::in);
    	datei1.read((char*)&anzahl,sizeof(int));	//ersten Satz Anzahl lesen
    	for (int i = 0; i < anzahl; i++){
    		b[i] = new Circle();
    		datei1.read((char *)b[i],sizeof(Circle));
    		cout << "Objekt Nr. " << i+1 << " ";
    		b[i]->print();
    	}
    	datei1.close();
    }
    

    Wenn ich das so mache funktioniert alles einwandfrei, die Objekte werden gespeichert, wieder ausgelesen und die Funktion print() wird ganz normal aufgerufen.

    Wenn ich jetzt aber "Datei lesen" und "Datei schreiben" in 2 verschiedene Programme packe - also das erste zum Anlegen der Datei, beschreiben der Datei... und das 2. zum lesen der Datei - bekomme ich immer einen Laufzeitfehler, an der Stelle, an der die Funktion print() aufgerufen wird. Die Attribute werden Problemlos beschrieben, nur die print() Fkt. ist nichtmehr aufzurufen.

    Der vollständigkeit halber:

    class DrawingObject{
    
    private:
    	int id;
    	static int maxID;
    	static int number;
    
    public:
    
    	DrawingObject(){...}
    
    	virtual void print(bool, bool) = 0;
    
    	~DrawingObject(){...}
    [.....]
    };
    

    und

    class Circle : public DrawingObject{
    public:
    	float x, y, rad;   //ja ich weiss, die sollten nicht public sein ^^
    
    	Circle(){...}
    
    	void print(bool, bool);
    [....]
    };
    
    void Circle::print(bool line = true, bool kon = false)
    {
    [...]
    	cout << "((" << x << ", " << y << "), " << rad << ")";
    	if ( line == true ){
    		cout << endl;
    	}
    [...]
    }
    

    Wär wirklich klasse wenn mir bei diesem, eher sehr speziellen Problem, jemand weiterhelfen könnte. Ich bin fast am verzeiwefeln...

    Vielen Dank schonmal im Voraus..
    Gruß izzy



  • 1. editier mal deinen post und änder die code-Tags durch cpp-Tags.

    1. void main(void) gibt es nicht - schreib stattdessen int main()

    Circle * c[50]; //<-
        Circle * b[50]; //<-
        int anzahl;
        string in;
    

    Was genau willst du damit machen? entweder du nimmst Circle *a = new Circle[50]; oder Circle a[50]; - beides geht nicht ^^

    außerdem solltest du dir mal den operator >> und << angucken - und den für deine Klasse überladen - dann nutzt du statt write bla einfach dateistream >> meinCircle und es geht...

    Außerdem ist eine print-Funktion nicht sehr sinnvoll... und ich könnte mich immer wieder über leute aufregen, die so etwas verzapfen:
    void print(bool, bool); woher soll nen außenstehender dann wissen, wofür die beiden bools da sind?

    bb



  • Was genau willst du damit machen? entweder du nimmst Circle *a = new Circle[50]; oder Circle a[50]; - beides geht nicht ^^

    Was stimmt den an einem Array von Zeigern auf Circle nicht? Er macht das nacher schon richtig, dass er da a[i] = new Circle macht.. (mal abgesehen davon, dass hier Standardcontainer eher angebracht wären..)
    Und zu alledem hat er vergessen den Speicher wieder freizugeben..

    außerdem solltest du dir mal den operator >> und << angucken - und den für deine Klasse überladen - dann nutzt du statt write bla einfach dateistream >> meinCircle und es geht...

    Er will das binär. Da ist nix mit den Operatoren. (Ausser man schreibt sich natürlich das ganze noch für binäre Klassen, ist aber nicht mal eben so schnell gemacht. Irgendwer hat das glaube ich mal hier im Forum ansatzweise gemacht..)

    Abgesehen davon ist der Code ziemlich wirr und das C/C++ mischmasch kann ja kaum funktionieren.. (fflush(stdin) unc co.)



  • Erstmal danke für die Antworten..

    drakon schrieb:

    Abgesehen davon ist der Code ziemlich wirr und das C/C++ mischmasch kann ja kaum funktionieren.. (fflush(stdin) unc co.)

    OK, das mag sein, dass das alles nicht sehr schön programmiert ist 😉
    Aber meine Eigentliche Verwirrung kommt daher, dass wenn ich Lesen und Schreiben im selben Programm mache funktionierts, und wenn Lesen und Schreiben auf 2 Programme verteile gehts nicht mehr...
    Das geht mir leider nicht in Kopf rein 😕

    Gruß



  • izzy123 schrieb:

    Erstmal danke für die Antworten..

    drakon schrieb:

    Abgesehen davon ist der Code ziemlich wirr und das C/C++ mischmasch kann ja kaum funktionieren.. (fflush(stdin) unc co.)

    OK, das mag sein, dass das alles nicht sehr schön programmiert ist 😉
    Aber meine Eigentliche Verwirrung kommt daher, dass wenn ich Lesen und Schreiben im selben Programm mache funktionierts, und wenn Lesen und Schreiben auf 2 Programme verteile gehts nicht mehr...
    Das geht mir leider nicht in Kopf rein 😕

    Gruß

    Es geht nicht wirklich darum, ob es schön ist, sonder, dass es schlichtweg falsch ist einen C++-Stream mit fflush (einer C-Funktion) leeren zu wollen..

    Naja. Wegen dem Rest kannst du mal mit dem Debuger schauen, ob du irgendwelche Objekte benutzt, die du in einem Zwischenschritt nicht richtig leerst.



  • Du kannst nicht einfach ein Objekt einer "nicht-POD" Klasse mit fread, fwrite, memcpy, memset etc. bearbeiten. C++ sieht diese Möglichkeit nicht vor bzw. "erlaubt" das nicht. D.h. wenn du willst dass deine Programme funktionieren solltest du es nicht machen.

    Was du möchtest nennt man "Serialisierung". Und es gibt zahlreiche (mehr oder weniger gute) Artikel zu dem Thema im Netz.



  • hustbaer schrieb:

    Du kannst nicht einfach ein Objekt einer "nicht-POD" Klasse mit fread, fwrite, memcpy, memset etc. bearbeiten. C++ sieht diese Möglichkeit nicht vor bzw. "erlaubt" das nicht. D.h. wenn du willst dass deine Programme funktionieren solltest du es nicht machen.

    Was du möchtest nennt man "Serialisierung". Und es gibt zahlreiche (mehr oder weniger gute) Artikel zu dem Thema im Netz.

    Danke für den Tipp mit der Serialisierung, habs nun damit hinbekommen!

    drakon schrieb:

    Es geht nicht wirklich darum, ob es schön ist, sonder, dass es schlichtweg falsch ist einen C++-Stream mit fflush (einer C-Funktion) leeren zu wollen..

    Danke auch für den Tipp, werd ich nichtmehr machen... hat nur so "gut" funktioniert, dann dacht ich "machst halt mal" ^^

    Gruß


Anmelden zum Antworten