Struct mit AnsiString speichern



  • Der Struct selber kann ich gut beschreiben, dass ist nicht das Problem, der muss eh global sein, weil ich das noch in anderen Units weiter verwende. Aber wenn ich ihn speichere, nimmt es irgendwelche Werte die nicht im Struct sind sonder sonst irgendwelche, wie eben der Name der Combobox oder die Variable für den Pfad die ich noch angelegt habe.



  • asdasdasdasd schrieb:

    Das ist kein C++.

    Wie das ist kein C++? Das hatten wir so in der Schule, nur nicht mit AnsiString sondern mit Char. Und Kompilieren kann er es ja, also wird es nicht so falsch sein.

    Sorry für den Doppel Post.



  • char / char* / ... ist ja auch Standard C++

    nur eben AnsiString ist kein Standard C++
    Standard wäre z.bsp. std::string

    AnsiString ist eine Erweiterung des BCBs...

    bb



  • unskilled schrieb:

    char / char* / ... ist ja auch Standard C++

    nur eben AnsiString ist kein Standard C++
    Standard wäre z.bsp. std::string

    AnsiString ist eine Erweiterung des BCBs...

    bb

    Schau lieber nochmal ganz genau hin: FILE , fopen , fwrite , etc.

    Naaaa? Eindeutig C!



  • asdasdasdasd schrieb:

    Schau lieber nochmal ganz genau hin: FILE , fopen , fwrite , etc.

    Naaaa? Eindeutig C!

    Hmm.. hätt ich machen können - hab iwie gerad erst gesehen, dass der erste Post nicht nur aus dem Code für das struct besteht^^

    also: /signed
    🙂

    bb



  • Das ist weder C noch C++, das ist einfach nur falsch. Dass sowas heutzutage überhaupt kompiliert...
    Wenn ihr es so in der Schule gelernt habt, dann habt ihr vermutlich nicht C++, sondern C90 gelernt (auch wenn dein Code selbst das nicht ist). Wenn das unter C++ lief, dann hat der Unterricht sein Ziel verfehlt.

    Was imho alles auf den ersten Blick falsch ist:

    • implicit int wird von Standard-C++ und C99 nicht unterstützt. Und selbst wenn dein Kompiler das zulässt, verlässt du dich auf undefined behavior, weil du dann eine Ganzzahl zurückgeben musst (der Rückgabetyp ist nicht void, sondern int!).
    • Pay ist kein POD, du kannst also nicht fread() darauf anwenden, weil dieses einfach nur in den rohen Speicher schreibt, bzw. fwrite(), weil diese Funktion einfach nur den rohen Speicher in die Datei schreibt.
    • fclose(0) ist undefined behavior.

    Dein aktuelles Hauptproblem ist der 2. Punkt. Verwende lieber die C++-Streams, dann klappt das auch mit dem Einlesen von Strings.



  • Ohweh. Ich würd den Thread ja gern verschieben - C++ ists nicht. C auch nicht (nichtmal in irgendeiner alten Version mit impliziten Rückgabetypen), weil diese seltsamen BCB-Stringklassen verwendet werden. Ich frag mal nach ob wir ein Extraforum "Gruselkabinett" für solche Fälle aufmachen können 😉

    @Mathiable: In was für einer Schule kriegt man sowas beigebracht? Sicher dass es so war, ganz ohne Rückgabeparameter, und dass es C++ sein sollte? Oder hast du da mehrere Sprachen durcheinanderbegracht? Falls es euch tatsächlich so beigebracht worden ist - kann das sein dass der Info-Lehrer von eurem Archäologielehrer irgendwo ausgegraben und wiederbelebt wurde - mitsamt einem Compiler der sowas schluckt? Nichts für ungut 😉



  • pumuckl schrieb:

    Ohweh. Ich würd den Thread ja gern verschieben - C++ ists nicht. C auch nicht (nichtmal in irgendeiner alten Version mit impliziten Rückgabetypen), weil diese seltsamen BCB-Stringklassen verwendet werden. Ich frag mal nach ob wir ein Extraforum "Gruselkabinett" für solche Fälle aufmachen können 😉

    @Mathiable: In was für einer Schule kriegt man sowas beigebracht? Sicher dass es so war, ganz ohne Rückgabeparameter, und dass es C++ sein sollte? Oder hast du da mehrere Sprachen durcheinanderbegracht? Falls es euch tatsächlich so beigebracht worden ist - kann das sein dass der Info-Lehrer von eurem Archäologielehrer irgendwo ausgegraben und wiederbelebt wurde - mitsamt einem Compiler der sowas schluckt? Nichts für ungut 😉

    Das mit den AnsiStrings hab ich mir aus dem Betrieb abgeschaut, das hatten wir so nicht in der Schule. Und ich bin Elektroniker, daher arbeite ich meist auch nur mit Uhralt Programmiersprachen. Ich lernte sogar noch mit Assembler. 😉

    Der Lehrer benützt eben immer noch denselben Stoff wie er ihn vor 10 Jahren geschrieben hat und hat keine Ahnung von C# oder anderem weil das nicht berufsspezifisch sei. 🙄

    zurück zum Thema:
    Ich habe nun einen Crashkurs mit fstream gemacht, speichern und laden kann er schon, nur macht er dieselben Fehler. Soll ich meine Theorie mit den AnsiStrings nochmals überlegen oder kennt jemand eine Lösung?

    Mit fstream mach ich es ganz einfach:

    file.open("C:/Data.bin",ios::in | ios::binary);
    
    file.read ((char*)&BenDat, sizeof(Pay));
    

    und das selbe dann noch für den Schreib zyklus.



  • Mathiable schrieb:

    Der Lehrer benützt eben immer noch denselben Stoff wie er ihn vor 10 Jahren geschrieben hat und hat keine Ahnung von C# oder anderem weil das nicht berufsspezifisch sei. 🙄

    Ähm - dir ist schon klar dass C, C++ und C# drei verschiedene Sprachen sind und vor allem C# mit den anderen beiden nichts zu tun hat?
    Dass du die AnsiStrings ausm Betrieb kennst sagt schon einiges, dann ergibt sich nämlich folgender Eindruck: Der Lehrer bringt euch C bei, nicht C++. Denn ohne die AnsiStrings ist das was du oben gepostet hast ein zwar reichlich veraltetes und verstaubtes, aber vor Dekaden mal gültiges C. Du hast dann die Borland-C++-AnsiStrings drunter gemischt und raus kommt eine ziemlich unsinnige Codesuppe die eigentlich auf keinem halbwegs ordentlichen Compiler kompilieren sollte. Dass du es scheinbar trotzdem fertig gebracht hast ist ebenso verwunderlich wie erschreckend.

    Du musst dich entscheiden ob du C oder C++ programmieren willst. In beiden Fällen empfehle ich die Lektüre eines guten Buches und/oder einiger Tutorials. Und gerade wenn du in der Schule Steinzeit-C und in der Firma Borland-C++ machst solltest du lernen folgendes auseinanderzuhalten:

    • Steinzeit-C (was dein Lehrer macht)
    • Standard-C
    • Standard-C++
    • Borland-C++ (was einige Klassenbibliotheken hat die es im Standard nicht gibt und scheinbar seeeeehr frei im Umgang mit der Sprache ist).


  • Ähm - dir ist schon klar dass C, C++ und C# drei verschiedene Sprachen sind und vor allem C# mit den anderen beiden nichts zu tun hat?

    Ist mir schon klar, wollte damit nur sagen dass der Lehrer immer noch auf den Programmiersprachen der 80er hängen geblieben ist. :p

    Dass du die AnsiStrings ausm Betrieb kennst sagt schon einiges, dann ergibt sich nämlich folgender Eindruck: Der Lehrer bringt euch C bei, nicht C++. Denn ohne die AnsiStrings ist das was du oben gepostet hast ein zwar reichlich veraltetes und verstaubtes, aber vor Dekaden mal gültiges C.

    Kannst du mir mal sagen was daran so altmodisch ist? Damit ich daran arbeiten kann und schlussendlich etwas Seriöseres raus bringen kann. Wenn der Lade/Speicher Zyklus mal läuft ist gut, den Rest krig ich dann schon irrgendwie zusammen...



  • Mathiable schrieb:

    Ähm - dir ist schon klar dass C, C++ und C# drei verschiedene Sprachen sind und vor allem C# mit den anderen beiden nichts zu tun hat?

    Ist mir schon klar, wollte damit nur sagen dass der Lehrer immer noch auf den Programmiersprachen der 80er hängen geblieben ist. :p

    Dir ist hoffentlich bewusst das C noch verbreiteter als C++ oder C# ist? Und dir ist hoffentlich auch bewusst das auch C++ schon aus den 80iger Jahren stammt (glaube um 1977). Wenn man den tiobe-Index nimmt: Java auf Platz 1, C auf 2, C++ auf 3 (C# auf Platz 7).

    cu André



  • @Mathiable
    Während sich die anderen wegen C, C++, oder C# Grundsätzen fusselig labern, gebe ich dir schonmal ein paar Tips:

    fwrite(&BenDat,sizeof(BenDat),1,f);
    

    Prinzipiell denkbar, üblicherweise schreibt man:

    fwrite(BenDat,sizeof(struct  Pay), sizoef(BenDat),f);
    

    Wie sieht dein AnsiString Typ aus? char* konstanter Länger oder watt?
    Wenn nicht, musst du die Strings einzeln speichern.
    Die Tatsache, das in deinen Variablen Werte stehen, die dort nicht hingehören, schließen darauf, das Arraygrenzen überschrieben werden.



  • Mathiable schrieb:

    Kannst du mir mal sagen was daran so altmodisch ist?

    Wie schon oben gesagt wurde sind Funktionen mit implizitem Rückgabetyp int nicht mehr erlaubt, IIRC seit dem C99-Standard. Im C++-Standard von 1998 ists das selbe.
    Funktionen müssen einen Rückgabetyp (z.B. void, int oder etwas anderes) explizit angegeben haben.

    Wenn du mir mitteilst, ob du in C oder C++ schreiben möchtest, kann ich den Thread entweder ins richtige C-Forum verschieben oder wir können dir hier mit ordentlichem C++ weiterhelfen 🙂



  • lattemann schrieb:

    fwrite(BenDat,sizeof(struct  Pay), sizoef(BenDat),f);
    

    Wechstaben verbuchselt :p
    Muss heißen sizeof, is klar, wa.



  • lattemann schrieb:

    Während sich die anderen wegen C, C++, oder C# Grundsätzen fusselig labern, gebe ich dir schonmal ein paar Tips:

    Die wenn du die anderen Beiträge gelesen hättest nicht funktionieren können.

    lattemann schrieb:

    Wie sieht dein AnsiString Typ aus? char* konstanter Länger oder watt?

    AnsiString ist wie gesagt ein Datentyp des BCB (Genauer: Eine Klasse der VCL-Bibliothek).



  • asc schrieb:

    ... wenn du die anderen Beiträge gelesen hättest nicht funktionieren können.

    die anderen? das gefeilsche um den rückgabetypen? nee, ne.
    bisher habe ich diesbezüglich nur einen brauchbaren, den von Old MacDonald gesehen.

    @Mathiable:
    Hol dir für jeden Structmember den Zeiger auf die Daten, ermittle die Anzahl der Bytes, hau das in die Datei rein und gut ist.
    Beim AnsiString bin ich mir gerade nicht so sicher, ob man den Zeiger so bekommt:
    AnsiString Name;
    char* p = Name.c_str();
    Gruß,
    jepp.



  • die anderen? das gefeilsche um den rückgabetypen? nee, ne.
    bisher habe ich diesbezüglich nur einen brauchbaren, den von Old MacDonald gesehen.

    Aber dein Vorschlag wäre sogar noch eine Verschlimmbesserung gewesen - der hätte nämlich glatt einen Bufferoverrun noch zusätzlich erzeugt. 🙄

    Hol dir für jeden Structmember den Zeiger auf die Daten, ermittle die Anzahl der Bytes, hau das in die Datei rein und gut ist.
    Beim AnsiString bin ich mir gerade nicht so sicher, ob man den Zeiger so bekommt:
    AnsiString Name;
    char* p = Name.c_str();

    Viel Spaß. Denn wie du die Zeichenketten variabler Länge wieder korrekt auslesen willst, hast du noch nicht gesagt; zumindest nicht eindeutig genug, dass es Mathiable versteht.



  • Old McDonald schrieb:

    Aber dein Vorschlag wäre sogar noch eine Verschlimmbesserung gewesen - der hätte nämlich glatt einen Bufferoverrun noch zusätzlich erzeugt. 🙄

    ich schrieb, dass man u.u. einzeln speichern muss und habe nach dem datentypen gefragt 🙄

    Old McDonald schrieb:

    Viel Spaß. Denn wie du die Zeichenketten variabler Länge wieder korrekt auslesen willst, hast du noch nicht gesagt; zumindest nicht eindeutig genug, dass es Mathiable versteht.

    wie willst du denn beurteilen, was er versteht und was nicht 🙄



  • Das hier:

    fwrite(BenDat,sizeof(struct  Pay), sizeof(BenDat),f);
    

    Erzeugt einen Pufferüberlauf. Wenn Pay ein POD wäre, müsste es so lauten:

    fwrite(BenDat,sizeof(BenDat[0]), sizeof(BenDat)/sizeof(BenDat[0]),f);
    

    Aber lassen wir das - es ändert eh nichts daran, dass es falsch ist 🙂

    wie willst du denn beurteilen, was er versteht und was nicht 🙄

    Das kann ich nicht - aber ich kann es vermuten. Je nachdem, wie man deine Beschreibung liest, wie die Struktur in die Datei geschrieben werden soll, kommt entweder totaler Murks raus oder etwas, dass man wieder auslesen kann. Warum? Weil du nicht eindeutig dazugeschrieben hast, dass man auch noch die Länge der Zeichenkette mitspeichern muss oder die Zeichenkette mit '\0' terminieren muss. Die Beschreibung ist so einfach zu schwammig oder unvollständig.
    Naja, jetzt abwarten, bis sich Mathiable wieder meldet 🙂



  • Old McDonald schrieb:

    Das hier:

    fwrite(BenDat,sizeof(struct  Pay), sizeof(BenDat),f);
    

    Erzeugt einen Pufferüberlauf.

    Auch du Scheiße. Da haddu recht, was bin ich doch für eine Schlampe :D, da hab ich gepennt.

    Den Teiler habe ich ganz vergessen!
    Korrekt wäre in der Tat gewesen:

    fwrite ( BenDat, sizeof( struct Pay ), sizeof( BenDat )/sizeof(struct Pay), fp);
    

    für die sogenannten PODs. -> hier kein rolleyes <- 🙂


Anmelden zum Antworten