Array einer Klasse in eine Datei schreiben



  • Mein Problem ist folgendes: Im folgenden Programm befindet sich das Array? "lekt[VOK_MAX]", in welchem z.B. ein Englisches Wort und dessen Übersetzung steht (z.B. hut Hut). Ich will nun alles mit der Funktion "void DateiSchreiben()" in eine Datei schreiben, jedoch funktioniert das nicht so, wie ich mir das vorgestellt hab.

    Habe es mit Vokabel.write(lekt[i], 241) probiert, jedoch bekomme ich die Meldung, dass es sich bei "i" um keinen konstanten Wert handelt. Wie kann ich das ganze ändern, damit es funktioniert?
    Ich denke mir fehlt da einfach nur grundsätzliches Verständnis von Klassen, oder?

    // HEADER FILES ***************************************************************
    #include <iostream>
    #include <fstream>
    #include <string.h>
    #include <stdlib.h>
    using namespace std;
    
    // DEFINES ********************************************************************
    # define VOK_L 120
    # define VOK_MAX 120
    
    // CLASSES ********************************************************************
    class Vokabel
    {
    private:
    	char fremd[VOK_L];
    	char deutsch[VOK_L];
    	int prio;
    
    public:
    	Vokabel()
    	Vokabel(char *f, char *d) 
             Vokabel(char *f, char *d, int p); 
    	friend class lektion;
    };
    
    class lektion {
    private:
    	Vokabel lekt[VOK_MAX];
    	int aktnum, aktion;
    
    	void Aufnehmen() 
             void DateiLesen() 
     	void Abfragen() 
             void DateiSchreiben() 	
             void Ausgeben() 
    
    public:
    	lektion()
    };
    
    // MAIN PROGRAM ***************************************************************
    int main()
    {
    	lektion l1;
    	return 0;
    }
    


  • Du willst also das Array lekt in eine Datei schreiben?

    fwrite ( const void * buffer, size_t size, size_t count, FILE * stream );
    

    Für buffer nimmst du einach den Array, für size die Größe der Struktur (kannst du mit "sizeof" ermitteln), für count nimmst du die Anzahl der Elemente.

    In deinem Fall würde die Funktion um das Array lekt zu speichern beispielsweise in etwa so aussehen:

    void lektion::DateiSchreiben(char* path)
    {
     FILE* pFile = fopen(path,"w+");
    
     fwite(this->lekt, sizeof(Vokabel), MAX_VOK, pFile);
    
     fclose(pFile);
    }
    


  • Hallo,
    Vorweg eines. Wenn du dir das Leben nicht unnötig schwer machen möchtest, empfehle ich std::string.

    Ansonsten zu deinem Problem:
    Wenn du das Array in deinem Programm beispielsweise verändert hast, und diese hinzugefügten/editierten/gelöchsten/etc. Vokabeln nun persistinent speichern möchtest, würde ich das ungefähr so machen:

    bool writeIntoFile(const std::string& s)
    {
           std::ofstream out(s.c_str());
           if(out)
           {
                  for(unsigned int i = 0; i < VOK_L; ++i)
                          out << fremd[i] << '\n' << deutsch[i] << endl;
                  return true;
           }
           return false;
    }
    

    Eventuell halt direkt einen File-Stream als Argument übergeben oder aber es die Klasse komplett verwalten lassen (und nicht die Funktion).

    Im Prinzip speicherst du nun in Zeile 2*n das Fremdwort und in 2*n+1 die deutsche Übersetzung.

    Hoffe ich konnte helfen.

    Caipi



  • @ Caipi
    Wir müssen es so machen, wie angegeben. Wie du geschrieben hast, würde es auch nicht funktionieren, da nicht zwingend alle eingelesenen Vokabeln auch in die Datei geschrieben werden

    @ MAG
    Thx, geschrieben wird schonmal 🙂 Es sind nurnoch diese Zeichen ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ zwischen den Wörtern, aber ich denke das liegt daran, dass nicht alle Vokabeln die max. Länge haben und nicht das ganze Array voll ist. Werde mal etwas rumtüfteln, hat mir aber schon sehr geholfen



  • Sorry, das wird wohl mein Fehler sein. Du musst die Datei im binären Modus öffnen. Es wird wohl nicht an leeren Einträgen liegen, da du statische Arrays zum Speichern der Wörter verwendest haben alle Einträge die gleiche Größe, auch wenn sie nur "Leerzeichen" enthalten.
    Das Klassen-Array wird mit der von mir geposteten Funktion sozusagen 1:1 in die Datei geschrieben und kann so direkt wieder eingelesen werden, später.
    Also nimm für den Modus beim Öffnen zum Schreiben statt "w+" einfach "wb+".
    Dann sollte es funktionieren. Wenn du später eine Datei wieder einlesen willst,
    kannst du das so machen:

    void lekt::DateiLesen(char* path)
    {
     FILE* pFile = fopen(path,"rb");
    
     fread(this->lekt, sizeof(Vokabel), MAX_VOK, pFile);
    
     fclose(pFile);
    }
    

    Du rufst also praktisch fread genau wie fwrite auf und hast dann das Array wieder geladen.



  • Ne, an den Zeichen hat sich nichts geändert. Sind weiterhin vorhanden. Es wär schon ideal, wenn die Datei so aussehen würde:

    hut Hut dog Hund cat Katze

    aber das wird wohl nicht gehen, oder?

    Der Standardkonstruktor macht eigentlich nur folgendes:

    Vokabel(){	
    		fremd[0]='\0';
    		deutsch[0]='\0';
    		prio=0;
    	}
    

    Würde es helfen, wenn ich das ganze Array mit irgendeinem Wert initialisiere ?



  • Das mit dem '\0' lass lieber raus!
    Mal abgesehen davon, siehst du diese "ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ" Zeichen in der Ausgabe deines Programms oder wenn du die geschriebene Datei mit dem Texteditor öffnest?



  • Wenn ich die Datei einlese und z.B. lekt[1] ausgebe, dann bekomm ich einen haufen Sonderzeichen. Die Vokabeln sind nicht lesbar.



  • Okay, wenn du's als Textdatei haben willst in der Form "hut Hut ...",
    dann machs halt doch wie Caipi vorschlug.

    Naja wie du es auch machst hast du immer noch das Problem mit den "nicht vollen" Strings. Am besten du nimmst statt char-Arrays einfach C++-Strings.
    Du musst dafür alle char-Arrays durch strings ersetzen.
    Aber wenn du schon C++ strings verwendest kannst du auch gleich ofstream verwenden:

    void lekt::SchreibeDatei(string path)
    {
     ofstream out(path.c_str());
    
     for(int i=0;i<MAX_VOK;i++)
     {
      out << lekt[i].fremd << " " << lekt[i].deutsch << endl;
     }
    
     out.close();
    }
    

    Dabei brauchst du dir dann keine Gedanken mehr um die Länge der Strings machen.



  • Genau nach sowas ( lekt[i].fremd ) hab ich gesucht 🙂 Wusste nicht, dass man auf das Array in diesem Fall wie auf ne Klasse zugreifen kann.

    Kannst mir vielleicht noch verraten, wie ich das ganze wieder ordnungsgemäß einlese? 🙄

    Habs mal so probiert:

    void DateiLesen() {
    		ifstream Vokabeln("Vokabeln.txt"); 
    
    		for(int i=0;i<VOK_MAX;i++) 
    		{ 
    		Vokabeln >> lekt[i].fremd >> lekt[i].deutsch >> endl; 
    		} 
    
    		Vokabeln.close(); 
    	}
    

    Aber da war ich wohl zu Naiv 😃



  • >>std::endl
    

    Geht das?



  • wenn ich dich richtig verstanden habe: ja.



  • Nein.
    Du willst doch nicht "endl" einen Wert zuweisen, also in "endl" Daten einlesen? Denn genau das machst du mit der Anweisung ">> endl;".
    Mit der Schreib-Funktion werden Alle Wörter mit Leerzeichen bzw. Zeilenumbruch getrennt. Das heißt jede Zeile besteht aus Fremdwort, Leerzeichen und nachfolgend der deutschen Übersetzung. Danach folgt halt ein Zeilenumbruch, und eine neue Zeile beginnt.
    Wenn du nun also wieder alles einlesen willst könntest du das wie folgt machen:

    void lekt::DateiLesen(string path)
    {
     ifstream in(path.c_str());
    
     char cSingleBuffer; // Speichert ein einziges Zeichen, wie " " oder "\n"
    
     for(int i=0;i<MAX_VOK;i++)
     {
      ///---Fremdwort--------Leerzeichen------Übersetzung--------Zeilenumbruch-
      in >> lekt[i].fremd >> cSingleBuffer >> lekt[i].deutsch >> cSingleBuffer;
     }
    
     in.close();
    }
    

    Ich habs nicht ausprobiert, aber theoretisch sollte es so funktionieren.



  • na wenn das so ist... natürlich, er hat ja ">>" und nicht "<<" geschrieben.


Anmelden zum Antworten