nummer eines structurefeldes

Für allgemeine Fragen zur Programmierung mit PureBasic.
BSP
Beiträge: 203
Registriert: 01.02.2009 14:04

nummer eines structurefeldes

Beitrag von BSP »

Hallo Allerseits.
Innerhalb meines Prg arbeite ich mit Structuren.
Zum abspeichern in einer Datei möchte ich nun alle Ergebnisse der Structur zu einem Satz zusammenfügen.
Um den Satz nun nicht in lauter einzelschritten zusammen zu fügen,
möchte ich das gerne in einer Schleife erledigen.
Gibt es dazu einen weg, die Nummer eines Structurefeldes zu erkennen?
Hier mal ein Beispiel, damit Ihr seht, was ich meine:

Code: Alles auswählen

Structure worte
  wort1.s
  wort2.s
  wort3.s
EndStructure
Define a.worte
Define satz.s

a\wort1 = "Test1"
a\wort2 = "Test2"
a\wort3 = "Test3"

; Version 1 : Alles einzeln Zusammenfügen
satz = a\wort1 +Chr(30)
satz + a\wort2 +Chr(30)
satz + a\wort3 +Chr(30)
Debug satz

; Version 2 : Alles durch eine Schleife zusammenfügen
satz = ""
For i = 1 To anzahl_structurefelder
  satz + a\structurefeld_i +Chr(30)
Next
Debug satz
Gruß: Bernd
PB 5.31 (x86) & (x64) Win10
c4s
Beiträge: 1235
Registriert: 19.09.2007 22:18

Re: nummer eines structurefeldes

Beitrag von c4s »

In dem Fall lohnt es sich eventuell die Strukturierung zu überdenken. Mit einer Liste geht es wunderbar:

Code: Alles auswählen

Structure worte
  List wort.s()
EndStructure
Define a.worte
Define satz.s

AddElement(a\wort()) : a\wort() = "Test1"
AddElement(a\wort()) : a\wort() = "Test2"
AddElement(a\wort()) : a\wort() = "Test3"

ForEach a\wort()
	satz + a\wort() +Chr(30)
Next
Debug satz
"Menschenskinder, das Niveau dieses Forums singt schon wieder!" — GronkhLP ||| "ich hogffe ihr könnt den fehle endecken" — Marvin133 ||| "Ideoten gibts ..." — computerfreak ||| "Jup, danke. Gruss" — funkheld
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8838
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: nummer eines structurefeldes

Beitrag von NicTheQuick »

Die schöne Version wäre offensichtlich ein statisches Array in der Structure:

Code: Alles auswählen

Structure worte
  wort.s[3]
EndStructure
Define a.worte
Define satz.s

a\wort[0] = "Test1"
a\wort[1] = "Test2"
a\wort[2] = "Test3"

; Version 2 : Alles durch eine Schleife zusammenfügen
satz = ""
For i = 0 To 2
  satz + a\wort[i] + Chr(30)
Next
Debug satz
Die nicht so schöne Version funktioniert mit Pointern und funktioniert auch nur, wenn in der Structure tatsächlich nur Strings nacheinander vorkommen und sonst nichts.

Code: Alles auswählen

Structure worte
  wort1.s
  wort2.s
  wort3.s
EndStructure
Define a.worte
Define satz.s

a\wort1 = "Test1"
a\wort2 = "Test2"
a\wort3 = "Test3"

; Version 2 : Alles durch eine Schleife zusammenfügen
satz = ""
Define *wortPointer.String = @a
For i = 1 To 3
  satz + *wortPointer\s + Chr(30)
  *wortPointer + SizeOf(String)
Next
Debug satz
BSP
Beiträge: 203
Registriert: 01.02.2009 14:04

Re: nummer eines structurefeldes

Beitrag von BSP »

Hallo c4s, Hallo Nick

Das es auch andere Möglichkeiten gibt, ist mir klar.
Ich könnte auch mit arrays arbeiten und brauche die dann nur zu durchlaufen.
Aber ich habe mein Beispiel mit bedacht so gewählt.
Es ist eben nur ein Beispiel.
Tatsächlich ist meine structur natürlich umfangreicher.
In dem Zusammenhang noch eine weitere Frage:
Man müsste natürlich auch die Art des Structurfeldes erkennen:
Beispiel:

Code: Alles auswählen

Structure worte
  wort1.s
  wort2.s
  wort3.s
EndStructure
Define a.worte
Define satz.s

a\wort1 = "Test1"
a\wort2 = "Test2"
a\wort3 = "Test3"

; Version 1 : Alles einzeln Zusammenfügen
satz = a\wort1 +Chr(30)
satz + a\wort2 +Chr(30)
satz + a\wort3 +Chr(30)
Debug satz

