Ich brauche ein Dynamisches, 3 Dimensionales Array

Alle Fragen zur Programmierung
gambasso
Foriker
Beiträge: 806
Registriert: Sa 17. Mär 2012, 09:55
Kontaktdaten:

Ich brauche ein Dynamisches, 3 Dimensionales Array

Beitrag von gambasso » Mi 8. Apr 2015, 18:59

moin,

ich brauche ein 3 Dimensionales Array, vom dem ich im voraus nicht weis wie groß es werden soll, und ob ich es jedesmal benötige.
Da soll im Bedarfsfall rein: 1 String mit 512 Bytes, 1 String mit 10 Bytes und eine Long-Zahl mit bis zu 10.000.000.000 (10 Mrd.).
Wobei die Long-Zahl ja auch als String gehen sollte und hoffentlich gewandelt werden kann.

Wie lege ich so ein Array an?
Wie schreibe ich den ersten 3-dimensionalen Eintrag?
Wie addiere ich den nächsten 3-dimensionalen Eintrag?
Wie lösche ich einen 3-dimensionalen Eintrag?
Wie lese ich die momentane Größe des Arrays und dessen Dimensionen aus?

Im Wiki steht was von 'Bounds'. Wie lese ich das ein und verarbeite es? Interger will nicht.
Gruss

tux_
Moderator
Beiträge: 941
Registriert: Di 11. Nov 2008, 20:05
Kontaktdaten:

Re: Ich brauche ein Dynamisches, 3 Dimensionales Array

Beitrag von tux_ » Mi 8. Apr 2015, 19:45

Da soll im Bedarfsfall rein: 1 String mit 512 Bytes, 1 String mit 10 Bytes und eine Long-Zahl mit bis zu 10.000.000.000 (10 Mrd.).


Das sind nur drei Groeszen. Du kannst fuer jede eine Variable (String, String, Long) anlegen. Dann brauchst du doch kein Array, geschweige denn ein dreidimensionales?

Ansonsten aber eine gut gestellte Frage. Das Gambas-Buch[0] hat Arrays allerdings auch schon breit besprochen -- auch die flexiblen mehrdimensionalen.

[0] http://www.gambas-buch.de/dw/doku.php?id=k7:k7.4:start, das ganze Kapitel 7.4.
Achtung: Es passiert, dass ich einen frisch geschrieben Beitrag innerhalb von 10 Minuten noch 3-4 Mal aendere!

gambasso
Foriker
Beiträge: 806
Registriert: Sa 17. Mär 2012, 09:55
Kontaktdaten:

Re: Ich brauche ein Dynamisches, 3 Dimensionales Array

Beitrag von gambasso » Do 9. Apr 2015, 08:21

moin,

einzeln ist nicht so gut, wenn die Daten in einem Array stehen, dann ist die Zusammengehörigkeit besser gewährleistet.
Im Gambasbuch steht aber nicht, finde ich jedenfals nicht, wie ich die diese weiterverarbeite, wie ich es genannt hatte.
Da werden die Abfragen nur ausgegeben und nicht in Variable gepackt, z.B. 'Bounds'.
Gruss

tux_
Moderator
Beiträge: 941
Registriert: Di 11. Nov 2008, 20:05
Kontaktdaten:

Re: Ich brauche ein Dynamisches, 3 Dimensionales Array

Beitrag von tux_ » Do 9. Apr 2015, 11:32

Wenn die drei Werte zusammengehoeren, dann kannst du ein Struct benutzen:
gambas code
Public Struct StructName
String1 As String ' der mit 512 Bytes
String2 As String ' der mit 10 Bytes
TheLong As Long ' die Long-Zahl
End Struct

Private $hMyData As New StructName

Das Objekt $hMyData haelt jetzt drei zusammengehoerige Variablen, in die deine Werte hineinpassen. Du kannst von dieser Struktur auch ein eindimensionales (!) Array erzeugen, wenn du mehrere solcher Datensaetze brauchst.

Im Gambasbuch steht aber nicht, finde ich jedenfals nicht, wie ich die diese weiterverarbeite, wie ich es genannt hatte.

Um aber doch deine Fragen (zumindest teilweise) zu beantworten (auch wenn mir scheint, dass dein Ansatz wesentlich komplizierter ist, als noetig):
Wie lege ich so ein Array an?

