Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht Das deutsche QBasic- und FreeBASIC-Forum
Für euch erreichbar unter qb-forum.de, fb-forum.de und freebasic-forum.de!
 
FAQFAQ   SuchenSuchen   MitgliederlisteMitgliederliste   BenutzergruppenBenutzergruppen  RegistrierenRegistrieren
ProfilProfil   Einloggen, um private Nachrichten zu lesenEinloggen, um private Nachrichten zu lesen   LoginLogin
Zur Begleitseite des Forums / Chat / Impressum
Aktueller Forenpartner:

Verschiedene Datentypen im gleichen Speicherfeld speichern?

 
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC.
Vorheriges Thema anzeigen :: Nächstes Thema anzeigen  
Autor Nachricht
Weazle25



Anmeldungsdatum: 04.11.2007
Beiträge: 18
Wohnort: Stralsund (Mecklenburg-Vorpommern)

BeitragVerfasst am: 02.03.2008, 18:14    Titel: Verschiedene Datentypen im gleichen Speicherfeld speichern? Antworten mit Zitat

Wie kann man verschiedene (einfache) Datentypen in ein und dem selben Speicherfeld speichern bzw aus selbigem auslesen?

Grund: Ich möchte meine Daten künftig komprimiert auf der Festplatte speichern.
Dazu müssen die komprimierten Daten in ein Speicherfeld gelesen und dort dekomprimiert werden.
Anschliessend werden die Daten aus diesem Speicherfeld ausgelesen.
Das De-/Komprimieren klappt mittlerweile problemlos.
Das Problem ist aber das auslesen der Daten.
Bisher habe ich das Speicherfeld als UByte PTR deklariert und Shorts/Ints beim Lesen/Speichern in einzelne Bytes zerlegt bzw. aus einzelnen Bytes zusammen gesetzt.
Floats musste ich um das Runden zu unterbinden bisher sogar Bitweise kopieren.

Daher meine Frage: Gibt es dafür eine einfachere Lösung?

Ich stelle mir das etwa wie bei BlitzBasic vor:
Bank = CreateBank( Size ) -> entspricht in etwa Allocate bzw. Callocate
Byte = PeekByte( Bank, Offset )
Short = PeekShort( Bank, Offset )
Float = PeekFloat( Bank, Offset )
PokeByte( Bank, Offset, Byte )
PokeFloat( Bank, Offset, Float )

Gibt es so etwas auch in FreeBasic?
Oder wie kann man das in FreeBasic umsetzen?


Gruss
Weazle
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
MisterD



Anmeldungsdatum: 10.09.2004
Beiträge: 3071
Wohnort: bei Darmstadt

BeitragVerfasst am: 03.03.2008, 00:27    Titel: Antworten mit Zitat

es gibt ein Äquivalent zu structs in C, die Types (mit der Erweiterung um funktionspointer):

TYPE foo
bar1 AS INTEGER
bar2 AS STRING
END TYPE

zB zu benutzen als

DIM obj AS foo
obj.bar1 = 2
obj.bar2 = "hallo"

schau dazu vllt mal in die Referenz.


Und Arrays gibts auch:

DIM array(maxIndex) AS type

zB

DIM feld(4) AS foo
feld(3) = obj
IF feld(4)=obj THEN PRINT "42"

suchst du sowas?
_________________
"It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration."
Edsger W. Dijkstra
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Weazle25



Anmeldungsdatum: 04.11.2007
Beiträge: 18
Wohnort: Stralsund (Mecklenburg-Vorpommern)

BeitragVerfasst am: 03.03.2008, 01:12    Titel: Antworten mit Zitat

@MisterD
Das ist leider nicht was ich suche.
Vielleicht habe ich mich etwas unglücklich ausgedrückt.
Ich will mit Allocate ein Speicherfeld erstellen und in diesem Speicherfeld Variablen mit verschiedenen Datentypen speichern.

Beispiel: (Pseudo-Code)

Bank = Allocate( 100 )
Offset = 0
PokeUByte( Bank, Offset, 200 )
Offset = 1
PokeUShort( Bank, Offset, 39217 )
Offset = 3
PokeUInteger( Bank, Offset, 1234567890 )
Offset = 7
PokeDouble( Bank, Offset, 37.45 )

