struct speichern/laden ->Fehler!
-
welchen typ nehme ich am besten um die struct direkt zu speichern (auch mit den strings)?
Das mit "<<" und so, erscheint mir imo etwas aufwändig...

-
Hallo
Dragonfire schrieb:
welchen typ nehme ich am besten um die struct direkt zu speichern (auch mit den strings)?
Theoretisch am einfachsten wäre es mit char[], also einem Array mit fester Dimension. Das hat natürlich auch nachteile :
- Die Zeichenketten haben eine Maximal-Größe
- Das Zusammenspiel mit AnsiString (zum Beispiel bei Kopieren in und aus VCL-Controls) ist umständlich
Sowohl char* als auch AnsiString können nicht über die von dir benutzte Kopiermethode gespeichert werden.Das mit "<<" und so, erscheint mir imo etwas aufwändig...

Was ist daran aufwendig? Du kannst sogar für dein struct die << und >> Ops definieren, die nichts weiter machen als für die einzelnen Member die Aktion auszuführen.
Wenn du nur wegen der Bequemlichkeit beim Laden/Speichern auf PODs fester Größe zurückgreift sparst du an der falschen Stelle, dafür wirst du dann in der Verarbeitung selber umständlich arbeiten müßen. Also benutzt lieber gleich durchgehend AnsiString.bis bald
akari
-
Hast du vllt. ein Beispiel wie das aussehen könnte, oder so ähnlich?
Was das Überladen von "<<" oder ">>" angeht bin ich noch nicht so fit...