Ich wuerde hier ein sog. abgeleitetes Array empfehlen. Damit bekommt man mehrere flexible Dimensionen. Im folgenden arbeite ich mit einem dreidimensionalen Array von Labels. Es wird angelegt als
gambas code
Dim hArray As New Label[][][]

Wie schreibe ich den ersten 3-dimensionalen Eintrag?
Wie addiere ich den nächsten 3-dimensionalen Eintrag?
Wie lösche ich einen 3-dimensionalen Eintrag?

Hier ist nicht klar, was ein "dreidimensionaler Eintrag" sein soll. Dreidimensional bedeutet, dass sich dein Array in drei voneinander unabhaengige Richtungen ausdehnen kann. Am besten betrachtest du ein dreidimensionales Array wie unseren dreidimensionalen Anschauungsraum. "Hinzufuegen" kann man mehrere Arten von Dingen:
  • einen einzelnen Punkt,
  • eine Gerade oder
  • eine Ebene.
In der Sprache der abgeleiteten Arrays bedeutet das, dass du einen Eintrag irgendwo an eines der am weitesten verschachtelten Arrays anhaengen kannst (Punkt) oder einen Eintrag an das mittlere der verschachtelten Arrays (Gerade) oder gar an das aeuszerste Array (was dir eine neue zweidimensionale Ebene liefert). In einer neuen Ebene eine neue Gerade und einen neuen Punkt anzulegen ist ein nicht ganz einfacher Fall und wird so erledigt:
gambas code
Dim hPlane As New Label[][], hLine As New Label[], hPoint As New Label

' ... <- weise hier dem neuen Label hPoint Eigenschaften zu, wie hPoint.Text, etc.
hLine.Add(hPoint)
hPlane.Add(hLine)
hArray.Add(hPlane)

Wie lese ich die momentane Größe des Arrays und dessen Dimensionen aus?

Auch schwierig. Wenn du mit Groesze die Anzahl der Elemente des Arrays meinst, dann
gambas code
Dim I, J, Count As Integer

For I = 0 To hArray.Max
For J = 0 To hArray[I].Max
Count += hArray[I][J].Count
Next
Next

Die Dimension eines dreidimensionalen abgeleiteten Arrays kannst du nur mit einem zweidimensionalen Array (Matrix mit Integer-Werten) beschreiben, weil jede Gerade in deinem Raum eine andere Ausdehnung haben kann als jede andere. Ich bezweifle wirklich, dass es das ist, was du tun willst.

Vielleicht moechtest du eher ein dreispaltiges eindimensionales Array haben? Das waere das "StructName[]" aus meinem ersten Absatz.
Achtung: Es passiert, dass ich einen frisch geschrieben Beitrag innerhalb von 10 Minuten noch 3-4 Mal aendere!

gambasso
Foriker
Beiträge: 806
Registriert: Sa 17. Mär 2012, 09:55
Kontaktdaten:

Re: Ich brauche ein Dynamisches, 3 Dimensionales Array

Beitrag von gambasso » Do 9. Apr 2015, 17:57

hi tux,

ich möchte ein Array das ungefähr so aussieht:
jeder Datensatz hat 3 Felder:
Feld 1 = 512 Bytes - 1 Sektor einer Festplatte (können auch manchmal mehr sein) -/- Feld2: 10 Bytes - das Device -/- Feld 3: eine 11-stellige Zahl - Sektornummer
Ich weiss sonst nicht wie ich es beschreiben soll.
Diese 3 Angaben möchte ich nach Belieben speichern, abrufen (anzeigen) oder löschen können.
Bei 1-dimensionalen Arrays weiss ich wie es geht, hier habe ich aber 3 Datenfelder aufeinmal.

Wenn ich ein Sektor aufrufe, und er hat eine Verzweigung zum folgenden Sektor, daß muß ja nicht der numerische Nächste sein, so möchte ich diesen auf Wunsch speichern können.
Da die Angabe der Sektoren und Größe der Partitionen in Little-Endian erfolgt, werde ich wohl zur Kontrolle erstmals zwischen den Sektoren hin- und herschalten müssen.
Gruss

