Noch einmal: Wie lese ich aus einer TxtDatei ein?



  • Ich dreh hier echt gleich am Rad und getreu dem Motto neue Frage neues Thema hab ich jetzt einen eigenen Thread eröffnet.
    Hier das Problem, die Textdatei die EXAKT so aufgebaut ist:

    Peter Meyer 28 423432/2324
    Sabine Schmitt 22 2313/324

    Wie bekomm ich das Ding eingelesen, ich hab schon total viel mit getline rumprobiert und nun mit string aber es klappt nicht richtig:

    // Testphase /////////////////////////////////////////////
    void ReadList()
    {
    	ifstream List("List.txt");
    	if(List)
    		{
    			char  vorname[80], name[80], alter[80], telefonnummer[80];
    
    			// Solange das Ende der Liste nicht erreicht ist weiter hinzufügen
    			while(!List.eof())
    				{	
    				List>>vorname; 
    				List>>name; 
    				List>>alter;
    				List>>telefonnummer;
    
    				// Personen wieder nacheinander verketten, Funktion 300%ig In Ordnung
    				AddPerson(vorname, name, alter, telefonnummer);
    
    				// Testen ob die Daten richtig eingelesen werden, JA werden sie! Ausgabe stimmt,
    				// Liste wird neu erstellt und verkettet, es wird die Adresse der Strukturen ausgegeben
    				ReadPerson();
    				cout<<"Adresse: "<<pCurrentPerson<<"\n\n";
    				}
    			List.close();
    			cout<<"Liste erfolgreich eingelesen!\n";
    		}
    	else
    		cout<<"Datei konnte nicht eingelesen werden!\n";
    }
    

    Fehler:

    1.) Er scheint alles mit dem letzten Eintrag in der txt zu überschreiben, bei einem erneutem Aufruf von ReadPerson() in der main() wird immer nur der letzte Name angegeben, auch wenn ich in meiner Liste springe.

    2.) der vorname wird grundsätzlich unterschlagen, nur name, alter und nr werden angezeigt.

    wo liegt der verdammte fehler? was mach ich falsch?!?!?



  • Ich sehe Dein Problem nicht. Ich mag es auch nicht suchen, viel lieber möchte ich Dir mal schrittweise auf die Schnelle mal einen einfacheren Weg zeigen.
    (kann man sich auch aus der FAQ ableiten, ggf. isses aber auch was für. ka)

    Als erstes verwenden wir std::string.

    Wir kommen so zu einer struktur die ich mal so aussehen lasse:

    struct person
    {
    	string VName;
    	string NName;
    	int    alter;
    	string TNummer;
    };
    

    Ich nehme an Du verwaltest Deine Leutchen in einer Liste. Hierfür verwende ich nun mal std::list.

    Nun können wir bequem mit einer Schleife ähnlich wie Du es machst einlesen:

    #include <iostream>
    #include <string>
    #include <fstream>
    #include <list>
    using namespace std;
    
    struct person
    {
    	string VName;
    	string NName;
    	int	   alter;
    	string TNummer;
    };
    
    int main(int argc, char* argv[])
    {
    
    	// kennst Du ja bereits
    	std::ifstream datei("t:\\test.txt");
    	if(!datei)
    		return 20;
    
    	// unsere Liste die Kopien von person(en) aufnimmt
    	list<person> PersonenListe;
    
    	// Ich gehe hier davon aus das es garantiert ist das IMMER ganze Datensätze stehen.	
    	person temp;
    	while(datei>>temp.VName)	// Als erstes den Namen lesen und 
    	{							// dabei prüfen ob das geklappt hat
    		// danach den rest lesen
    		datei>>temp.NName;
    		datei>>temp.alter;
    		datei>>temp.TNummer;
    		// und in die Liste anfügen	
    		PersonenListe.push_back(temp);
    	}
    
    	// Kontrollausgabe
    	for(list<person>::iterator pos = PersonenListe.begin();pos != PersonenListe.end();++pos)
    	{
    		cout<<pos->VName<<' ';
    		cout<<pos->NName<<' ';
    		cout<<pos->alter<<' ';
    		cout<<pos->TNummer<<'\n';
    	}
    
    }
    

    Nun, das klappt schaut auch schon ganz hübsch aus. 😮

    Aber wir könnten noch die operatoren << und >> überladen. Somit schaffen wir es person überall da auszugeben und zu lesen wo >> und << verwendet wird.
    (Dateien Bildschirmausgabe StringStreams u.v.m.)

    Sie Signatur für diese Überladung sieht folgend aus:

    istream & operator>>(istream & instream,person & temp);
    ostream & operator<<(ostream & outstream,const person & temp);
    

    Damit kannst Du nun so tun als wäre person ein eingebauter Datentyp.
    cout<<"Der gewinner ist:"<<person;

    Kein lästiges Ausgeben der Einzelnen Elemente jedesmal wenn Du was ausgeben willst. Du kannst bestimmen wie die Ausgabe ablaufen soll.

    Die Funktion für die Ausgabe ist das gleiche wie zuvor, ohne Schleife:

    istream & operator>>(istream & instream,person & temp)
    {
    	instream>>temp.VName;
    	instream>>temp.NName;
    	instream>>temp.alter;
    	instream>>temp.TNummer;
    	return instream;
    }
    
    ostream & operator<<(ostream & outstream,const person & temp)
    {
    	outstream<<temp.VName<<' ';
    	outstream<<temp.NName<<' ';
    	outstream<<temp.alter<<' ';
    	outstream<<temp.TNummer<<'\n';
    	return outstream;
    }
    

    Mit dieser Hilfe können wir das Einlesen und die Kontrollausgabe auf folnde Zeilen reduzieren:

    while(datei>>temp)
        PersonenListe.push_back(temp);
    
     for(list<person>::iterator pos = PersonenListe.begin();pos != PersonenListe.end();++pos)
    		cout<<*pos;
    

    Hier das gesammte zum Compilieren:

    #include <iostream>
    #include <string>
    #include <fstream>
    #include <list>
    
    using namespace std;
    
    struct person
    {
    	string VName;
    	string NName;
    	int	   alter;
    	string TNummer;
    };
    
    istream & operator>>(istream & instream,person & temp);
    ostream & operator<<(ostream & outstream,const person & temp);
    
    istream & operator>>(istream & instream,person & temp)
    {
    	instream>>temp.VName;
    	instream>>temp.NName;
    	instream>>temp.alter;
    	instream>>temp.TNummer;
    	return instream;
    }
    
    ostream & operator<<(ostream & outstream,const person & temp)
    {
    	outstream<<temp.VName<<' ';
    	outstream<<temp.NName<<' ';
    	outstream<<temp.alter<<' ';
    	outstream<<temp.TNummer<<'\n';
    	return outstream;
    }
    
    int main(int argc, char* argv[])
    {
    
    	std::ifstream datei("t:\\test.txt");
    	if(!datei)
    		return 20;
    
    	list<person> PersonenListe;
    
    	while(datei>>temp)
    		PersonenListe.push_back(temp);
    
    	for(list<person>::iterator pos = PersonenListe.begin();pos != PersonenListe.end();++pos)
    		cout<<*pos;
    
    	return 0;
    }
    

    Mich persönlich stören noch die Schleifen. Ich persönlich (schon mal in deckung geh) finde es viel schöner das ganze mit hilfe von copy zu realisieren.
    Wir nutzen dabei die Hilfmittel istream:iterator ostream_iterator und copy:

    copy(beg,end,back_inserter(PersonenListe));
    	copy(PersonenListe.begin(),PersonenListe.end(),ostream_iterator<person>(cout));
    

    Du definierst die Person , packst es in eine Klasse, lieferst die operator<< und operator>> mit und schon kann sich das gesammte einlesen auf eine Zeile beschränken.

    Hier mal das Fragment zum selbsttesten:

    #include <iostream>
    #include <string>
    #include <fstream>
    #include <list>
    #include <iterator>
    
    using namespace std;
    
    struct person
    {
    	string VName;
    	string NName;
    	int	   alter;
    	string TNummer;
    };
    
    istream & operator>>(istream & instream,person & temp);
    ostream & operator<<(ostream & outstream,const person & temp);
    
    istream & operator>>(istream & instream,person & temp)
    {
    	instream>>temp.VName;
    	instream>>temp.NName;
    	instream>>temp.alter;
    	instream>>temp.TNummer;
    	return instream;
    }
    
    ostream & operator<<(ostream & outstream,const person & temp)
    {
    	outstream<<temp.VName<<' ';
    	outstream<<temp.NName<<' ';
    	outstream<<temp.alter<<' ';
    	outstream<<temp.TNummer<<'\n';
    	return outstream;
    }
    
    int main(int argc, char* argv[])
    {
    
    	std::ifstream datei("t:\\test.txt");
    	if(!datei)
    		return 20;
    
    	istream_iterator<person> beg(datei);
    	istream_iterator<person> end;
    
    	// Einlesen aller Personen der Datei.
    	// Wieder wird angenommen das ganze Datensätze vorhanden sind!
    	copy(beg,end,back_inserter(PersonenListe));
    
    	// Kontrollaugabe
    	copy(PersonenListe.begin(),PersonenListe.end(),ostream_iterator<person>(cout));
    	return 0;
    }
    

    Ich hoffe Dich auf neue Ideen gebracht zu haben 🤡


Log in to reply