Ich hoffe das das jetzt verständlicher ist.


Gruss
Weazle
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
MisterD



Anmeldungsdatum: 10.09.2004
Beiträge: 3071
Wohnort: bei Darmstadt

BeitragVerfasst am: 03.03.2008, 05:03    Titel: Antworten mit Zitat

TYPE bank
wert1 AS UBYTE
wert2 AS USHORT
wert3 AS UINTEGER
wert4 AS DOUBLE
END TYPE

DIM myBank AS bank
WITH myBank
.wert1 = 200
.wert2 = 39217
.wert3 = 1234567890
.wert4 = 37.45
END WITH

oder meinst du, dass du die typen auch noch runtime ändern können willst?
_________________
"It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration."
Edsger W. Dijkstra
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Elektronix



Anmeldungsdatum: 29.06.2006
Beiträge: 742

BeitragVerfasst am: 03.03.2008, 10:08    Titel: Antworten mit Zitat

Dim pFOO as ANY Ptr

"ANY" erlaubt es, daß der Pointer auf jede Art von Datentyp, einschließlich userdefinierte Datentypen- zeigen kann. Allerdings, bevor Du allociierst, sollte das Programm genau wissen, wieviel Speicher es braucht. D. h. die Variablen, für die Du Speicher allociierst, sollten bis dahin fertig gefüllt sein.

[Edit] Ist für Deine Belange aber ungeeignet. Ein allociierter Datentyp muß einen entsprechenden Pointer haben.

Was ist mit UNION?
_________________
Und die Grundgebihr is aa scho drin- DOS is jo nett.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Weazle25



Anmeldungsdatum: 04.11.2007
Beiträge: 18
Wohnort: Stralsund (Mecklenburg-Vorpommern)

BeitragVerfasst am: 03.03.2008, 13:19    Titel: Antworten mit Zitat

Also noch mal zum mitschreiben zwinkern
Ich will nix über UDT's oder Arrays wissen sondern über Speicherfelder die mit Allocate bzw. Callocate erstellt werden.

In der Online-Hilfe habe ich dazu dieses Beispiel gefunden:

Code:

' Platz für 15 INTEGER-Speicherstellen reservieren
CONST IntegerCount AS INTEGER = 15
DIM AS INTEGER PTR buffer
buffer = ALLOCATE( IntegerCount * LEN( INTEGER ) )

IF( buffer = 0 ) THEN
   ' Reservierung schlug fehl wenn PTR = 0
   PRINT "Fehler: Speicher konnte nicht reserviert werden"
   END -1
END IF

' Fibonacci-Sequenz einleiten
buffer[ 0 ] = 0
buffer[ 1 ] = 1

DIM AS INTEGER i
' ..., vervollständigen...
FOR i = 2 TO IntegerCount - 1
   buffer[ i ] = buffer[ i - 1 ] + buffer[ i - 2 ]         
NEXT
' ... und ausgeben
FOR i = 0 TO IntegerCount - 1
   PRINT buffer[ i ] ;
NEXT

' Speicher wieder freigeben
DEALLOCATE( buffer )

' Programm beenden
END 0


Jetzt ist das Speicherfeld aber auf Integer fest genagelt.
Ich will aber verschiedene Datentypen gleichzeitig in diesem Speicherfeld speichern.
Wenn ich nun

Code:

DIM AS INTEGER PTR buffer


durch

Code:

DIM AS Any PTR buffer


ersetze und dann mit

Code:

buffer[ 0 ] = 0


darauf zu greife sagt Freebasic das die Deklaration unvollständig sei.
Also wie muss ich das jetzt machen?


Gruss
Weazle
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
MisterD



Anmeldungsdatum: 10.09.2004
Beiträge: 3071
Wohnort: bei Darmstadt

BeitragVerfasst am: 03.03.2008, 13:27    Titel: Antworten mit Zitat

TYPE bank
wert1 AS INTEGER
wert2 AS STRING
END TYPE

DIM AS bank PTR buffer

buffer = ALLOCATE(4*sizeof(bank))

buffer[3].wert1=200
buffer[3].wert2="hallo"

DEALLOCATE(buffer)