tux_
Moderator
Beiträge: 941
Registriert: Di 11. Nov 2008, 20:05
Kontaktdaten:

Re: Ich brauche ein Dynamisches, 3 Dimensionales Array

Beitrag von tux_ » Do 9. Apr 2015, 22:11

ich möchte ein Array das ungefähr so aussieht:
jeder Datensatz hat 3 Felder:
Feld 1 = 512 Bytes - 1 Sektor einer Festplatte (können auch manchmal mehr sein) -/- Feld2: 10 Bytes - das Device -/- Feld 3: eine 11-stellige Zahl - Sektornummer


OK. Das ist ein eindimensionales Array mit drei Spalten. Es ist eindimensional, weil das Array nur in eine Richtung wachsen kann (die Anzahl der Spalten ist ja fest, nur die Zeilenzahl, d.h. die Anzahl solcher Datensaetze, ist variabel). Mit solchen eindimensionalen Arrays kann man ja gut arbeiten. Du realisierst es am besten als Struktur:
gambas code
Public Struct Sektor
Daten As String
Device As String
SektorNr As Long
End Struct
...
Dim hArray As New Sektor[] ' Array anlegen
Dim hSektor As New Sektor ' neuer Sektor zum anfuegen

hSektor.Daten = sSektorDaten ' hSektor mit deinen Datenfuellen, etc.
hArray.Add(hSektor) ' neuen Sektor an das Ende des Arrays anfuegen

hSektor = hArray[iIndex] ' einen Sektor anhand seines Index holen...
Print hSektor.Daten, hSektor.Device, hSektor.SektorNr ' ...und anzeigen

Um einen Sektor anhand seiner SektorNr zu suchen musst du ggf. ueber das Array iterieren (auszer du weiszt etwas mehr ueber den Aufbau des Arrays wie Sortierung).
Achtung: Es passiert, dass ich einen frisch geschrieben Beitrag innerhalb von 10 Minuten noch 3-4 Mal aendere!

gambasso
Foriker
Beiträge: 806
Registriert: Sa 17. Mär 2012, 09:55
Kontaktdaten:

Re: Ich brauche ein Dynamisches, 3 Dimensionales Array

Beitrag von gambasso » Fr 10. Apr 2015, 08:38

hi tux,

einmal zuweisen klappt, weil jedesmal das Array (Zeile 7) neu erstellt wird. Beim 2. Male wird das Array wieder neu angelegt, und die vorherigen Daten sind weg.

Wie und wo lege ich das Array so an, daß es nicht jedesmal überschrieben wird?
Gruss

tux_
Moderator
Beiträge: 941
Registriert: Di 11. Nov 2008, 20:05
Kontaktdaten:

Re: Ich brauche ein Dynamisches, 3 Dimensionales Array

Beitrag von tux_ » Fr 10. Apr 2015, 09:02

:shock: Als globale Variable natuerlich!
gambas code
Private $hArray As New Sektor[]

im Kopf deiner Klasse, noch bevor du die erste Funktion implementierst.

Wenn Gambas deine erste Programmiersprache ist, solltest du einen Programmiergrundkurs zurate ziehen ("wie strukturiert man ein Programm?", "was sind globale Variablen?", "was ist eine Funktion und warum schreibt man sie?", etc.). Im Gambas-Buch ist ein solches Grundlagen-Kapitel nicht vorgesehen, wenn ich richtig sehe, was auch vernuenftig ist, weil es eine grosze didaktische Herausforderung ist, die andere Autoren schon bewaeltigt haben und hier nichts wirklich sprach-spezifisches behandelt wird.
Achtung: Es passiert, dass ich einen frisch geschrieben Beitrag innerhalb von 10 Minuten noch 3-4 Mal aendere!

gambasso
Foriker
Beiträge: 806
Registriert: Sa 17. Mär 2012, 09:55
Kontaktdaten:

Re: Ich brauche ein Dynamisches, 3 Dimensionales Array

Beitrag von gambasso » Fr 10. Apr 2015, 11:27

Bei

gambas code
Private $hArray As New Sektor[]

vor allem, kommt: 'Unbekannter Bezeichner: Sektor...'

In einer 'Sub' wird nicht gemeckert.
Gruss

tux_
Moderator
Beiträge: 941
Registriert: Di 11. Nov 2008, 20:05
Kontaktdaten:

