Struktur variabel erweitern ?

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Struktur variabel erweitern ?

Beitrag von Bisonte »

Hallo miteinander...

Code: Alles auswählen

Structure lagerdaten

Item.s
Lager.s

Endstructure

...

Item(1)\Item=GetDatabaseString(0)
Item(1)\Lager=GetDatabaseString(1)
wenn nun Lager.s noch eins dazukommt... wie sag ich meinem Programm, das er das auch einlesen soll....

Ein Lager.s[MaxLager] funktioniert leider nicht, Fehlermeldung ....

Wäre es eine LinkList, hätte ich das gleiche Problem mit dem einlesen aus der DB...

Das Table sieht so aus :

Item,Lager1,Lager2,Lager3....usw.

Ein Datensatz demnach

Kuchen,0,2,1,....usw


P.S.: PB 3.3 nicht vergessen ;)

Help ...
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

das geht nur, wenn du von vornherein eine feste anzahl möglicher weiterer lagerorte vorsiehst,
also z.b.

Code: Alles auswählen

Structure lagerdaten
  Item.s
  Lager1.s
  Lager2.s
  Lager3.s
Endstructure
um die größe musst du dir keine sorgen machen, da die strukturierten elemente selber nur 4byte pro pointer brauchen.
an stringspeicher wird nur benötigt was auch belegt wird.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Re: Struktur variabel erweitern ?

Beitrag von NicTheQuick »

Bisonte hat geschrieben:Ein Lager.s[MaxLager] funktioniert leider nicht, Fehlermeldung ....
Wenn du statt MaxLager eine Konstante benutzt, also #MaxLager, dann
funktioniert es. Statische Arrays funktionieren nur mit Konstanten.

Code: Alles auswählen

#MaxLager = 10
Structure lagerdaten
  item.s
  Lager.s[#MaxLager]
EndStructure

Lager.lagerdaten
Lager\item = "Kuchen"
For a = 0 To #MaxLager - 1
  Lager\Lager[a] = Str(Random(1000))
Next

Debug Lager\item
For a = 0 To #MaxLager - 1
  Debug Lager\Lager[a]
Next
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Beitrag von Bisonte »

Also in der Datenbank wird bei einer Lagererweiterung ein Table hinzugefügt.

Also sollte ich demnach sagen wir

Code: Alles auswählen

Lager.s[100]
schreiben,dann wird auch nur der Platz im Speicher belegt, wo auch wirklich daten drin sind ? (ok plus 4 Byte für den Pointer also 100*4)

hab ich das so richtig im blick ?

Weil es wohl keine 100 Lager geben wird...Soll also heissen

Code: Alles auswählen

Structure lagerdaten
Item.s
Lager.s[100]
EndStructure

....

Item(1)\Item=GetDataBaseString(0)
For x=1 To AnzahlLager
Item(1)\Lager[x]=GetDataBaseString(x)
Next x
....

War das so gemeint ?
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Beitrag von Bisonte »

Das mit der Konstanten hätte den Haken:

Ich muss vorher die Anzahl der Tables ermitteln, und wenn ich

#MaxLager = Lager.l

Schreibe, dann gibts Fehlermeldung...
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8809
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 64 GB DDR4-3200
Ubuntu 24.04.2 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken

Beitrag von NicTheQuick »

Ich hab hier auch noch eine andere Möglichkeit, wenn du die willst. Die
müsste auch mit PB V3.3 funktionieren. Hab sie gerade extra etwas
abgeändert. Sie ist auch dynamisch, aber weniger komfortabel.

Code: Alles auswählen

Procedure SetString(*pPtr.Long, String.s)
  Protected Size.l = Len(String)
  
  If Size = 0
    If *pPtr\l
      FreeMemory(*pPtr\l)
      *pPtr\l = 0
      ProcedureReturn #True
    Else
      ProcedureReturn #True
    EndIf
  EndIf
  
  *pPtr\l = ReAllocateMemory(*pPtr\l, Size + SizeOf(Long) + 1)
  
  If *pPtr\l
    PokeL(*pPtr\l, Size)
    PokeS(*pPtr\l + SizeOf(Long), String)
    ProcedureReturn #True
  EndIf
  
  ProcedureReturn #False
EndProcedure

Procedure.s GetString(*pPtr.Long)
  If *pPtr\l
    ProcedureReturn PeekS(*pPtr\l + SizeOf(Long), PeekL(*pPtr\l))
  EndIf
  
  ProcedureReturn ""
EndProcedure

Procedure.l StringLength(*pPtr.Long)
  If *pPtr\l
    ProcedureReturn PeekL(*pPtr\l)
  EndIf
  
  ProcedureReturn 0
EndProcedure

Structure SArray
  *arr
  c.l
EndStructure

Procedure SA_Add(*SArray.SArray, String.s) ;Fügt einen neuen String ans Ende hinzu
  Protected *tmp
  
  *tmp = ReAllocateMemory(*SArray\arr, (*SArray\c + 1) * SizeOf(*tmp))
  If *tmp
    *SArray\arr = *tmp
    *tmp + *SArray\c * SizeOf(*tmp)
    SetString(*tmp, String)
    *SArray\c + 1
    
    ProcedureReturn #True
  EndIf
  
  ProcedureReturn #False
EndProcedure

Procedure SA_Del(*SArray.SArray, pos.l) ;Löscht String an Position
  Protected *tmp
  
  If pos >= 0 And pos < *SArray\c
    *tmp = *SArray\arr + pos * SizeOf(*tmp)
    SetString(*tmp, "")
    MoveMemory(*tmp + SizeOf(*tmp), *tmp, (*SArray\c - pos - 1) * SizeOf(*tmp))
    *SArray\c - 1
    If *SArray\c
      *SArray\arr = ReAllocateMemory(*SArray\arr, *SArray\c * SizeOf(*tmp))
    Else
      FreeMemory(*SArray\arr)
      *SArray\arr = 0
    EndIf
    ProcedureReturn #True
  EndIf
  
  ProcedureReturn #False
EndProcedure

Procedure SA_Set(*SArray.SArray, pos.l, String.s) ;Setzt String
  Protected *tmp
  
  If pos >= 0 And pos < *SArray\c
    *tmp = *SArray\arr + pos * SizeOf(*tmp)
    
    SetString(*tmp, String)
    
    ProcedureReturn #True
  EndIf
  
  ProcedureReturn #False
EndProcedure

Procedure.s SA_Get(*SArray.SArray, pos.l) ;Gibt String zurück
  Protected *tmp
  
  If pos >= 0 And pos < *SArray\c
    *tmp = *SArray\arr + pos * SizeOf(*tmp)
    
    ProcedureReturn GetString(*tmp)
  EndIf
  
  ProcedureReturn ""
EndProcedure

Procedure SA_Move(*SArray.SArray, pos.l, newpos.l) ;Verschiebt String an neue Position
  Protected *String, *tmp.SArray
  
  If pos = newpos : ProcedureReturn #False : EndIf
  If pos >= 0 And newpos >= 0 And pos < *SArray\c And newpos < *SArray\c
    *tmp = *SArray\arr + pos * SizeOf(Long)
    *String = *tmp\arr
    
    If pos < newpos
      MoveMemory(*tmp + SizeOf(*String), *tmp, (newpos - pos) * SizeOf(*String))
      *tmp = *SArray\arr + newpos * SizeOf(*String)
      *tmp\arr = *String
    Else
      *tmp = *SArray\arr + newpos * SizeOf(*String)
      MoveMemory(*tmp, *tmp + SizeOf(*String), (pos - newpos) * SizeOf(*String))
      
      *tmp\arr = *String
    EndIf
  EndIf
EndProcedure

Procedure SA_Clear(*SArray.SArray) ;Löscht das gesamte Array
  Protected a.l, *tmp = *SArray\arr
  
  For a = 1 To *SArray\c
    SetString(*tmp, "")
    *tmp + SizeOf(String)
  Next
  
  If *SArray\arr : FreeMemory(*SArray\arr) : EndIf
  *SArray\arr = 0
  *SArray\c = 0
EndProcedure

Structure Lager
  item.s
  Lager.SArray
EndStructure

Define Lager.Lager

Lager\item = "Kuchen"
items = Random(10)
For a = 1 To items
  SA_Add(Lager\Lager, Str(a))
Next

Debug Lager\item
For a = 1 To Lager\Lager\c  ;Anzahl Elemente
  Debug SA_Get(Lager\Lager, a - 1)
Next

Debug ""
SA_Clear(Lager\Lager)
Debug Lager\Lager\c
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Beitrag von Bisonte »

Hossa die Waldfee....

Ich bin doch DER "Pointernoob..." ;)

