STL Container vector abspeichern nach Anleitung hier aus dem FAQ Bereich
-
Hallo,
zuerst:
- Ich bin noch Anfänger in Sachen C++, trotz fortgeschrittenem Informatik Studium, wir haben eigentlich nur mit Java gearbeitet
- Ich nutze Microsoft Visual Studio .NET 2003, kriegen wir über die Uni über MSDN umsonst.
- Ich möchte, bevor ich überhaupt richtig einsteige in .NET oder Qt oder was auch immer erstmal ein Programm mit Standard C++ Code schreiben um Grundlagen zu sammeln.Ich programmiere zur Übung ein kleines, konsolenbasiertes Adressbuch. Ich möchte gerne meinen Container Adressbuch, der nichts anderes als ein Vector vom Typ Datensatz ist in eine Datei speichern. Ich hab hier im FAQ Bereich unter diesem Link
http://www.c-plusplus.net/forum/viewtopic-var-t-is-39470.html
(und zwar im letzten Beitrag dieses Threads) folgende Anleitung von HumeSikkins gefunden:
copy(myVec.begin(),myVec.end(),ostream_iterator<int>(datei," "));Ich wollte das jetzt übernehmen für meine Problemstellung, nur dass ich statt
ostream_iterator<int>jetzt
ostream_iterator<datensatz>verwende. Wenn ich meinen SourceCode nun kompilieren möchte, öffnet sich in Visual Studio zu meinen Klassendateien noch die Datei
C:\Programme\Microsoft Visual Studio .NET 2003\Vc7\include\iterator
mit der Meldung, dass in dieser Datei in Zeile 257 der Fehler
error C2679: Binärer Operator '<<': Es konnte kein Operator gefunden werden, der einen rechtsseitigen Operator vom Typ 'const datensatz' akzeptiert (oder keine geeignete Konvertierung möglich ist)Kann ich etwa nur einfache Datentypen verwenden ? Gibts es eine Möglichkeit, diese Einschränkung zu umgehen ?
Gruß
matrix1977
-
Deine Datensatz-Klasse muss den op<< für Streams überladen, siehe zB hier ganz unten: http://cache.sidewindershome.net/Operators.h
Wenn du etwas mehr Hilfe als die Deklaration benötigst, gib Bescheid