Re: Ich brauche ein Dynamisches, 3 Dimensionales Array

Beitrag von tux_ » Fr 10. Apr 2015, 12:20

vor allem, kommt: 'Unbekannter Bezeichner: Sektor...'

Hast du die Variable vielleicht deklariert, bevor du die Sektor-Struktur deklarierst? Der Compiler weisz natuerlich nicht, was ein "Sektor" sein soll, bevor du ihm zeigst, was ein Sektor ist:

gambas code
Public Struct Sektor
Daten As String
Device As String
SektorNr As Long
End Struct

Private $hArray As New Sektor[]
Achtung: Es passiert, dass ich einen frisch geschrieben Beitrag innerhalb von 10 Minuten noch 3-4 Mal aendere!

gambasso
Foriker
Beiträge: 806
Registriert: Sa 17. Mär 2012, 09:55
Kontaktdaten:

Re: Ich brauche ein Dynamisches, 3 Dimensionales Array

Beitrag von gambasso » Fr 10. Apr 2015, 12:56

ja, das Addieren klappt, aber es stehen in jedem Element die Daten vom letzetn 'Add'.

Habe eine Schleife (10 Durchläufe) gemacht, in der Zufallszahlen + Text erzeugt werden. Die zufälligen Daten lasse ich mir anzeigen.
Am Ende der Schleife ein :
gambas code
hArray.Add(hSektor) ' neuen Sektor an das Ende des Arrays anfuegen

Die erzeugten daten sind alle unterschiedlich, aber in dem Array sind alle Satensätze gleich.

gambas code
Public S_Daten As String
Public D_Daten As String
Public N_Daten As Long

Public Struct Sektor
Daten As String
Device As String
SektorNr As Long
End Struct

Private hArray As New Sektor[]


gambas code
Public Sub Button1_Click() '                    Button1_Click   Erstelle
Dim hSektor As New Sektor ' neuer Sektor zum anfuegen
Dim ii, jj, zz As Integer
Dim hi1 As String

hArray = New Sektor[]
S_Daten = ""
Randomize

For jj = 1 To 10
For ii = 1 To 20 ' Text für Daten
zz = Int(Rnd(65, 90))
S_Daten &= Chr(zz)
Next
Print jj & " S_Daten: " & S_Daten

For ii = 1 To 11 ' 11 -stellige Zahl
zz = Int(Rnd(0, 9))
hi1 &= Str(zz)
Next

N_Daten = Val(hi1)
Print jj & " hi1: " & hi1
hi1 = ""
hSektor.Daten = S_Daten
hSektor.Device = "/dev/sgd" & Str(jj)
hSektor.SektorNr = N_Daten

Print jj & " hSektor.Device: " & hSektor.Device
hArray.Add(hSektor) ' neuen Sektor an das Ende des Arrays anfuegen
S_Daten = ""
N_Daten = -1
D_Daten = ""
Next

End ' Button1_Click
Gruss

gambasso
Foriker
Beiträge: 806
Registriert: Sa 17. Mär 2012, 09:55
Kontaktdaten:

Re: Ich brauche ein Dynamisches, 3 Dimensionales Array

Beitrag von gambasso » Fr 10. Apr 2015, 13:25

Ich glaube es klappt, ich habe hinter
gambas code
For jj = 1 To 10

ein
gambas code
hSektor = New Sektor

eingefügt.
Ist schon seltsam, warum wurde 'hArray' vorher komplett mit dem letzten Werten überschrieben?
Gruss

tux_
Moderator
Beiträge: 941
Registriert: Di 11. Nov 2008, 20:05
Kontaktdaten:

Re: Ich brauche ein Dynamisches, 3 Dimensionales Array

Beitrag von tux_ » Fr 10. Apr 2015, 13:45

Ist schon seltsam, warum wurde 'hArray' vorher komplett mit dem letzten Werten überschrieben?

Es mag beim ersten Mal seltsam erscheinen, ist aber richtig so.