; Version 2 : Alles durch eine Schleife zusammenfügen
satz = ""
For i = 1 To anzahl_structurefelder
  If structurefeld = interger
    ;satz + Str(a\structurefeld_i)
  ElseIf structurefeld = float
    ;satz + StrF(a\structurefeld_i)
  Else
    ;satz + a\structurefeld_i 
  endif
  satz + Chr(30)
Next
Debug satz
Und ausserdem ginge mir in Eurem Beispiel ja die Übersichtlichkeit der Namensgebung verloren.
"a\feldname"

Gruß: bernd
PB 5.31 (x86) & (x64) Win10
BSP
Beiträge: 203
Registriert: 01.02.2009 14:04

Re: nummer eines structurefeldes

Beitrag von BSP »

Und noch ein PS an Nick.
Dein Beispiel mit dem Pointer geht schon gut in meine Gedachte Richtung.
Wir hatten uns beim schreiben gerade überschnitten, deshalb meine nachgesetzte Antwort/Frage.

Gibt es noch eine Möglichkeit die Art des Feldes zu erkennen?

Gruß: Bernd
PB 5.31 (x86) & (x64) Win10
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8838
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: nummer eines structurefeldes

Beitrag von NicTheQuick »

Tja, das geht aber leider nicht so einfach. Ich habe so etwas ähnliches mal programmiert um ganze Structures über's Netzwerk zu senden oder in Dateien zu schreiben oder daraus zu lesen. Damit das klappt, hatte ich neben der eigentlichen Structure noch einen String, der sozusagen die Structure in einfachen Buchstaben darstellte und gleichzeitig zu den Structurefeldern in einer Schleife durchlaufen wurde. So wusste man wie viele Bytes man pro Feld weiter gehen musste und wie man es ausliest. Der Thread dazu ist hier: Write-, ReadStructure (3. Update)
Aber es ist in PureBasic nicht vorgesehen über Structure-Felder zu iterieren, die verschiedene Typen haben. Das müsste dann ja schon zur Übersetzungszeit geschehen, weil zur Laufzeit dein Programm nichts mehr von Structures weiß. Die wurden bis dahin "klein"-kompiliert.
BSP
Beiträge: 203
Registriert: 01.02.2009 14:04

Re: nummer eines structurefeldes

Beitrag von BSP »

@Nick.
hm, ok. Mal nachgrübeln.
Dann werde ich wohl meine komplette structure als Strings machen, auch die Zahlen.
Und dann Dein Beispiel mit SizeOf verwenden.
Ich habe mir Deine Beispiele mal kurz angesehen. (Aber noch nicht alles verstanden).
Und ob ich das sooo kompliziert brauche, denke ich nicht. Smile.
Es geht mir darum, den Datensatz schnell zusammen zu fügen.
Zum Abspeichern oder für vergleichszwecke, ob >etwas< geändert wurde.
Innerhalb des Programms ist es ja gerade ein wertvoller vorteil,
alles schön als wiedererkennbaren namen vorliegen zu haben.
a\der_eine_name
a\der_andere_name
a\und_ein_wert
usw.

Nachteile von "alles als String" ist sicherlich ein etwas grösserer speicherverbrauch und das man zahlen zur Berechnung immer erst mal umwandeln muss.
Aber das ist bei den heutigen Rechnern sicher kein so grosses Problem mehr.
Der Vorteil wäre, grössere Flexibilität im hinblick auf spätere Erweiterungen der Structure.
Ich müsste sonst später vieleicht in mehreren Proceduren Änderungen vornehmen.
Wenn ich alles in einer Schleife zusammenfüge, muss ich das nicht.
Ausser dann beim wieder zurück schreiben.
Vom Datensatz in die Structure.
Na, mal überlegen.

Jedenfalls Gruß & Dank:
Bernd
PB 5.31 (x86) & (x64) Win10
Benutzeravatar
STARGÅTE
Kommando SG1
Beiträge: 7039
Registriert: 01.11.2005 13:34
Wohnort: Glienicke
Kontaktdaten:

Re: nummer eines structurefeldes

Beitrag von STARGÅTE »

Hier mal ein etwas komplexeres Beispiel, welches sowas wie Klassen und Methoden benutzt.
Am Anfang definiere ich mir alle möglichen Komponenten die ein Satz haben kann (z.B. Text und Nummer).
Danach definiere ich mir Funktionen zum Hinzufügen und Ausgeben von Komponenten eines Satzes (Block).
Am Ende werden die Satzteile dynamisch zu einem Satz zusammen gebaut, und die Ausgabe des Satzes erfolgt dann über die jeweiligen Methoden, wie eine Komponente zu einem String verarbeitet werden soll.

Code: Alles auswählen

Prototype.s GetItem(*Head)

Structure Head
	Get.GetItem
EndStructure

Structure Text Extends Head
	String.s
EndStructure

Structure Number Extends Head
	Float.f
EndStructure

Structure Block
	List *Item.Head()
EndStructure

Global NewList Text.Text()
Global NewList Number.Number()