-
Hallo
#include <ostream> // Wichtig : vor vcl.h! #include <vcl.h> struct Info { AnsiString spiel; AnsiString version; AnsiString typ; AnsiString autor; int groesse; AnsiString beschreibung; AnsiString erweiterung; }; std::ostream& operator<<(std::ostream& stream, const Info& info) { stream << info.spiel << std::endl; // Zeilenumbruch als Trennzeichen stream << info.version << std::endl; ... stream << info.erweiterung << std::endl; }bis bald
akari
-
Hallo,
Z.Bsp. so
struct Info { AnsiString spiel; AnsiString version; AnsiString typ; AnsiString autor; int groesse; AnsiString beschreibung; AnsiString erweiterung; }; ostream& operator<<(ostream& out, const Info& value) { out << version << " "; out << typ << " "; out << autor << " "; out << groesse << " "; out << beschreibung << " "; out << erweiterung << std:.endl; return out; } //--------------------------------------------------------------------------- istream& operator>>(istream& in, Info& value) { in >> version; in >> typ; in >> autor; in >> groesse; in >> beschreibung; in >> erweiterung; return in; } //---------------------------------------------------------------------------[edit]War wohl etwas spät.
[edit]
-
Gut...also hab ich jetzt:
std::ostream& operator<<(std::ostream& stream, const Info& info) { stream << info.spiel.c_str() << std::endl; // Zeilenumbruch als Trennzeichen stream << info.version.c_str() << std::endl; stream << info.typ.c_str() << std::endl; stream << info.autor.c_str() << std::endl; stream << info.groesse << std::endl; stream << info.beschreibung.c_str() << std::endl; stream << info.erweiterung.c_str() << std::endl; }und zum lesen:
int Unit::loadInfoFromFile(char *datei) { //----Stream-initialisieren---- ifstream ifl(datei, ios::in|ios::binary); //----Fehler?---- if(!ifl) { return 0; } //----Länge-bestimmen---- unsigned int ende; ifl.seekg(0, ios::end); ende = ifl.tellg(); ifl.seekg(0, ios::beg); //----Daten-einlesen---- //info = new Info[ende/sizeof(Info)]; //ifl.read((char*)info, ende); ifl >> &info; //----Stream-schließen---- ifl.close(); //----Alles-OK---- return 1; }und die methode zum schreiben:
int Unit::saveInfoToFile(char *datei) { //----Stream-initialisieren---- ofstream ofl(datei, ios::out|ios::binary); //----Fehler?---- if(!ofl) { return 0; } //----Schreiben---- //ofl.write((char*)info, sizeof(*info)); ofl << &info; //----Stream-schließen---- ofl.close(); //----Alles-OK---- return 1; }ist das so richtig, nebenbei (hab ich vllt. vergessen
), info ist ein Array von Info...Bekomm nämlich noch ne Fehlermeldung wenn ich auf das geladene struct zugreifen will.(ohne den operator >> zum einlesen)
Mit >> zum einlesen bekomm ich den Fehler beim compilieren:
[C++ Fehler] Unit.cpp(222): E2015 Mehrdeutigkeit zwischen '_STL::basic_istream<char,_STL::char_traits<char> >::operator >>(bool &)' und '_STL::basic_istream<char,_STL::char_traits<char> >::operator >>(void * &)'
-
Muss ich das struct vllt. serialisieren?
Das musste zumindest in Java gemacht werden...
Nur wie wird das hier realisiert?
-
Du versuchst hier
ofl << &info;ja auch eine Pointer zu schreiben (beim lesen genauso). Dein Operator ist aber für ein Objekt (Referenz darauf).
Das hier sollte dann gehen.ofl << info;PS.
Das was du da machst nennt man serialisieren.
-
Aha!

Danke!
Nur an der stelle
ifl >> infoliefert der compiler [C++ Fehler] Unit.cpp(222): E2015 Mehrdeutigkeit zwischen '_STL::basic_istream<char,_STL::char_traits<char> >::operator >>(bool &)' und '_STL::basic_istream<char,_STL::char_traits<char> >::operator >>(void * &)'
-
Kann es sein, dass dein operator<< an dieser Stelle nicht bekannt ist? Sind die richtigen Header inkludiert? Kann es sein, dass info da ein Pointer ist?
Du solltest übrigens das ios::binary bei deinen Streams weglassen. So wie du den operator geschrieben hast, arbeitet er im Textmodus.
-
Also ich habe: #include "fstream.h" inkludiert.
Mir wäre lieber wenn der operator auch binär schreiben würde.
In meinem Prog. ist info ein Pointer, da es ein Array ist. (von struct Info)
-
Wenn es ein Pointer ist, mußt du dereferenzieren. Wenn es aber ein Array ist, kannst du ja auch mit [] auf das zu schreibende Element zugreifen.
Vielleicht solltest du uns den korrekten Code zeigen wo der Fehler auftritt.So wie dein operator<< aufgebaut ist schreibt er nicht binär, sondern im Textmodus. Das ist hier auch notwendig, um das Ende der Strings ordentlich zu kennzeichnen.
Wenn du binär schreiben willst solltest du deiner struct die memberfunktionen read/write spendiern, die das dann übernehmen. Bei Streams sind die nämlich für binäre daten zuständig. Wenn du Strings binär schreiben willst, solltest du immer vorher die Länge mit abspeicher, damit du wieder ordentlich einlesen kannst.fstream.h ist sowieso falsch. Wenn schon, dann #include <fstream>.
das meinte ich hier aber gar nicht. Ich meinte den header, wo deine Operatoren<< und >> deklariert worden sind.
-
Also ich hatte mir vorgestellt es wie in java zu machen.
Aber nun gut,
Wenn du binär schreiben willst solltest du deiner struct die memberfunktionen read/write spendiern, die das dann übernehmen. Bei Streams sind die nämlich für binäre daten zuständig.
Wie sähen die Memberfunktionen aus?
fstream.h ist sowieso falsch. Wenn schon, dann #include <fstream>
Was ist der unterschied?
Ich meinte den header, wo deine Operatoren<< und >> deklariert worden sind.
Imo sind die mit in der cpp Datei, "Unit.cpp".
Die Stelle des Fehlers ist:(Zeile 18)
int Unit::loadInfoFromFile(char *datei) { //----Stream-initialisieren---- ifstream ifl(datei, ios::in|ios::binary); //----Fehler?---- if(!ifl) { return 0; } //----Länge-bestimmen---- unsigned int ende; ifl.seekg(0, ios::end); ende = ifl.tellg(); ifl.seekg(0, ios::beg); //----Daten-einlesen---- //info = new Info[ende/sizeof(Info)]; //ifl.read((char*)info, ende); ifl >> info; //----Stream-schließen---- ifl.close(); //----Alles-OK---- return 1; }
-
Hallo
Wie sähen die Memberfunktionen aus?
Da must du dir schon selber einen Kopf machen. Da du ja mit den AnsiStrings keine reine PODs mehr hast gibt es kein einfaches binäres Format mehr.
Was ist der unterschied?
Braunsteins Verbesserung zeigt den aktuellen C++ Standard
Imo sind die mit in der cpp Datei, "Unit.cpp".
Vermutlich aber erst nachdem Aufruf in loadInfoFromFile?
Du must die Op-Deklaration (und nur die Deklaration, nicht die Implementatio) auch in die Unit.h schreiben.bis bald
akari
-
Dragonfire schrieb:
Wie sähen die Memberfunktionen aus?
so etwa
ostream& Info::write(ostream& out) const { int strsize = spiel.Length(); out.write(reinterpret_cast<const char*>(&strsize), sizeof(strsize)); out.write(spiel().c_str(), strsize+1); // usw. } istream& Info::read(istream& in) { int strsize; in.read(reinterpret_cast<char*>(&strsize), sizeof(strsize)); char* tstr = new char[strsize+1]; in.read(tstr, strsize+1); delete[] tstr; // usw.
-
Da must du dir schon selber einen Kopf machen. Da du ja mit den AnsiStrings keine reine PODs mehr hast gibt es kein einfaches binäres Format mehr.
Die AnsiString müssen nicht sein, man kann ja auch char[] verwenden, nötigenfalls mit begrenzung, z.B. char[255].
Braunsteins Verbesserung zeigt den aktuellen C++ Standard
Aha

Du must die Op-Deklaration (und nur die Deklaration, nicht die Implementatio) auch in die Unit.h schreiben.
Hab ich gemacht (ich dummi^^).
Nun bekomm ich folgende Meldung:[C++ Fehler] CraGine.h(42): E2080 'Unit::operator <<(ostream,const Info)' muß mit einem Parameter deklariert werden
thx nochmal für die Mühen

[EDIT]Oh zuspät...Danke
, ich probiers gleich mal aus.[/EDIT]
-
Die Deklaration sollte so aussehen
std::ostream& operator<<(std::ostream& stream, const Info& info);Natürlich muß Info zu diesem Zeitpunkt bekannt sein. Es ist sowieso am besten die Operation im selben headerfile wie die Klasse zu deklarieren.
-
so bin jetzt soweit:
#unit.cpp#
... ostream& Info::write(ostream& out) const { int strsize = spiel.Length(); out.write(reinterpret_cast<const char*>(&strsize), sizeof(strsize)); out.write(spiel().c_str(), strsize+1); strsize = version.Length(); out.write(reinterpret_cast<const char*>(&strsize), sizeof(strsize)); out.write(version().c_str(), strsize+1); strsize = typ.Length(); out.write(reinterpret_cast<const char*>(&strsize), sizeof(strsize)); out.write(typ().c_str(), strsize+1); strsize = autor.Length(); out.write(reinterpret_cast<const char*>(&strsize), sizeof(strsize)); out.write(autor().c_str(), strsize+1); strsize = beschreibung.Length(); out.write(reinterpret_cast<const char*>(&strsize), sizeof(strsize)); out.write(beschreibung().c_str(), strsize+1); strsize = erweiterung.Length(); out.write(reinterpret_cast<const char*>(&strsize), sizeof(strsize)); out.write(erweiterung().c_str(), strsize+1); strsize = sizeof(groesse); out.write(reinterpret_cast<const char*>(&strsize), sizeof(strsize)); out.write(groesse, strsize+1); }Bei:
istream& Info::read(istream& in) { int strsize; in.read(reinterpret_cast<char*>(&strsize), sizeof(strsize)); char* tstr = new char[strsize+1]; in.read(tstr, strsize+1); delete[] tstr; // usw. }Was bedeutet/was ist hier: tstr?
#unit.h#
... ostream& write(ostream&) const; istream& read(istream&);trotzdem kennt er die Methoden in der cpp datei nicht...
-
tstr ist nur ein temporärer String. Ich hatte da vergessen den eingelesenen Inhalt zu übertragen.
So wäre es richtig.istream& Info::read(istream& in) { int strsize; in.read(reinterpret_cast<char*>(&strsize), sizeof(strsize)); char* tstr = new char[strsize+1]; in.read(tstr, strsize+1); spiel = tstr; delete[] tstr; // usw. }Beim write oben müssen die Klammern nach spiel usw. weg. (auch mein Fehler).
Die Deklarationen von read und write gehören in deine Info-Klasse.
Bitte versuche mal zu verstehen was das bedeutet. Dann mußt du auch nicht mehr so viel fragen und findest deartige Fehler selber.
-
Gut
Mach ich.Nur bin ich im speichern auf Festplatte in C++ nicht so fit^^.
Nur habe ich immer noch die Fehlermeldung:
[C++ Fehler] Unit.cpp(222): E2015 Mehrdeutigkeit zwischen '_STL::basic_istream<char,_STL::char_traits<char> >::operator >>(bool &)' und '_STL::basic_istream<char,_STL::char_traits<char> >::operator >>(void * &)'