Bei $hArray.Add(hSektor) schreibst du ein Objekt in das Sektor-Array. Objekte sind in Gambas nichts weiter als Referenzen (a.k.a. Zeiger) auf einen Speicherbereich. Wenn du zwischendurch also nicht immer neue Sektor-Objekte erzeugst, dann speicherst du mehrfach die gleiche Referenz im Array. Alle Eintraege deines Arrays zeigen dann auf den gleichen Speicherbereich. Auszerdem aenderst du in jeder Iteration mit
gambas code
hSektor.Daten = S_Daten
hSektor.Device = "/dev/sgd" & Str(jj)
hSektor.SektorNr = N_Daten

die Daten hinter der Referenz. Also kommt es dir so vor, als wuerde in allen Eintraegen das gleiche stehen. Es ist aber so, dass alle Eintraege nur auf den gleichen Speicher verweisen, in dem die Daten der letzten Iteration stehen.

Des Problems Loesung hast du schon erkannt: erzeuge in jeder Iteration ein neues Objekt.
Achtung: Es passiert, dass ich einen frisch geschrieben Beitrag innerhalb von 10 Minuten noch 3-4 Mal aendere!

gambasso
Foriker
Beiträge: 806
Registriert: Sa 17. Mär 2012, 09:55
Kontaktdaten:

Re: Ich brauche ein Dynamisches, 3 Dimensionales Array

Beitrag von gambasso » Fr 10. Apr 2015, 14:04

ist aber gewöhnungsbedürftig und nicht ganz schlüssig.
hat denn das Array: - hArray.Add(hSektor) - nicht seinen eigenen Speicherbereich, da müßte es doch das 'Richtige' hinpacken.
Denn bei jedem '*.Add' steht doch was Anderes in dem Daten und der eigene Zähler von 'hArray' wird doch um 1 erhöht, sollte es zumindest.
Also, bekommt er jedesmal andere Daten, nur ist sein Zähler ist kaputt?
Gruss

tux_
Moderator
Beiträge: 941
Registriert: Di 11. Nov 2008, 20:05
Kontaktdaten:

Re: Ich brauche ein Dynamisches, 3 Dimensionales Array

Beitrag von tux_ » Fr 10. Apr 2015, 14:57

Das Array hat seinen eigenen Speicher und in jedem Eintrag steht ein Sektor-Objekt. Durch $hArray.Add(hSektor) fuegst du einen Eintrag hinzu und schreibst das Objekt hSektor in diesen Eintrag. Soweit verstehen wir uns?

Nun habe ich gesagt, dass ein Objekt in Gambas nur eine Referenz ist, ein Zeiger auf einen bestimmten Speicherbereich. Ein Objekt-Array wie $hArray speichert nur Verweise auf Speicherbereiche, in denen die eigentlichen Daten der Array-Elemente liegen. Es werden keine Kopien der Objekte angelegt[*]! Du hast nur ein einziges hSektor-Objekt in deinem Quelltext (wenn du nicht "hSektor = New Sektor" in jeder Iteration ausfuehrst) und dieser hSektor hat eine fixe Adresse. Da du immer wieder dieses eine hSektor-Objekt in das Array schreibst, ist dein Array am Ende mit k-mal der gleichen Adresse gefuellt. Alles zeigt auf ein einziges Sektor-Objekt im Speicher und das ist mit den Daten gefuellt, die du zuletzt hinein geschrieben hast, naemlich den Daten aus der letzten Iteration. Ein Bild:

object-array.png
object-array.png (9.65 KiB) 4672 mal betrachtet


[*] Zum einen, weil der Interpreter nicht weisz, wie man das macht und zum anderen weil es in mindestens der Haelfte der Faelle unerwuenscht ist. Du hast hier einen Fall, in dem es erwuenscht waere, weil deine Objekte nirgendwo sonst gespeichert oder dargestellt werden. Nimm z.B. den Fall, dass du ein Array von Labels auf deinem Formular speichern willst, um bestimmte Werte bei dieser ganzen Gruppe von Labels auf einmal zu aendern. Wenn das Hinzufuegen zu diesem Array mit einer Kopie der Objekte verbunden waere, dann haette man auf einmal doppelt so viele Labels auf dem Formular, wie man eigentlich will und man wuerde immer nur auf den Kopien arbeiten, nicht auf den originalen Labels.
Achtung: Es passiert, dass ich einen frisch geschrieben Beitrag innerhalb von 10 Minuten noch 3-4 Mal aendere!

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast