Seite 2 von 2

Verfasst: 05.01.2007 15:19
von NicTheQuick
@jear:

Zum Schreiben einer Struktur in einer Datei und zum Auslesen derselben hab
ich schon vor langer Zeit eine halbwegs elegante Procedure gecodet. Ich
habe sie jetzt nochmal an PB V4.02 angepasst und hier findest du sie:

http://www.purebasic.fr/german/viewtopic.php?t=11492

Verfasst: 05.01.2007 21:49
von jear
@NicTheQuick
Danke. Sehr interessanter Weg. Zum Verstehen habe ich mir erlaubt, Deinen Code auseinanderzunehmen und möglichst übersichtlich darzustellen.

Das Verfahren könnte Grundlage für eine entsprechende native Funtion in PB sein. Der Compiler kennt ja sogar den Typ eines jeden Strukturelementes, sodass die zusätzliche Ablage des "Bauplans" der Struktur in einer Stringvariablen überflüssig wäre.

Zwei neue Funktionen also : WriteDataStructure() und ReadDataStructure().

Code: Alles auswählen

; * Methode von NicTheQuick zur Speicherung von Strukturen mit Strings
; * hier : das Speichern der Daten in eine Datei
; - statt des sinnlos gewordenen Pointers auf den eigentlichen Stringinhalt wird
;   dessen Länge als Long in die Datei gespeichert
; - der Inhalt des Strings wird daran angehängt
; - wollte man ein Array oder einen LinkedList auf diese Art speichern, müsste jedes
;   Mitglied des Arrays bzw. der Liste in die Strukturvariable "Var" umgespeichert werden 

Define.s out                        ; Hilfsstring für Messagerequester

Define.s Struc_Strukt = "bwlqsfsd"  ; Der "Bauplan" der Struktur in einem String
Structure Strukt                    ; Daten-Struktur 
  Byte.b 
  word.w 
  Long.l 
  Quad.q 
  String1.s 
  Float.f 
  String2.s 
  Double.d 
EndStructure 
Define.Strukt Var                   ; Variable mit der Struktur anlegen

Structure AllTypes 
  StructureUnion 
    s.s : b.b : c.c : w.w : l.l : f.f : d.d : q.q
  EndStructureUnion 
EndStructure 

Procedure WriteDataStructure(FileId, *Var.AllTypes, *Struc.Character) 
  Protected length.l 
  While *Struc\c 
    Select *Struc\c 
      Case 'b' 
        WriteData(FileId, *Var, SizeOf(Byte)) : *Var + SizeOf(Byte) 
      Case 'c' 
        WriteData(FileId, *Var, SizeOf(Character)) : *Var + SizeOf(Character) 
      Case 'w' 
        WriteData(FileId, *Var, SizeOf(Word)) : *Var + SizeOf(Word) 
      Case 'l' 
        WriteData(FileId, *Var, SizeOf(Long)) : *Var + SizeOf(Long) 
      Case 'f' 
        WriteData(FileId, *Var, SizeOf(Float)) : *Var + SizeOf(Float) 
      Case 'd' 
        WriteData(FileId, *Var, SizeOf(Double)) : *Var + SizeOf(Double) 
      Case 'q' 
        WriteData(FileId, *Var, SizeOf(Quad)) : *Var + SizeOf(Quad) 
      Case 's' 
        length = Len(*Var\s) : WriteLong(FileId, length) 
        If length : WriteData(FileId, *Var\l, length) : EndIf 
        *Var + SizeOf(String) 
    EndSelect 
    *Struc + SizeOf(Character) 
  Wend 
EndProcedure 

; Datenstruktur füllen
Var\Byte = 123 
Var\word = 23432 
Var\Long = Date() 
Var\Quad = 2468012343344533 
Var\String1 = "Hallo du!" 
Var\Float = 1234.1234 
Var\String2 = "Ich bin NTQ!" 
Var\Double = 123456789.123456789 

; Datenstruktur abspeichern
If CreateFile(0, "test_structure.txt") 
  WriteDataStructure(0, @Var, @Struc_Strukt) 
  CloseFile(0) 
EndIf 

; Datenstruktur präsentieren
out = "Byte: " + Str(Var\Byte) + #lf$
out + "Word: " + Str(Var\word) + #lf$
out + "Long: " + Str(Var\Long) + #lf$
out + "Quad: " + StrQ(Var\Quad) + #lf$
out + "String1: " + Var\String1 + #lf$
out + "Float: " + Str(Var\Float) + #lf$
out + "String2: " + Var\String2 + #lf$
out + "Double: " + StrD(Var\Double) + #lf$

MessageRequester("Gespeicherte Datenstruktur",  out ) 

; so sieht die Datei aus
RunProgram("test_structure.txt", "", "")

End

Code: Alles auswählen

; Methode von NicTheQuick zur Speicherung von Strukturen mit Strings
; hier : das Einlesen aus einer geschriebenen Datei
; - die Procedure erkennt den String am Bauplan der Struktur, der als String "Struc_Strukt" übergeben wird
; - sie ermittelt die Länge, liest den String ein und speichert ihn in die Struktur-Variable
; - wollte man ein Array oder einen LinkedList auf diese Art füllen, müsste der Inhalt der
;   eingelesenen Strukturvariablen "Var" als Mitglied in das Arrays bzw. der Liste umgespeichert werden 

