Seite 1 von 2

Pointer Problem

Verfasst: 24.11.2007 19:41
von nexus72
Hallo Zusammen,

ich hätte da mal eine Frage zu den Pointern. Ich habe mir jetzt alle
Informationen zu Pointern durchgelesen, jedoch, wenn ich das
in ein Beispiel umsetzten will, krieg ich es nicht hin.

Also folgenden Code habe:

Code: Alles auswählen

;***** Structuren definieren
Structure structTab
  lId.l
  sName.s
EndStructure

Structure structZellinh
  lId.l
  lZeile.l
  lSpalte.l
  sZelleninh.s
EndStructure

Structure structZeile
  lId.l
  lZeile.l
  qStringHash.q
EndStructure
;***** Structuren definieren Ende

;***** LinkedList
Global NewList DB1Tab.structTab()
Global NewList DB1Zellinh.structZellinh()
Global NewList DB1Zeile.structZeile()

Global NewList DB2Tab.structTab()
Global NewList DB2Zellinh.structZellinh()
Global NewList DB2Zeile.structZeile()
;***** LinkedList Ende

;... Hier folgt der Code zum füllen der LinkedListen

; Anschließend vergleiche ich diese beiden Linkedlisten DB1 mit DB2

ForEach DB2Zeile()
  ForEach DB1Zeile()
    If DB2Zeile()\qStringHash=DB1Zeile()\qStringHash
      lx.l = 1
    EndIf
  Next
  ; CallDebugger
  If lx = 1
    ; Debug "Datensatz vorhanden" + Str(DB2Zeile()\qStringHash)
  Else
    Debug "Datensatz nicht vorhanden"
  EndIf
  lx = 0
Next
Nun bin ich mir nicht ganz sicher, ob ich hier Pointer einsetzen kann.
Ich denke ja, nur ich weis noch nicht genau wie.
Besonders weis ich nicht ob der Vergleich der beiden Linkedlisten
durch Pointer beschleunigt wird, da ich ja hier nur StringHash (longs)
vergleiche.
Nur als Hinweis: DB1 und DB2 beinhalten je 180.000 Datensätze.
Dadurch wird ja der Vergleich erheblich Zeit verbrauchen. Geht
es mit Pointern schneller????
Ich hoffe es könnte mir hier jemand Hilfestellung geben, damit ich
anhand des o. g. Code das mit den Pointern verstehen lerne.

Schon mal vielen Dank für Eure Mühe.

Viele Grüße

Verfasst: 24.11.2007 21:53
von Scarabol
Hi,

also mit Pointern müsstest du das ungefähr so machen:
Du musst:
If DB2Zeile()\qStringHash=DB1Zeile()\qStringHash
durch das:
If CompareMemory(*DB2Zeile()\qStringHash,*DB1Zeile()\qStringHash,4)
4, weil eine Long Variable 4 Byte "lang" ist.
ersetzen.

und dann noch die Geschwindigkeit !ohne Debugger! vergleichen.

Gruß
Scarabol

Verfasst: 24.11.2007 22:24
von HeX0R
Scarabol hat geschrieben: If CompareMemory(*DB2Zeile()\qStringHash,*DB1Zeile()\qStringHash,4)
Das geht so nicht.

Was helfen würde, wäre ein Array anstatt einer LL zu nehmen.
Wenn die Grösse Anfangs unbekannt ist, kannst du ja per ReDim beim Einlesen das Array jeweils vergrössern ohne die bis dahin enthaltenen Elemente zu verlieren.

Verfasst: 25.11.2007 01:15
von Scarabol
Why?

Mit @ vielleicht?

Gruß
Scarabol

Verfasst: 25.11.2007 01:22
von #NULL
@nexus72
das einzige was du an operationen zeigst ist

Code: Alles auswählen

    If DB2Zeile()\qStringHash=DB1Zeile()\qStringHash
ob du da was mit pointern bastelst ist der geschwindigkeit ziemlich egal.
wenn du den grundzugriff über pointer realisieren willst geht das mit LLs nicht, sondern nur über arrays. die wären dann in manchen sachen auch schneller, aber eine (geschachtelte) foreach-schleife mit einem einfachen quadvergleich macht auf arrays umgestellt keinen wirklichen unterschied in geschw. (hab ich aber nicht getestet 8) ).
das iterieren durch eine liste ist nicht langsam, sondern eher sachen wie AddElement().