Procedure.s GetText(*Text.Text)
	ProcedureReturn *Text\String
EndProcedure

Procedure.s AddText(*Block.Block, String.s)
	AddElement(*Block\Item())
	*Block\Item() = AddElement(Text())
	Text()\Get = @GetText()
	Text()\String   = String
EndProcedure

Procedure.s GetNumber(*Number.Number)
	ProcedureReturn StrF(*Number\Float)
EndProcedure

Procedure.s AddNumber(*Block.Block, Float.f)
	AddElement(*Block\Item())
	*Block\Item() = AddElement(Number())
	Number()\Get = @GetNumber()
	Number()\Float = Float
EndProcedure


Define MyBlock.Block

AddText(MyBlock, "Heute werden es ")
AddNumber(MyBlock, 30.5)
AddText(MyBlock, "°C und es regnet mit einer Wahrscheinlichkeit von ")
AddNumber(MyBlock, 5.25)
AddText(MyBlock, "%.")

Define Output.s
ForEach MyBlock\Item()
	Output + MyBlock\Item()\Get(MyBlock\Item())
Next
Debug Output
PB 6.01 ― Win 10, 21H2 ― Ryzen 9 3900X, 32 GB ― NVIDIA GeForce RTX 3080 ― Vivaldi 6.0 ― www.unionbytes.de
Aktuelles Projekt: Lizard - Skriptsprache für symbolische Berechnungen und mehr
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8838
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: nummer eines structurefeldes

Beitrag von NicTheQuick »

BSP hat geschrieben:@Nick.
hm, ok. Mal nachgrübeln.
Dann werde ich wohl meine komplette structure als Strings machen, auch die Zahlen.
Und dann Dein Beispiel mit SizeOf verwenden.
<snip>
Nachteile von "alles als String" ist sicherlich ein etwas grösserer speicherverbrauch und das man zahlen zur Berechnung immer erst mal umwandeln muss.
Aber das ist bei den heutigen Rechnern sicher kein so grosses Problem mehr.
Der Vorteil wäre, grössere Flexibilität im hinblick auf spätere Erweiterungen der Structure.
Ich müsste sonst später vieleicht in mehreren Proceduren Änderungen vornehmen.
Wenn ich alles in einer Schleife zusammenfüge, muss ich das nicht.
Ausser dann beim wieder zurück schreiben.
Vom Datensatz in die Structure.
Na, mal überlegen.
Nein, mach das bitte nicht, also überall Strings verwenden. Das ist Quatsch. So programmiert man nicht. Man nutzt für alles den richtigen Datentyp und speichert ihn auch so. Konvertierungen zwischen Strings und Zahlenvariablen sind ellenlangsam und ungenau, z.B. bei Fließkommazahlen, wenn man nicht aufpasst.
Bei imperativen Programmiersprachen wie PureBasic ist es nun mal meist komplizierter wie in objektorientierten Sprachen. Aber da kann man dann ohne viele Tricks nicht viel dagegen machen und muss halt damit leben seine Procedures auch mal anzupassen, wenn sich eine Structure ändert. Aber wenn du alles schön hierarchisch aufbaust, solltest du da kaum Probleme mit haben.
Benutzeravatar
KeyKon
Beiträge: 1412
Registriert: 10.09.2004 20:51
Computerausstattung: Laptop: i5 2,8 Ghz, 16GB DDR3 RAM, GeForce 555GT 2GB VRAM
PC: i7 4,3 Ghz, 32GB DDR3 RAM, GeForce 680 GTX 4GB VRAM
Win10 x64 Home/Prof
PB 5.30 (64bit)
Wohnort: Ansbach
Kontaktdaten:

Re: nummer eines structurefeldes

Beitrag von KeyKon »

Eine weitere Möglichkeit, wenn keine Strings dabei sind.
Es ist allerdings möglich fixed Strings zu nutzen, das würde ich aber wirklich nur empfehlen wenn die Länger der Strings ziemlich genau bekannt ist, sonst ist das einfach Platzverschwendung:

Code: Alles auswählen

EnableExplicit

Structure struc
  long.l
  word.w
  float.f
  string.s{10}
  quad.q
EndStructure


Define var.struc


CompilerIf 0 ;Schreiben
  
  var\long = 11
  var\word = 12
  var\float = 13.13
  var\string = "Vierzehn"
  var\quad = 15
  
  
  If Not CreateFile(0,"D:\testfile")
    End
  EndIf
  WriteData(0,@var,SizeOf(struc))
  CloseFile(0)
  
CompilerElse ;Lesen
  
  If Not ReadFile(0,"D:\testfile")
    End
  EndIf
  ReadData(0,@var,SizeOf(struc))
  CloseFile(0)
  
  Debug var\long
  Debug var\word
  Debug var\float
  Debug var\string
  Debug var\quad
  
CompilerEndIf
(\/) (°,,,°) (\/)
Antworten