Da muss ich erstmal sichten was das alles ist ....

Dank ... hier bekommt man ja verdammt schnell ne Antwort ;)
Kaeru Gaman
Beiträge: 17389
Registriert: 10.11.2004 03:22

Beitrag von Kaeru Gaman »

> dann wird auch nur der Platz im Speicher belegt, wo auch wirklich daten drin sind ? (ok plus 4 Byte für den Pointer also 100*4)

eigentlich schon. ich würd sicherheitshalber auf der 3.30 noch mal nen testlauf machen.

z.b. sowas:
taskmanager aufmachen, prozessfenster anzeigen, und das hier starten

Code: Alles auswählen

Structure Test
  Item.s
  Name.s[100]
EndStructure
Dim TestLager.Test(999)

Debug "Array ist leer. Speicherbedarf checken."
Delay(10000)  ; 10 sec Pause
Debug "---"
Debug "Array wird nun schrittweise gefüllt."

For n=0 To 99
  Debug "--- Schritt "+Str(n+1)+" ---"
  For t=0 To 9
    For x=0 To 99
      TestLager(10*n+t)\Name[x] = Space(1023)
    Next x
    Debug "Item Nr."+Str(t)+": +100KB"
  Next t
  Debug "Schritt "+Str(n+1)+" abgeschlossen: 1MB beansprucht."
  Delay(1000)
Next n
damit wird in 1-sec-Schritten jeweils 1MB mehr beansprucht.
...auf der 4.02 sieht es sogar so aus, als ob auch der Speicher für die Pointer erst beim belegen wirklich angefordert wird.
Der Narr denkt er sei ein weiser Mann.
Der Weise weiß, dass er ein Narr ist.
Benutzeravatar
Bisonte
Beiträge: 2468
Registriert: 01.04.2007 20:18

Beitrag von Bisonte »

jupp.... bei 3.3 ist es so ;) man kann zusehen wie der Speicher sich vollmüllt ;) Mercy ...
Antworten