vector <struct> in Datei schreiben und einlesen



  • Ich habe versucht folgendes zu programmieren. In einer Headerdatei Header.h habe ich folgendes struct definiert:

    struct Struct
    	{
    	    Struct( string e_, string d_, string k_, bool m_ )
    	        : Param1( e_ ), Param2( d_ ), Param3( k_), Param4( m_)
    	    {}
    		string Param1;
    		string Param2;
    		string Param3;
    		bool Param4;
    
    	    // Struktur mit operatoren zum Lesen und Schreiben derselben ausstatten
    	    friend std::ostream& operator<<( std::ostream& out, const Struct& s )
    	    {
    	        return out << s.Param1 << "|" << s.Param1 << "|" << s.Param1 << "|" << s.Param4; 
    	    }
    	    friend std::istream& operator>>( std::istream& in, Struct& s )
    	    {
    	    	getline(in, s.Param1, '|');
    	    	getline(in, s.Param2, '|');
    	    	getline(in, s.Param3, '|');
    	    	in >> s.Param4;
    	        return in;
    	    }
    	};
    

    und außerdem habe ich in Header.h folgendes definiert.

    Vector <Struct> vs;
    

    In der main.cpp lege ich einen vector <Struct> vs an und fülle einen Vektor v wie folgt: Ausserhalb der main definiere ich

    Header v;
    

    Dann schreibe ich in der main:

    int abbruch = 1;
    	int s = 0;
    	while ( abbruch != 0) {
    
    		string Param1;
    		string Param2;
    		string Param3;
    
    		cout << "Geben Sie Param1 ein:" <<endl;
    		getline(cin, Param1);
    		cout <<"\nGeben sie Param2 ein:" <<endl;
    		getline(cin, Param2);
    		cout << "\nGeben Sie Param3 ein:" << endl;
    		getline(cin, Param3);
    		v.vs.push_back(Header::Struct (Param1, Param2, Param3, 0));
    
    		cout << "\n\nFalls Sie keine weiteren Daten eingeben wollen, dann drücken Sie '0'." <<endl;
    		cout << "Für weitere Eingaben drücken sie '1'." <<endl;
    		s = cinint(0, 1);
    		if ( s == 0)
    			abbruch = 0;		
    	}
    

    Die Funktion cinint ist in der main.cpp wie folgt definiert:

    int cinint(int minint, int maxint){
        int wahl = 0;
        while ( ( !(cin >> wahl) || !( wahl >= minint && wahl <= maxint) ) ) {
        	cout << "\n Sie müssen eine Zahl von " << minint << " bis " << maxint << " eingeben!" <<endl;
            // falsche Eingabe
            std::cin.clear();
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
        }
        return wahl;
    }
    

    Ich möchte v in eine Datei schreiben und wieder auslesen. Dazu habe ich in Header.cpp folgende Funktionen definiert:

    void Header::toFile(const char* filename) {
            ofstream file( filename );
            file << vs.size() << endl; // Anzahl schreiben ist eine gute Sache
            copy( vs.begin(), vs.end(), ostream_iterator< Sruct >( file, "\n" ) );
    	}
    

    und

    void Header::fromFile(const char* filename)
    	{
    		ifstream fileIn;
    		fileIn.open( filename);
    
    		if( !fileIn )
    			cout << "Could not open the input file!" <<endl;
    		else
    		{				
    			size_t n;
    			fileIn >> n; // Anzahl lesen
    			cout << "Anzahl der zu ladenden Elemente = " << n << endl;
    
    			for ( int i = 0; i < n; ++i)
    			{
    				string dummy1;
    				string dummy2;
    				string dummy3;
    				bool  dummy4;			
    
    				fileIn >> dummy1 >> dummy2 >> dummy3 >> dummy4;
    				vs.push_back(Header::Struct (dummy1 , dummy2, dummy3, dummy4));
    			}
    		}	
    	}
    

    Das Schreinen in eine Datei funktioniert: so erhalte ich z.B. die Datei filename.txt

    2
    das ist|genauso wie|es sein soll|0
    leider ist| es doch nicht|ganz richtig|0

    Ich versuche nun in der main.cpp aus der Datei filename.txt zu lesen, indem ich folgende Funktion geschrieben habe:

    void Datensatzladen(Header &vos)
    {
    	char* filename = new char[1000];	
    	cout << "Bitte geben Sie einen Dateinamen der Form 'filename.txt' ein!" << endl;	
    	cout << "\n Dateiname ? ";
    	cin >> filename;	
    	ifstream fileIn;
    
    	vos.fromFile(filename);
    
    	delete[] filename;	
    	cout << "\nLaden der Daten beendet! Es wurden " << vos.vs.size() << " Datensätze geladen.\n" << endl;
    }
    

    Leider funktioniert das einlesen nicht. Als Trennzeichen wird nicht | verwendet sondern, das erste Leerzeichen, d.h. die Datensätze werden beim ersten Leerzeichen getrennt und nicht wie gewünscht beim |.

    Alternativ hatte ich folgendes versucht:

    In der main habe ich die while Schleife wie folgt geändert:

    while ( abbruch != 0) {
                    char* Param1 = new char[1000];
                    char* Param2 = new char[1000];
                    char* Param3 = new char[1000];
                    cout << "Geben Sie Param1 ein:" <<endl;
                    cin >> Param1;
                    cout <<"\nGeben Sie Param2 ein:" <<endl;
                    cin >> Param2;
                    cout << "\nGeben Sie Param3 ein:" << endl;
                    cin >> Param3;
                    v.vs.push_back(Header::Struct (Param1, Param2, Param3, 0));
                    cout << "\n\nFalls Sie keine weiteren Daten eingeben wollen, dann drücken Sie '0'." <<endl;
                    cout << "Für weitere Eingaben drücken sie '1'." <<endl;
                    s = cinint(0, 1);
                    if ( s == 0)
                            abbruch = 0;
            }
    

    In der Header.h habe ich alle string durch char* ersetzt und in der Header.cpp habe ich

    char* dummy1 = new char[1000];
                                    char* dummy2 = new char[1000];
                                    char* dummy3 = new char[1000];
    

    definiert.
    Leider kann ich auch so die Datensätze nicht aus der Datei einlesen
    Ich habe folgende Fragen:
    1. Wie kann ich meinen vector <Struct> aus der Datei einlesen?
    2. Wieso funktionieren meine beiden Ansätze nicht?
    3. Später möchte ich einzelne Elemente meines vector <struct> ersetzen, also in der Form v.vs[1].Param2 = „so ist es“;
    Kann ich das so einfach machen oder ist meine Struct und Vector <Struct> vs; dafür schlecht definiert?
    Für Antworten wäre ich sehr dankbar.


  • Mod

    Das ist ja komisch. Die Codeformatierung funktioniert bei deinem Beitrag nicht, aber wenn ich den gleichen Beitrag schreibe, geht's. Damit die Leute sich nicht beschweren, hier dein Beitrag noch einmal in lesbar:

    Ich habe versucht folgendes zu programmieren. In einer Headerdatei Header.h habe ich folgendes struct definiert:

    struct Struct
    	{
    	    Struct( string e_, string d_, string k_, bool m_ )
    	        : Param1( e_ ), Param2( d_ ), Param3( k_), Param4( m_)
    	    {}
    		string Param1;
    		string Param2;
    		string Param3;
    		bool Param4;
    
    	    // Struktur mit operatoren zum Lesen und Schreiben derselben ausstatten
    	    friend std::ostream& operator<<( std::ostream& out, const Struct& s )
    	    {
    	        return out << s.Param1 << "|" << s.Param1 << "|" << s.Param1 << "|" << s.Param4; 
    	    }
    	    friend std::istream& operator>>( std::istream& in, Struct& s )
    	    {
    	    	getline(in, s.Param1, '|');
    	    	getline(in, s.Param2, '|');
    	    	getline(in, s.Param3, '|');
    	    	in >> s.Param4;
    	        return in;
    	    }
    	};
    

    und außerdem habe ich in Header.h folgendes definiert.

    Vector <Struct> vs;
    

    In der main.cpp lege ich einen vector <Struct> vs an und fülle einen Vektor v wie folgt: Ausserhalb der main definiere ich

    Header v;
    

    Dann schreibe ich in der main:

    int abbruch = 1;
    	int s = 0;
    	while ( abbruch != 0) {
    
    		string Param1;
    		string Param2;
    		string Param3;
    
    		cout << "Geben Sie Param1 ein:" <<endl;
    		getline(cin, Param1);
    		cout <<"\nGeben sie Param2 ein:" <<endl;
    		getline(cin, Param2);
    		cout << "\nGeben Sie Param3 ein:" << endl;
    		getline(cin, Param3);
    		v.vs.push_back(Header::Struct (Param1, Param2, Param3, 0));
    
    		cout << "\n\nFalls Sie keine weiteren Daten eingeben wollen, dann drücken Sie '0'." <<endl;
    		cout << "Für weitere Eingaben drücken sie '1'." <<endl;
    		s = cinint(0, 1);
    		if ( s == 0)
    			abbruch = 0;		
    	}
    

    Die Funktion cinint ist in der main.cpp wie folgt definiert:

    int cinint(int minint, int maxint){
        int wahl = 0;
        while ( ( !(cin >> wahl) || !( wahl >= minint && wahl <= maxint) ) ) {
        	cout << "\n Sie müssen eine Zahl von " << minint << " bis " << maxint << " eingeben!" <<endl;
            // falsche Eingabe
            std::cin.clear();
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
        }
        return wahl;
    }
    

    Ich möchte v in eine Datei schreiben und wieder auslesen. Dazu habe ich in Header.cpp folgende Funktionen definiert:

    void Header::toFile(const char* filename) {
            ofstream file( filename );
            file << vs.size() << endl; // Anzahl schreiben ist eine gute Sache
            copy( vs.begin(), vs.end(), ostream_iterator< Sruct >( file, "\n" ) );
    	}
    

    und

    void Header::fromFile(const char* filename)
    	{
    		ifstream fileIn;
    		fileIn.open( filename);
    
    		if( !fileIn )
    			cout << "Could not open the input file!" <<endl;
    		else
    		{				
    			size_t n;
    			fileIn >> n; // Anzahl lesen
    			cout << "Anzahl der zu ladenden Elemente = " << n << endl;
    
    			for ( int i = 0; i < n; ++i)
    			{
    				string dummy1;
    				string dummy2;
    				string dummy3;
    				bool  dummy4;			
    
    				fileIn >> dummy1 >> dummy2 >> dummy3 >> dummy4;
    				vs.push_back(Header::Struct (dummy1 , dummy2, dummy3, dummy4));
    			}
    		}	
    	}
    

    Das Schreinen in eine Datei funktioniert: so erhalte ich z.B. die Datei filename.txt

    2
    das ist|genauso wie|es sein soll|0
    leider ist| es doch nicht|ganz richtig|0

    Ich versuche nun in der main.cpp aus der Datei filename.txt zu lesen, indem ich folgende Funktion geschrieben habe:

    void Datensatzladen(Header &vos)
    {
    	char* filename = new char[1000];	
    	cout << "Bitte geben Sie einen Dateinamen der Form 'filename.txt' ein!" << endl;	
    	cout << "\n Dateiname ? ";
    	cin >> filename;	
    	ifstream fileIn;
    
    	vos.fromFile(filename);
    
    	delete[] filename;	
    	cout << "\nLaden der Daten beendet! Es wurden " << vos.vs.size() << " Datensätze geladen.\n" << endl;
    }
    

    Leider funktioniert das einlesen nicht. Als Trennzeichen wird nicht | verwendet sondern, das erste Leerzeichen, d.h. die Datensätze werden beim ersten Leerzeichen getrennt und nicht wie gewünscht beim |.

    Alternativ hatte ich folgendes versucht:

    In der main habe ich die while Schleife wie folgt geändert:

    while ( abbruch != 0) {
                    char* Param1 = new char[1000];
                    char* Param2 = new char[1000];
                    char* Param3 = new char[1000];
                    cout << "Geben Sie Param1 ein:" <<endl;
                    cin >> Param1;
                    cout <<"\nGeben Sie Param2 ein:" <<endl;
                    cin >> Param2;
                    cout << "\nGeben Sie Param3 ein:" << endl;
                    cin >> Param3;
                    v.vs.push_back(Header::Struct (Param1, Param2, Param3, 0));
                    cout << "\n\nFalls Sie keine weiteren Daten eingeben wollen, dann drücken Sie '0'." <<endl;
                    cout << "Für weitere Eingaben drücken sie '1'." <<endl;
                    s = cinint(0, 1);
                    if ( s == 0)
                            abbruch = 0;
            }
    

    In der Header.h habe ich alle string durch char* ersetzt und in der Header.cpp habe ich

    char* dummy1 = new char[1000];
                                    char* dummy2 = new char[1000];
                                    char* dummy3 = new char[1000];
    

    definiert.
    Leider kann ich auch so die Datensätze nicht aus der Datei einlesen
    Ich habe folgende Fragen:
    1. Wie kann ich meinen vector <Struct> aus der Datei einlesen?
    2. Wieso funktionieren meine beiden Ansätze nicht?
    3. Später möchte ich einzelne Elemente meines vector <struct> ersetzen, also in der Form v.vs[1].Param2 = „so ist es“;
    Kann ich das so einfach machen oder ist meine Struct und Vector <Struct> vs; dafür schlecht definiert?
    Für Antworten wäre ich sehr dankbar.


  • Mod

    Harry313 schrieb:

    und außerdem habe ich in Header.h folgendes definiert.

    Vector <Struct> vs;
    

    Gar nicht gut. Definitionen haben in Headern nichts verloren. Wird der Header in zwei Übersetzungseinheiten eingebunden, dann hast du vs doppelt.

    void Header::fromFile(const char* filename)
    	{
    		ifstream fileIn;
    		fileIn.open( filename);
    				
    		if( !fileIn )
    			cout << "Could not open the input file!" <<endl;
    		else
    		{				
    			size_t n;
    			fileIn >> n; // Anzahl lesen
    			cout << "Anzahl der zu ladenden Elemente = " << n << endl;
    		
    			for ( int i = 0; i < n; ++i)
    			{
    				string dummy1;
    				string dummy2;
    				string dummy3;
    				bool  dummy4;			
    
    				
    				
    				fileIn >> dummy1 >> dummy2 >> dummy3 >> dummy4;
    				vs.push_back(Header::Struct (dummy1 , dummy2, dummy3, dummy4));
    			}
    		}	
    	}
    

    STOPP! Hier benutzt du nicht deinen oben definierten Leseoperator, sondern schreibst unnötigerweise eine falsche, neue Lesefunktion mit operator>>(istream&, string&) . Der trennt nicht bei '|', sondern bei Whitespace.

    void Datensatzladen(Header &vos)
    {
    	char* filename = new char[1000];	
    	cout << "Bitte geben Sie einen Dateinamen der Form 'filename.txt' ein!" << endl;	
    	cout << "\n Dateiname ? ";
    	cin >> filename;	
    	ifstream fileIn;
    
    	vos.fromFile(filename);
    	
    	delete[] filename;	
    	cout << "\nLaden der Daten beendet! Es wurden " << vos.vs.size() << " Datensätze geladen.\n" << endl;
    }
    

    😮 Du kennst doch string. Was soll das?

    while ( abbruch != 0) {
                    char* Param1 = new char[1000];
                    char* Param2 = new char[1000];
                    char* Param3 = new char[1000];
                    cout << "Geben Sie Param1 ein:" <<endl;
                    cin >> Param1;
                    cout <<"\nGeben Sie Param2 ein:" <<endl;
                    cin >> Param2;
                    cout << "\nGeben Sie Param3 ein:" << endl;
                    cin >> Param3;
                    v.vs.push_back(Header::Struct (Param1, Param2, Param3, 0));
                    cout << "\n\nFalls Sie keine weiteren Daten eingeben wollen, dann drücken Sie '0'." <<endl;
                    cout << "Für weitere Eingaben drücken sie '1'." <<endl;
                    s = cinint(0, 1);
                    if ( s == 0)
                            abbruch = 0;
            }
    

    😮 Du kennst doch string. was soll das?

    In der Header.h habe ich alle string durch char* ersetzt und in der Header.cpp habe ich

    char* dummy1 = new char[1000];
                                    char* dummy2 = new char[1000];
                                    char* dummy3 = new char[1000];
    

    definiert.

    😮 Du kennst doch string. Was soll das?

    Leider kann ich auch so die Datensätze nicht aus der Datei einlesen
    Ich habe folgende Fragen:
    1. Wie kann ich meinen vector <Struct> aus der Datei einlesen?

    Dein Leseoperator sah auf den ersten Blick durchaus richtig aus. Falls nicht, emelde dich nochmal.

    2. Wieso funktionieren meine beiden Ansätze nicht?

    Weil du deinen richtigen Operator gar nicht benutzt hast.

    3. Später möchte ich einzelne Elemente meines vector <struct> ersetzen, also in der Form v.vs[1].Param2 = „so ist es“;
    Kann ich das so einfach machen oder ist meine Struct und Vector <Struct> vs; dafür schlecht definiert?

    Klar, warum nicht? Dazu brauchst du dann einen entsprechenden (nicht-expliziten) Konstruktor (oder eher zwei, wenn du nicht nur Zeichenkettenliterale, sondern auch strings zulassen möchtest), der dir die Zeichenkette zerlegt.



  • Ja, es ist so einfach. Manchmal sieht man den Wald vor lauter Bäumen nicht. So einfach ist es:

    void Header::fromFile(const char* filename)
    {
    ifstream fileIn;
    fileIn.open( filename);

    if( !fileIn )
    cout << "Could not open the input file!" <<endl;
    else
    {
    size_t n;
    fileIn >> n; // Anzahl lesen
    cout << "Anzahl der zu ladenden Elemente = " << n << endl;

    for ( int i = 0; i < n; ++i)
    {
    Header::Struct dummy("", "", "", 0);
    fileIn >> dummy;
    vs.push_back(Header::Struct (dummy.Param1 , dummy.Param2, dummy:Param3, dummy.Param4));
    }
    }
    }

    Danke für die Hilfe. Manchmal sieht ein objektives Auge viel mehr. 😉 🙂


Anmelden zum Antworten