Objekte in Datei schreiben und lesen!
-
-
Ja, die Sache mit dem Eintragen ist das Problem, mir ist deine Klasse zu umständlich. ABer in Kürze:
#include <fstream> //Arbeit mit Ströhen aus/in Dateien #include <iostream> using namespace std; int main() { ofstream ziel; //Ausgabestrom mit Namen ziel ziel.open("ziel.txt",ios::out|ios::binary); //Datei ziel.txt öffnen, wir wollen hinein schreiben und wir wollen den "Text" //der Datei haben (Wenn es z.B. ein Programm wäre) if(!ziel) //Mit dem überladenen Operator ! prüfen wir, ob die Datei geöffnet/erstellt werden konnte cerr<<"Fehler!!!"; //cerr=Fehlerkanal else ziel<<"Das ist ein Test!"; //Wie mit cout, nur in die Datei und nicht in die Ausgabe ziel.close(); //Schließen, sonst können wir die Datei nicht nochmal öffen string einlesen("Fehler!"); ifstream quelle; quelle.open("ziel.txt",ios::in|ios::binary); //Zum Einlesen öffen if(!quelle) cerr<<"Fehler!!!"; else quelle>>einlesen; cout<<einlesen; //Hoffentlich: "Das ist ein Test!" cin.get(); //quelle.close(); //Macht der Destruktor für uns };
-
@Kingruedi:
Und was machst du jetzt, was ich nicht mache? Sie(?) wollte schließlich die ganze sache Abspeichern und dann wieder lesen, das hab ich halt versucht...
Aber einen überladenen operator{<<,>>} zu definieren ist natürlich ein guter Schachzug. Was aber bewirkt sowas:friend std::ostream &operat...
? Ich glaube du erlaubst gleichzeitig ostream auf deine Daten zuzugreifen und sagst, das du einen ostream& zurückgibst.
-
Also Grundsätzlich hab ich das ja verstanden, aber bekomm ich das überhaupt in meine verkettete Liste rein ? Das speichern kann ich mir noch gut vorstellen, aber wie siehts mit dem einlesen aus wenn das Programm gestartet wird ? Immerhin soll man danach beim letzten eingelesen Namen weitermachen können! Gar nicht so einfach...!
-
ness schrieb:
@Kingruedi:
Und was machst du jetzt, was ich nicht mache? Sie(?) wollte schließlich die ganze sache Abspeichern und dann wieder lesen, das hab ich halt versucht...
Aber einen überladenen operator{<<,>>} zu definieren ist natürlich ein guter Schachzug. Was aber bewirkt sowas:friend std::ostream &operat...
? Ich glaube du erlaubst gleichzeitig ostream auf deine Daten zuzugreifen und sagst, das du einen ostream& zurückgibst.
Ja, das muss auch so sein. Denn ohne friend, koennte er nicht die Daten ausgeben
und die <</>>-Ops koennen nicht als Memberfunction implementiert werden. Ein
ostream& muss man zurueckgeben, um das nicht neuschreiben zu
muessen, gebe ich hier mal ein Link zu Volkards aelterem Kurs, wo das sehr gut
erklaert ist:http://www.volkard.de/vcppkold/operatoren_ausserhalb_von_klassen.html
mfg
v R
-
@ness
siehe http://www.cpp-tutor.de/cpp/le12/le12_05.htm[EDIT] vieeeeeeeelllll zu langsam
-
OK also das schreiben in eine Datei klappt jetzt mit meinem Code. Blos weiß ich einfach nicht wie ich den Kram einlesen kann ? Das ganze müsste ja ganz am Anfang von Main eingelesen und in die verkettete Liste eingetragen werden. Aber wie ??? Wenn man dann einen neuen User einträgt soll die Liste quasi fortgeführt werden.
Hier mein veränderter Code mit der Datei schreibe Funktion:
#include <iostream> #include <string> #include <fstream> using namespace std; class Person{ private: string name; Person *next; public: void setDaten(Person **liste_pointer); void getDaten(); friend std::ostream &operator<<(std::ostream &out,Person const &p) { out << p.name << '\n'; return out; } friend std::istream &operator>>(std::istream &in,Person &p) { std::getline(in,p.name); return in; } }; void Person::setDaten(Person **liste_pointer){ if(NULL==(*liste_pointer)){ *liste_pointer=new Person; cout<<"\nName: "; cin>>(*liste_pointer)->name; (*liste_pointer)->next=NULL; std::ofstream out("datei.txt"); out << **liste_pointer; } else{ setDaten(&((*liste_pointer)->next)); } } void Person::getDaten(){ if(this!=NULL){ cout<<"\n\nName: " <<name; next->getDaten(); } } int main(){ Person *wurzel=NULL; int auswahl=0; for(;;){ cout<<"\n\n1) Name eingeben" <<endl; cout<<"2) Alle Namen ausgeben" <<endl; cout<<"\nAuswahl: "; cin>>auswahl; fflush(stdin); if(auswahl==1){ wurzel->setDaten(&wurzel); auswahl=0; } if(auswahl==2){ wurzel->getDaten(); } } return 0; }
Danke Leute!
-
Nachtrag:
Pustekuchen! Ich seh ja eben erst das der immer nur den letzten Namen in meine Datei schreibt. !??? Jetzt bin ich verwirrt.
-
friend std::ostream &operator<<(std::ostream &out,Personen const &p)
asche über das Haupt desjenigen, der kurz vorher noch das gesagt hat:
Dafür gibt es doch extra das Stream Konzept in C++, das erlaubt es einen, dann eben Objekte auf allen möglichen Streams auszugeben (Dateien, Konsolen, Netzwerk etc.)
das wiederspricht sich nämlich, da ostream schon ein typedef auf basic_ostream<char,char_traits<char> > ist, und man so a( nicht mit neuen netzwerkresourcen arbeiten könnte, und man b) alle w- versionen vergessen könnte.
richtig wärs wohl so:
template<class charT,class traits> friend std::basic_ostream<charT,traits> &operator<<(std::basic_ostream<charT,traits> &out,Personen const &p)
sorry, king, darauf musste ich noch hinweisen :), kannst dich ja bald mal revanchieren
//edit ist zwar in diesem fall nicht ganz akut, aber man weis ja nie, wie elemente dritter implementiert sind, und ob man das ganze nicht auch mal über wcout ausgeben können will
-
@vr: Was du sagst ist mir bekannt, eogentlich wollte ich nur wissen was das "HALT" sollte? Ich _habe_ doch die tollen Ströme benutuzt, auch wenn ich << und >> nicht überladen habe.
@Annika: Versuche mal die Klasse etwas umzubauen, so das sie einfacher wird. So das sie Liste sich selber vrwaltet, und du nicht Wurzel, ... speichern musst sondern alles aufeinmal in der Liste. Mein Beispiel oder auch std::list (kompliziert) könnte dir ein Bild geben.
-
Ich muss es leider so machen. Ist ne Bedingung der Aufgabe das ich meine Liste so aufbau. Leider...
-
OK jetzt weiss ich warum immer nur 1 Name in der Datei steht, weil sie immer wieder neu angelegt wird, denn die Methode wird ja auch mehrmals angelegt. Definier ich dieses:
std::ofstream out("datei.txt");außerhalb der Methode schreibt er komischerweise gar nichts mehr in die Datei. Komisch...!
-
Nabend,
sorry, king, darauf musste ich noch hinweisen :), kannst dich ja bald mal revanchieren
Warum musst du immer so unverschaemt sein?
@vr: Was du sagst ist mir bekannt, eogentlich wollte ich nur wissen was das "HALT" sollte? Ich _habe_ doch die tollen Ströme benutuzt, auch wenn ich << und >> nicht überladen habe.
Ups, sry. Da hab ich dich glaube ich falsch verstanden :). So ein 'halt'
rutscht mir manchmal auch raus, das ist mit Sicherheit nicht persoenlich
gemeint gewesen. Er wollte lediglich darauf hinweisen, dass man hier
prima den Op << und >> auf otzes Art und Weise (jaja ich meine das so :D)
ueberladen kann.Zum Thema Listen. Eine einfach verkettete Liste implementiert man i.d.R so:
class Person{ private: string name; Person *next; public: Person() : next(0) //0 makiert das ende {} //ich versteh nicht ganz, warum hier Person**? //void setDaten(Person **liste_pointer); //so ganz spontan haette ich das so gemacht: void setDaten(const Person& p); void getDaten(); friend std::ostream &operator<<(std::ostream &out,Person const &p) { out << p.name << '\n'; return out; } friend std::istream &operator>>(std::istream &in,Person &p) { std::getline(in,p.name); return in; } }; void Person::setDaten(const Person& p){ Person* tmp = this; //this ist kopf der liste Person* newPerson = new Person; //daten kopieren newPerson->name = p.name; //an das ende der liste laufen while(tmp) tmp = tmp->next; //wir sind am ende angelangt, newPerson ist das neue //letzte element tmp = newPerson; tmp->next = 0; //damit o. schleife auch funktioniert } //die funktionalitaet sollte jetzt klar sein void Person::getDaten(){ Person* tmp = this; while(tmp) { cout<<name<<endl; tmp = tmp-> next; } }
Hoffe ich hab jetzt keinen Fehler gemacht und dir ist das Prinzip klar geworden.
mfg
v R
-
Wie rufe ich diese Liste denn in MAIN auf und wo gebe ich den Namen ein ?
Das Speichern/Lesen ist ja noch nicht integriert, mal abgesehen von den Funktionen. Hast du da noch ne Idee ?
-
Hä? Sicher das amn so eine Liste implementiert? Also vom Prinzip her schon, aber ich kann ja nicht mal nen name speichern? Oder bin ich blöd?
@Annika:
Speichern ist von einzelnen Personen ist implementiert, und das ist nur ein Bsp. Wenn du sowas benutzen willst, kannste std::list benutzen. Wenn dus selber implementieren willst (zu übungszwecken) musst du das natürlich noch erweitern.
Mir sagt übrigens die ganze Listenklasse nicht zu und mindestens einen Destruktor würde ich noch vorschlagen!
-
ness schrieb:
Hä? Sicher das amn so eine Liste implementiert? Also vom Prinzip her schon, aber ich kann ja nicht mal nen name speichern? Oder bin ich blöd?
Ups, hab en Fehler drin. Bei setDaten tmp = next setzen. Und ja, en DTor sollte
noch rein, um die Liste wieder zu loeschen.Bei mir wird die Liste ordnungsgemaess angelegt.
[edit]
Die Schleife in setData muss noch raus
[/edit]mfg
v R
-
Und wie soll man den namen von ner Person ändern? Ein Iterator wäre nicht schlecht, und rein oop-technisch würde ich aus Person nen struct machen und ein template einfach_verkettete_liste einführen...
-
@virtuell Realisticer
Kannst du bitte nochmal schreiben wie die MAIN Funktion von Deinem geposteten Code aussieht ?
Vielen Dank.
-
otze schrieb:
[...]
richtig wärs wohl so:
template<class charT,class traits> friend std::basic_ostream<charT,traits> &operator<<(std::basic_ostream<charT,traits> &out,Personen const &p)
sorry, king, darauf musste ich noch hinweisen :), kannst dich ja bald mal revanchieren
ja, natürlich! Wie konnte ich nur!
-
ness schrieb:
Und wie soll man den namen von ner Person ändern? Ein Iterator wäre nicht schlecht, und rein oop-technisch würde ich aus Person nen struct machen und ein template einfach_verkettete_liste einführen...
Naja, i.d.R. aendert sich der Name einer Person nicht im laufe seines Lebens. Ein
Iterator koennte man in der Tat noch machen. Und ob du ein struct oder ein class
nimmst, ist "oop-technisch" egal. Bis auf die Standardsichtbarkeit verhalten sich
beide Konstrukte gleich. Der Einfachheit halber wuerde ich persoenlich ein
std::list fuer sowas nehmen, aber wenn es nur zur Uebung ist.@virtuell Realisticer
Kannst du bitte nochmal schreiben wie die MAIN Funktion von Deinem geposteten Code aussieht ?
Vielen Dank.
Du solltest etwas mehr eigeninitiative zeigen. Auf die main-Funktion sollte
man jetzt sehr leicht kommen. Sie koennte z. B. so aussehen:int main() { Person person; Person tmp; char end; while(end != 'n') { cout<<"Personenname: "; cin >> tmp; person.setDaten(tmp); cout<<"Noch mehr Personen? "; cin >> end; } return 0; }
[edit]
Hmmm...offentsichtlich bin ich zu bloed geworden, um eine Liste zu
implementieren :(. Die Liste funktioniert nicht so, wie sie soll, aber ich
kann mich im Moment nicht darum kuemmern, muss ja auch was arbeiten ;).Heut Abend, wenn ich die Zeit bekomme, werde ich mir das nochmal anschauen.
Soll trotzdem niemanden daran hindern, hier was zu posten.
[/edit]mfg
v R