struct speichern/laden ->Fehler!
-
Hi! Ich hab ein Problem, speichern scheint ja zu funktioneieren, allerdings das Laden macht probleme, sitze schon ca. 2 Tage an dem Problem. Wisst ihr wo der Fehler liegt?
Hier `nen bisschen Code:
Die Struct:
struct Info { AnsiString spiel; AnsiString version; AnsiString typ; AnsiString autor; int groesse; AnsiString beschreibung; AnsiString erweiterung; };Methoden:
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)); //----Stream-schließen---- ofl.close(); //----Alles-OK---- return 1; } 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); //----Stream-schließen---- ifl.close(); //----Alles-OK---- return 1; }thx

-
Überleg dir mal was AnsiString ist und was passiert wenn du AnsiString einfach direkt in die Datei schreibst (das nennt sich eine "flache Kopie").
-
und wie änder ich das am besten?
ist z.B. wenn ich es in ein char array ändere, beim speichern eine tiefe kopie?
-
Ich vermute mal, dass die Bibliothek einen op<< für AnsiString mitliefert, in dem Fall kannst du einfach die Strings mit of1 << my_ansistring in die Datei schreiben.
Wahrscheinlich bietet die Klasse AnsiString auch eine Methode um auf das interne char-Array zuzugreifen, dann kannst du es auch sehr einfach mit write in die Datei schreiben (aber dann musst du auch die Größe mit abspeichern, deswegen wäre ein Textformat einfacher).
-
Hallo
AnsiString gehört zur VCL des Builders.
Und ja die bietet auch die << und >> Ops für Ansistring in std::stream an. Wie du die aktivieren kannst findest du in der Builder-Hilfe zu AnsiString.bis bald
akari
-
Dieser Thread wurde von Moderator/in HumeSikkins aus dem Forum C++ in das Forum VCL/CLX (Borland C++ Builder) verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
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.