Define.s out                        ; Hilfsstring für Messagerequester

Define.s Struc_Strukt = "bwlqsfsd"  ; Der "Bauplan" der Struktur in einem String
Structure Strukt                    ; Daten-Struktur 
  Byte.b 
  word.w 
  Long.l 
  Quad.q 
  String1.s 
  Float.f 
  String2.s 
  Double.d 
EndStructure 
Define.Strukt Var                   ; Variable mit der Struktur anlegen

Structure AllTypes 
  StructureUnion 
    s.s : b.b : c.c : w.w : l.l : f.f : d.d : q.q
  EndStructureUnion 
EndStructure 

Procedure ReadDataStructure(FileId, *Var.AllTypes, *Struc.Character) 
  Protected length.l  
  While *Struc\c 
    Select *Struc\c 
      Case 'b' 
        ReadData(FileId, *Var, SizeOf(Byte)) : *Var + SizeOf(Byte) 
      Case 'c' 
        ReadData(FileId, *Var, SizeOf(Character)) : *Var + SizeOf(Character) 
      Case 'w' 
        ReadData(FileId, *Var, SizeOf(Word)) : *Var + SizeOf(Word) 
      Case 'l' 
        ReadData(FileId, *Var, SizeOf(Long)) : *Var + SizeOf(Long) 
      Case 'f' 
        ReadData(FileId, *Var, SizeOf(Float)) : *Var + SizeOf(Float) 
      Case 'd' 
        ReadData(FileId, *Var, SizeOf(Double)) : *Var + SizeOf(Double) 
      Case 'q' 
        ReadData(FileId, *Var, SizeOf(Quad)) : *Var + SizeOf(Quad) 
      Case 's' 
        length = ReadLong(FileId) : *Var\s = Space(length) 
        ReadData(FileId, @*Var\s, length) : *Var + SizeOf(String) 
    EndSelect 
    *Struc + SizeOf(Character) 
  Wend 
EndProcedure 

; Datenstruktur aus Datei einlesen
If ReadFile(0, "test_structure.txt") 
  ReadDataStructure(0, @Var, @Struc_Strukt) 
  CloseFile(0) 
EndIf

; Datenstruktur präsentieren
out = "Byte: " + Str(Var\Byte) + #lf$
out + "Word: " + Str(Var\word) + #lf$
out + "Long: " + Str(Var\Long) + #lf$
out + "Quad: " + StrQ(Var\Quad) + #lf$
out + "String1: " + Var\String1 + #lf$
out + "Float: " + Str(Var\Float) + #lf$
out + "String2: " + Var\String2 + #lf$
out + "Double: " + StrD(Var\Double) + #lf$

MessageRequester("Eingelesene Datenstruktur",  out ) 

End

Verfasst: 06.01.2007 09:19
von Marvin
Nur so am Rande: Ich bezweifle, dass PB die Quads intern als 2 Longs benutzt, da FASM auch "dq", also das QuadWord bereitstellt. :wink:

Verfasst: 06.01.2007 16:00
von Toshy
Nun das weiß ich nicht genau, ich erinnere mich nur an etwas, das Fred, Andre oder so mal geschrieben hat, das die Quads keine echten Quads sind, intern (noch) irgendwie anders behandelt werden. Mit der Prozessorten und ASM kenne ich micht nicht aus, aber es wurde mal erwähnt, das "logischer Weise" auf 32bit-Systemen, kein 64bit "direkt" ausgeführt werden kann.
So oder so ähnlich. Was weiß ich schon, Hauptsache das tolle PB läuft wie es sollte :-)

Verfasst: 09.01.2007 21:19
von Andre
Jear hat geschrieben:Zwei neue Funktionen also : WriteDataStructure() und ReadDataStructure().
Hab ich ebenfalls Fred + freak mit Verweis auf diesen Thread und den schon geposteten Codes vorgeschlagen.

Verfasst: 11.01.2007 14:30
von jear
@Andre
Habe mal die Routinen in eine Include-Datei gelegt und noch Testprogrämmchen mit Arrays und LinkedLists hinzugefügt.
Auch für das CodeArchiv geeignet.

StoreStructuresWithStrings.zip (3KB)

Verfasst: 11.01.2007 15:59
von NicTheQuick
Nur als Hinweis, ist aber nicht sonderlich wichtig:

Ich hab die beiden Procedures noch einmal überarbeitet. Jetzt sind sie
kürzer, aber nicht schneller.

Verfasst: 12.01.2007 17:08
von Andre
jear hat geschrieben:@Andre
Habe mal die Routinen in eine Include-Datei gelegt und noch Testprogrämmchen mit Arrays und LinkedLists hinzugefügt.
Auch für das CodeArchiv geeignet.

StoreStructuresWithStrings.zip (3KB)
Danke, ist vorgemerkt. :D