Damit FB auf irgendwas zugreifen kann muss es den Datentyp des Speicherobjekts kennen, ANY ist ein nicht definierter Datentyp -> geht nicht. Also entweder musst du dir dann von Hand merken, was wo steht, oder du definierst deinen Speicherbereich als udt-pointer-feld was ja auch geht, siehe oben.
_________________
"It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration."
Edsger W. Dijkstra
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
volta



Anmeldungsdatum: 04.05.2005
Beiträge: 1876
Wohnort: D59192

BeitragVerfasst am: 03.03.2008, 14:27    Titel: Antworten mit Zitat

Code:
Dim As Any Ptr bank= Allocate(100)
Dim As Integer offs =0
Dim As UByte x
Cast(UByte Ptr,bank)[offs]=200
offs += 1

Cast(Ushort Ptr,bank)[offs]=39217
offs += 2

Cast(Uinteger Ptr,bank)[offs]=1234567890
offs += 4

Cast(double Ptr,bank)[offs]=37.45
offs += 8


offs -= 8
? *(Cast(double Ptr, bank)+offs)

offs -= 4
? *(Cast(Uinteger Ptr, bank)+offs)

offs -= 2
? *(Cast(Ushort Ptr, bank)+offs)

offs -= 1
? *(Cast(UByte Ptr, bank)+offs)

DeAllocate bank
sleep
Das kannst du auch als subs anlegen, ist aber sehr mühsam die Positionen der einzelnen Variablen zu rekonstruiren.
_________________
Warnung an Choleriker:
Dieser Beitrag kann Spuren von Ironie & Sarkasmus enthalten.
Zu Risiken & Nebenwirkungen fragen Sie Ihren Therapeuten oder Psychiater.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden Website dieses Benutzers besuchen
Elektronix



Anmeldungsdatum: 29.06.2006
Beiträge: 742

BeitragVerfasst am: 03.03.2008, 14:27    Titel: Antworten mit Zitat

Weazle25 hat Folgendes geschrieben:
Also noch mal zum mitschreiben zwinkern
Ich will nix über UDT's oder Arrays wissen sondern über Speicherfelder die mit Allocate bzw. Callocate erstellt werden.


Jetzt ist das Speicherfeld aber auf Integer fest genagelt.
Ich will aber verschiedene Datentypen gleichzeitig in diesem Speicherfeld speichern.
Wenn ich nun

Code:

DIM AS INTEGER PTR buffer


durch

Code:

DIM AS Any PTR buffer


ersetze und dann mit

Code:

buffer[ 0 ] = 0


darauf zu greife sagt Freebasic das die Deklaration unvollständig sei.
Also wie muss ich das jetzt machen?


Gruss
Weazle


Dann wirst Du um UDTs oder Unions nicht herumkommen. Um Speicher mit Allocate/Callocate zu reservieren, mußt Du Allocate die genaue Größe (per X*LEN(Variable)) des Speicherbereiches übergeben. Dann kannst Du per Pointer darauf zugreifen, aber nur mit dem Pointer des Variablentyps, der in dem Speicherbereich abgelegt ist. Wenn Du mehrere verschiedene Variablen brauchst, geht das nur über ein Type (UDT).
_________________
Und die Grundgebihr is aa scho drin- DOS is jo nett.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Cherry



Anmeldungsdatum: 20.06.2007
Beiträge: 249

BeitragVerfasst am: 03.03.2008, 14:33    Titel: Antworten mit Zitat

Meinst du sowas?

Code:
#define MB *1048576
Dim bank As Any Ptr = CAllocate(2 MB) ' 2 MB reservieren
Dim position As Integer = 0
' Daten speichern
*Cast(Byte Ptr, bank + position) = 123: position += SizeOf(Byte)
*Cast(Short Ptr, bank + position) = 12345: position += SizeOf(Short)
*Cast(Integer Ptr, bank + position) = 1234567: position += SizeOf(Integer)
' Daten laden (und mit Print anzeigen)
position = 0
Print *Cast(Byte Ptr, bank + position): position += SizeOf(Byte)
Print *Cast(Short Ptr, bank + position): position += SizeOf(Short)
Print *Cast(Integer Ptr, bank + position): position += SizeOf(Integer)
' Speicher freigeben
DeAllocate(bank)
Sleep
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden E-Mail senden
Weazle25