Verfasst: 25.11.2007 02:07
von nexus72
Hallo Zusammen,
hallo #Null, Scarabol, HeXOR

vielen Dank für Eure Hilfe.

Also, wenn ich das richtig verstehe, dann wäre selbst, wenn ich den
Grundzugriff über ein Array incl. Pointer realisiere, kein großer Geschwindigkeits-
unterschied zu dem derzeitigen Programmcode zu erreichen?

Könntest Du mir mal ein Beispiel für den Grundzugriff über Pointer und Array
in Abänderung des o. g. Code geben. Das wäre super.

Schon mal vielen Dank für Eure Mühe.

Viele Grüße

Verfasst: 25.11.2007 04:19
von #NULL
was dagegen wenn wir aus den 3 structures und den 6 listen erstmal 1 Structure und 2 listen machen?
..oder einfacher 3 Strc. und 2 LLs/arrays

<edit>
ne, is wurst.

also so ein dynamisches pointer array kannst du in etwa so benutzen:
(das array wird in groesseren schritten, und damit seltener neu dimensioniert)

Code: Alles auswählen

Structure struct
  a.l
  b.l
  c.l
EndStructure

max = 0
max_arr = 0

Dim *arr.struct(max)


Procedure add(*p.struct, _a, _b)
  max +1
  If max > max_arr
    max_arr + 1 + max_arr/4
    ReDim *arr.struct(max)
  EndIf
  *arr(max) = AllocateMemory(SizeOf(struct)
  If *arr(max)
    *arr(max)\a = _a
    *arr(max)\b = _b
    *arr(max)\c = 12345
  EndIf
  ProcedureReturn *arr(max)
EndProcedure


;...

For i=0 To max
  For k=0 To max
    If *arr_one(i)\a = *arr_two(i)\a
      ;...
    EndIf
  Next
Next

Verfasst: 25.11.2007 11:34
von nexus72
Hallo #Null,

super, vielen Dank für Dein Beispiel.

Ich habe gerade den Code ausgeführt und erhalte folgende Fehlermeldung
in folgender Code-Zeile:

Code: Alles auswählen

    ReDim *arr.struct(max)
und zwar: ReDim can't be used on a non-declared array: arr()

Könntest Du hier noch mal draufschauen?

Vielen Dank und viele Grüße

Verfasst: 25.11.2007 12:56
von mk-soft
Es gibt ein sehr gutes Tutorial von Freak. Sollte man auf jeden fall lesen
http://freak.purearea.net/ -> Help -> Pointer Tutorial

Hier ein kleine beispiel nur mit Pointer auf Strukturen und AllocateMemory

Code: Alles auswählen

;-TOP

; Struktur Datenanlegen
Structure udtDaten
  RecID.l
  Date.l
  Val.l
  Text.s{32} ; Mit festen String. kann man besser den Datensatz kopieren
EndStructure

; Struktur Array anlegen
Structure udtArray_of_Daten
  size.l
  id.udtdaten[0] ; <- Eigendlich nur ein Datensatz. PB macht aber keine Überwachung bei Bereichsverletzung ;)
EndStructure

; Ein Zeiger (Pointer) auf die Daten anlegen - Noch gibt es keine Speicher dafür
Global *daten.udtArray_Of_daten

; Kleine Hilfsfunktion um Speicher anzufordern
Procedure InitDaten(size)
  Protected *result.udtArray_of_daten
  *result = AllocateMemory(size * SizeOf(udtdaten) + 4) ; 4 Byte for Size
  If *result
    *result\size = size
  EndIf
  ProcedureReturn *result
EndProcedure

; Speicher anfordern
*daten = InitDaten(1000)
If *daten = 0
  Debug "Kein Speicher mehr"
  End
EndIf
; Mit Daten Arbeiten
For i = 0 To *daten\size -1
  With *daten\id[i]
    \RecID = i + 100
    \Text = "RecID: " + Str(\RecID)
  EndWith
Next
; Daten ausgeben
For i = 0 To *daten\size -1 Step 10
  With *daten\id[i]
    Debug "ID " + Str(i) + ":" + \Text
  EndWith
Next
FF :wink:

Verfasst: 25.11.2007 15:33
von nexus72
Hallo Zusammen,
hallo mk-soft,

vielen Dank für das Beispiel und für den Tip mit dem Tutorial.

Hatte einfach nur irgendwie das Problem mit dem Umsetzen
in den Code aus meinem Posting.

Nochmals vielen Dank für Deine / Eure Mühe.

Viele Grüße