MfG SideWinder
-
matrix1977 schrieb:
Hallo,
zuerst:
- Ich bin noch Anfänger in Sachen C++, trotz fortgeschrittenem Informatik Studium, wir haben eigentlich nur mit Java gearbeitet
- Ich nutze Microsoft Visual Studio .NET 2003, kriegen wir über die Uni über MSDN umsonst.
- Ich möchte, bevor ich überhaupt richtig einsteige in .NET oder Qt oder was auch immer erstmal ein Programm mit Standard C++ Code schreiben um Grundlagen zu sammeln.Ich programmiere zur Übung ein kleines, konsolenbasiertes Adressbuch. Ich möchte gerne meinen Container Adressbuch, der nichts anderes als ein Vector vom Typ Datensatz ist in eine Datei speichern. Ich hab hier im FAQ Bereich unter diesem Link
http://www.c-plusplus.net/forum/viewtopic-var-t-is-39470.html
(und zwar im letzten Beitrag dieses Threads) folgende Anleitung von HumeSikkins gefunden:
copy(myVec.begin(),myVec.end(),ostream_iterator<int>(datei," "));Ich wollte das jetzt übernehmen für meine Problemstellung, nur dass ich statt
ostream_iterator<int>jetzt
ostream_iterator<datensatz>verwende. Wenn ich meinen SourceCode nun kompilieren möchte, öffnet sich in Visual Studio zu meinen Klassendateien noch die Datei
C:\Programme\Microsoft Visual Studio .NET 2003\Vc7\include\iterator
mit der Meldung, dass in dieser Datei in Zeile 257 der Fehler
error C2679: Binärer Operator '<<': Es konnte kein Operator gefunden werden, der einen rechtsseitigen Operator vom Typ 'const datensatz' akzeptiert (oder keine geeignete Konvertierung möglich ist)Kann ich etwa nur einfache Datentypen verwenden ? Gibts es eine Möglichkeit, diese Einschränkung zu umgehen ?
Gruß
matrix1977Du musst für deinen speziellen Datentyp den operator << überschreiben
um deine Daten in die Datei zu Schreiben. Und logischerweise auch den
operator >> um die Daten wieder aus der Datei zu Lesen.
-
Danke für Eure schnelle Hilfe,
ich bin etwas verwirrt, spricht etwas dagegen, wenn man einfach eine Methode vom Vector-Objekt Adressbuch schreibt, namens AdressbuchSpeichern() oder ähnlich, die in einer Schleife den Vector abläuft und an jedem Index die get-Methoden von Datensatz aufruft und die Rückgabewerte vom Typ string einfach in die Datei schreibt ?
Dann bräuchte ich nicht den Operator operator<< und operator>> überladen, wobei mir auch nicht wirklich klar ist, wo und wie ich das machen müsste.
Oder ist meine Schleife zwar funktionell aber unschön ?
Gruß
matrix1977
-
matrix1977 schrieb:
Danke für Eure schnelle Hilfe,
ich bin etwas verwirrt, spricht etwas dagegen, wenn man einfach eine Methode vom Vector-Objekt Adressbuch schreibt, namens AdressbuchSpeichern() oder ähnlich, die in einer Schleife den Vector abläuft und an jedem Index die get-Methoden von Datensatz aufruft und die Rückgabewerte vom Typ string einfach in die Datei schreibt ?
Kannst du machen.
Dann bräuchte ich nicht den Operator operator<< und operator>> überladen, wobei mir auch nicht wirklich klar ist, wo und wie ich das machen müsste.
Was meinst du genau? Jeden Teil der Datenstruktur einzeln zu schreiben?
Wenn ja, dann folgendes Beispiel:
Bei folgender Datenstruktur:class foo { string s; public: foo() {} foo(const string& s) : s(s) {} const string& get_string() const { return s; } };Wenn du jetzt z.B. folgenden vektor aus foo-Elementen hast:
vector<foo> v;dessen Elemente du alle in den ofstream of schreiben möchtest, kannst du dir folgende Funktion basteln:
void write_foo(vector<foo>::const_iterator beg, vector<foo>::const_iterator end, ofstream& of) { for( ; beg != end; ++beg) of << beg->get_string(); }Wenn du etwas anderes meinst, dann beschreibe dein Problem doch bitte etwas genauer :).
Oder ist meine Schleife zwar funktionell aber unschön ?
Ich finde eine Lösung mittels des op<< deutlich schöner.
Gruß Caipi
-
Das wird in der Tat unschön, meine Klasse Datensatz hat sechs get-Methoden:
getVorname()
getNachname()
getStrasse()
getPostleitzahl()
getOrt()
getTelefon()Alle haben einen Rückgabewert vom Typ string. D.h. ich müsste in jedem Schleifendurchlauf 6 get-Methoden aufrufen. Ich sehe ein, dass da die Variante mit dem Überladen der op>> und op<< Operatoren schöner ist. Kann mir da vielleicht nochmal jemand etwas zu sagen, wie ich das implementiere ?
Gruß
matrix1977
-
Weiß zwar nicht, wie deine Klasse aussieht, aber ich würde, um die Wiederverwendbarkeit des Codes zu erhöhen, glaube ich sowas in der Art machen:
class entry { private: string surename; string name; // ... public: // Ctors, Copy-Ctors, Dtors ... // die gettter/setter ... virtual ostream& write(ostream& os) const; // Eine Methode, die einen Eintrag schreibt. }; // implementationen der Ctoren, etc. virtual ostream& entry::write(ostream& os) const { os << get_surename() << '\n'; // Alle Werte für den einen Eintrag schreiben. } ostream& operator<<(ostream& os, const entry& e) { return e.write(os); }Obige Vorgehensweise hat, wie bereits angedeutet, Vorteile wenn du später von entry ableitest, und diese abgeleiteten Klassen eine andere Art haben ihre Methoden zu schreiben... (Dann musst du nämlich nur noch die Methode write() in deiner neuen Klasse zu redefinieren und nicht auch noch den op<<).
Jetzt noch die Funktion mit folgendem Prototyp, der du start und end-Iterator übergibst, um das Array in den ostream o zu schreiben:
void write_entries(vector<entry>::const_iterator beg, vector<entry>::const_iterator end, ostream& o);Die Implementation derer überlasse ich dir als Übung :).
/edit: Falls du beim Operator überladen absolutes "Neuland" betritst, dann empfehle ich [1] [2].
Gruß Caipi
-
Vielen Dank für die schnelle Hilfe, ich sehe, ich muss noch viel lernen.
Ich habe es jetzt erstmal auf unschöne Art und Weise gelöst:void meinVector::schreibeAdressbuch() { ... fstream datei; ... for (int i = 0; i < (int)meinVector.size(); i++) { datei.write(meinVector[i].getVorname().append("\n").c_str(), meinVector[i].getVorname().size()+1); datei.write(meinVector[i].getNachname().append("\n").c_str(), meinVector[i].getNachname().size()+1); datei.write(meinVector[i].getStrasse().append("\n").c_str(), meinVector[i].getStrasse().size()+1); datei.write(meinVector[i].getPostleitzahl().append("\n").c_str(), meinVector[i].getPostleitzahl().size()+1); datei.write(meinVector[i].getOrt().append("\n").c_str(), meinVector[i].getOrt().size()+1); datei.write(meinVector[i].getTelefon().append("\n").c_str(), meinVector[i].getTelefon().size()+1); } ... }Das funktioniert immerhin, bis auf Sonderzeichen, diese werden nur fehlerhaft geschrieben. Für die Variante mit dem Überladen der Operatoren muss ich wohl erstmal noch einiges lernen, mir ist da noch nicht alles ganz klar, aber danke für die beiden Links. Bei Methoden, die mit virtual deklariert sind, bin ich auch noch nicht angelangt. Ich muss erst noch so einiges lesen ... Trotzdem vielen Dank schonmal!
Gruß
matrix1977