Anmeldungsdatum: 04.11.2007
Beiträge: 18
Wohnort: Stralsund (Mecklenburg-Vorpommern)

BeitragVerfasst am: 03.03.2008, 15:33    Titel: Antworten mit Zitat

Ich bin gerade in der Online-Hilfe über Peek und Poke gestolpert und da kam mir folgendes in den Sinn:

Code:

Dim Bank As Any Ptr
Bank = callocate( 100 )
Dim _Offset As UInteger = 10
Dim Value1 As Byte = 75
Dim Value2 As Short

Poke Byte, Bank + _Offset, Value1
Value2 = Peek( Short, Bank + _Offset )


Das wäre genau das was ich suche.
Jetzt muss ich nur mal schauen ob das auch funktioniert.


Gruss
Weazle
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Elektronix



Anmeldungsdatum: 29.06.2006
Beiträge: 742

BeitragVerfasst am: 03.03.2008, 15:56    Titel: Antworten mit Zitat

Weazle25 hat Folgendes geschrieben:
Ich bin gerade in der Online-Hilfe über Peek und Poke gestolpert und da kam mir folgendes in den Sinn:

Code:

Dim Bank As Any Ptr
Bank = callocate( 100 )
Dim _Offset As UInteger = 10
Dim Value1 As Byte = 75
Dim Value2 As Short

Poke Byte, Bank + _Offset, Value1
Value2 = Peek( Short, Bank + _Offset )


Das wäre genau das was ich suche.
Jetzt muss ich nur mal schauen ob das auch funktioniert.


Gruss
Weazle


Siehe dazu die FB-Hilfe:
Zitat:

Mit PEEK und POKE wurden in älteren BASIC-Dialekten Pointer-Funktionen erstellt.

Beispiel: Wert dreier Variablen aus dem Speicher lesen:
Code:

DIM ByteVal AS BYTE, ShortVal AS SHORT, IntVal AS INTEGER
DIM AS INTEGER ByteAddr, ShortAddr, IntAddr

ByteAddr  = VARPTR(ByteVal)
ShortAddr = VARPTR(ShortVal
IntAddr   = VARPTR(IntVal)

ByteVal   = 127
ShortVal  = 32767
IntVal    = 2 ^ 31 - 1

PRINT ByteVal, ShortVal, IntVal
PRINT PEEK(BYTE, ByteAddr), PEEK(SHORT, ShortAddr), PEEK(INTEGER, IntAddr)

Diese Form funktioniert einwandfrei. FreeBASIC hat jedoch eigene Pointer-Funktionen,
die ein komfortableres Programmieren ermögichen. Mit den FB-eigenen Funktionen würde dieses Beispiel so aussehen:
Code:

DIM ByteVal AS BYTE, ShortVal AS SHORT, IntVal AS INTEGER
DIM BytePtr AS BYTE PTR, ShortPtr AS SHORT PTR, IntPtr AS INTEGER PTR

BytePtr  = @ByteVal
ShortPtr = @ShortVal
IntPtr   = @IntVal

ByteVal   = 127
ShortVal  = 32767
IntVal    = 2 ^ 31 - 1

PRINT ByteVal, ShortVal, IntVal
PRINT *BytePtr, *ShortPtr, *IntPtr

Die Syntax *Pointer gibt also den Wert zurück, der an der Speicherstelle steht, auf die der Pointer zeigt. Wie viele Bytes
gelesen werden, hangt dabei vom Typ des Pointers ab (BYTE PTR, SINGLE PTR, ...)


Der Zugriff über Pointer oder über Poke ist demnach gleichwertig.
_________________
Und die Grundgebihr is aa scho drin- DOS is jo nett.
Nach oben
Benutzer-Profile anzeigen Private Nachricht senden
Beiträge der letzten Zeit anzeigen:   
Neues Thema eröffnen   Neue Antwort erstellen    Das deutsche QBasic- und FreeBASIC-Forum Foren-Übersicht -> Allgemeine Fragen zu FreeBASIC. Alle Zeiten sind GMT + 1 Stunde
Seite 1 von 1

 
Gehe zu:  
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.

 Impressum :: Datenschutz