Prozedur mit beliebig vielen Argumenten? Möglich?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Benutzeravatar
N_Gnom
Beiträge: 149
Registriert: 11.09.2013 19:52

Prozedur mit beliebig vielen Argumenten? Möglich?

Beitrag von N_Gnom »

Ist es möglich eine Prozedur zu erstellen der man Argumente übergeben kann, deren Anzahl beliebig ist?
Also ProcedureFoo(para1, para2, para3 ...) und diese müssten dann bei Vorhandensein in der Prozedur verarbeitet werden.

Aber bei der Prozedurdefinition weiß ich im voraus nicht wieviele Argumente dann übergeben werden.
Erst beim benutzen dieser.

Hoffe ich habs nicht zu schwer erklärt.
Wie in einem Ordner bei dem ich beim Öffnen des Ordners festlege wieviele Blätter ich einheften und abarbeiten will.

Ich weiß ich könnte eine Liste im Vorfeld erstellen und diese dann in die Prozedur übernehmen und abarbeiten lassen, jedoch würde ich dies gern anders machen.
Laptop: Win10@64bit - i3 2x2Ghz - 8GB Ram - 1TB HDD
Desktop: Win10@64bit - AMD Ryzen 5 2400G - MSI B450 Tomahawk - 8GB Ram - 240GB SSD
Benutzeravatar
mk-soft
Beiträge: 3902
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Prozedur mit beliebig vielen Argumenten? Möglich?

Beitrag von mk-soft »

In prinzip nicht da Purebasic nicht wie "C" arbeiten.

Hatte aber eine alternative vor ewigkeiten mal geschrieben. Sind Max 11 Parameter möglich.

http://www.purebasic.fr/german/viewtopi ... =8&t=13008

An sonsten mit den Parametertype Variant arbeiten...
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
Bisonte
Beiträge: 2476
Registriert: 01.04.2007 20:18

Re: Prozedur mit beliebig vielen Argumenten? Möglich?

Beitrag von Bisonte »

Wenn alle Parameter den gleichen Typ haben (Integer z.B.), dann könnte man doch einfach

Code: Alles auswählen

Procedure Foo(Array Params(1))
  Debug "Parameter Anzahl : " + ArraySize(Params())
EndProcedure
oder nicht ?
(Wobei man am Ende der Prozedur das übergebene Array auch vernichten könnte, damit keine "Reste" beim
nächsten Aufruf überbleiben)
PureBasic 6.21 (Windows x86/x64) | Windows11 Pro x64 | AsRock B850 Steel Legend Wifi | R7 9800x3D | 64GB RAM | GeForce RTX 5080 | ThermaltakeView 270 TG ARGB | build by vannicom​​
Lambda
Beiträge: 526
Registriert: 16.06.2011 14:38

Re: Prozedur mit beliebig vielen Argumenten? Möglich?

Beitrag von Lambda »

Einfach einen Pointer auf eine Struktur übergeben, ist meiner Meinung nach wesentlich sauberer.
Derren
Beiträge: 558
Registriert: 23.07.2011 02:08

Re: Prozedur mit beliebig vielen Argumenten? Möglich?

Beitrag von Derren »

@Alexi: Bräuchtest du dazu nicht eine Struktur mit unendlich vielen Feldern?
Bisonte hat geschrieben:Wenn alle Parameter den gleichen Typ haben (Integer z.B.), dann könnte man doch einfach

Code: Alles auswählen

Procedure Foo(Array Params(1))
  Debug "Parameter Anzahl : " + ArraySize(Params())
EndProcedure
oder nicht ?
(Wobei man am Ende der Prozedur das übergebene Array auch vernichten könnte, damit keine "Reste" beim
nächsten Aufruf überbleiben)
Geht auch mit beliebigen Parametern. Man braucht nur die entsprechende Struktur.

Hab hier mal schnell zwei verschiedene Möglichkeiten (auf die schnelle, geht alles eleganter, verbraucht garantiert Speicher ohne Ende, falls man es überhaupt mehrmals ausführen kann ohne dass sich die Listen und Array stören, aber soll ja nur ein Denkanstoß sein)

Code: Alles auswählen

Enumeration 1
  #paramType_String
  #paramType_Integer
  #paramType_Float
EndEnumeration 

Structure paramTypes
  type.i
  string.s
  integer.i
  float.f
EndStructure 


Procedure myProc(Array parameter.paramTypes(1))
  Protected numberOfParams = ArraySize(parameter())
  Protected k, sumInteger
  Protected sumFloat.f
  Protected strings.s
  
  For k = 0 To numberOfParams
    Select parameter(k)\type
      Case #paramType_String
        strings = strings + parameter(k)\string + ", "
      Case #paramType_Integer
        sumInteger + parameter(k)\integer
      Case #paramType_Float
        sumFloat + parameter(k)\float
    EndSelect 
  Next 
  
  Debug strings
  Debug sumInteger
  Debug sumFloat  
EndProcedure 


Dim myArray.paramTypes(5)

myArray(0)\type = #paramType_String
myArray(0)\string = "Param1"

myArray(1)\type = #paramType_Float
myArray(1)\float = 0.1

myArray(2)\type = #paramType_Integer
myArray(2)\integer = 7

myArray(3)\type = #paramType_String
myArray(3)\string = "Param2"

myArray(4)\type = #paramType_Float
myArray(4)\float = 0.3

myArray(5)\type = #paramType_Integer
myArray(5)\integer = 9


myProc(myArray())




Leider kann man keine Doppelpunkte in den Macroargumenten benutzen, deswegen der umständliche Weg mit myProc und EndMyProc...

Code: Alles auswählen

Macro bla(foo)
  foo
EndMacro 

bla(a=1 : b=2) ;Syntax Error :(
Debug a+b

Code: Alles auswählen

Enumeration 1
  #paramType_String
  #paramType_Integer
  #paramType_Float
EndEnumeration 

Structure paramTypes
  type.i
  string.s
  integer.i
  float.f
EndStructure 


Procedure myProc(List parameter.paramTypes())
  
  Protected sumInteger.i
  Protected strings.s
  Protected sumFloat.f
  ResetList(parameter())
  While NextElement(parameter())    
    Select parameter()\type
      Case #paramType_String
        strings = strings + parameter()\string + ", "
      Case #paramType_Integer
        sumInteger + parameter()\integer
      Case #paramType_Float
        sumFloat + parameter()\float
    EndSelect 
  Wend  
  
  Debug strings
  Debug sumInteger
  Debug sumFloat  
EndProcedure 





Macro myString(__string)
  AddElement(myList())
  myList()\type = #paramType_String
  myList()\string = __string
EndMacro 

Macro myInteger(__integer)
  AddElement(myList())
  myList()\type = #paramType_Integer
  myList()\integer = __integer
EndMacro 

Macro myFloat(__float)
  AddElement(myList())
  myList()\type = #paramType_Float
  myList()\float = __float
EndMacro 
  


Macro _myProc()
  NewList myList.paramTypes()  
EndMacro 

Macro _EndMyProc()
  myProc(myList())
EndMacro 


_myProc()
myString("Hallo"): myString("Welt"): myInteger(1): myInteger(9): myFloat(0.5)
_EndMyProc()
  
Signatur und so
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Prozedur mit beliebig vielen Argumenten? Möglich?

Beitrag von ts-soft »

PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8837
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: Prozedur mit beliebig vielen Argumenten? Möglich?

Beitrag von NicTheQuick »

@ts-soft:
Jetzt wollte ich deinen Code noch etwas vereinfachen, und was passiert? Ich hab mal wieder einen Bug gefunden:

Code: Alles auswählen

Debug "#PB_Word = " + #PB_Word	
Debug "#PB_Structure = " + #PB_Structure
Define.w word
Debug "TypeOf(word) = " + TypeOf(word)
Nichtsdestotrotz hier der einfachere Code:

Code: Alles auswählen

;==================================================================
; ###  Example to use variable parameters for Procedures    ###
; Author:            Thomas <ts-soft> Schulz & <NicTheQuick>
; Date:              Mrz 16, 2012
; Version:           1.1
; Target OS:         All
; Target Compiler:   PureBasic 5.10 and later
;==================================================================

EnableExplicit

Structure V_ARG
	Type.l
	StructureUnion
		a.a
		b.b
		c.c
		d.d
		f.f
		i.i
		l.l
		q.q
		u.u
		w.w
	EndStructureUnion
	s.s
EndStructure

Procedure V_ARG_Add_(Array V_ARG.V_ARG(1), Type.l, size.i, *value)
	Protected index = ArraySize(V_ARG())
	ReDim V_ARG(index + 1)
	
	With V_ARG(index)
		\Type = Type
		If (Type = #PB_String)
			\s = PeekS(*value)
		Else
			CopyMemory(*value, @V_ARG(index) + OffsetOf(V_ARG\a), size)
		EndIf
	EndWith
EndProcedure

Macro V_ARG_Add(v_arg, value)
	V_ARG_Add_(v_arg, TypeOf(value), SizeOf(value), @value)
EndMacro

; example
Procedure Foo(Array V_ARG.V_ARG(1))
	Protected i.i
	Protected count.i = ArraySize(V_ARG())
	Debug "Count of parameters: " + Str(count)
	Debug ""
	For i = 0 To count - 1
		With V_ARG(i)
			Debug \Type
			Select \Type
				Case #PB_Ascii
					Debug "Parameter " + Str(i + 1) + " = UByte, Value = " + Str(V_ARG(i)\a)
				Case #PB_Byte
					Debug "Parameter " + Str(i + 1) + " = Byte, Value = " + Str(V_ARG(i)\b)
				Case #PB_Character
					Debug "Parameter " + Str(i + 1) + " = Char, Value = " + Str(V_ARG(i)\c)
				Case #PB_Double
					Debug "Parameter " + Str(i + 1) + " = Double, Value = " + StrD(V_ARG(i)\d)
				Case #PB_Float
					Debug "Parameter " + Str(i + 1) + " = FLoat, Value = " + StrF(V_ARG(i)\f)
				Case #PB_Integer
					Debug "Parameter " + Str(i + 1) + " = Integer, Value = " + Str(V_ARG(i)\i)
				Case #PB_Long
					Debug "Parameter " + Str(i + 1) + " = Long, Value = " + Str(V_ARG(i)\l)
				Case #PB_Quad
					Debug "Parameter" + Str(i + 1) + " = Quad, Value = " + Str(V_ARG(i)\q)
				Case #PB_String
					Debug "Parameter " + Str(i + 1) + " = String, Value = " + V_ARG(i)\s
				Case #PB_Unicode
					Debug "Parameter " + Str(i + 1) + " = UWord, Value = " + Str(V_ARG(i)\u)
				Case #PB_Word
					Debug "Parameter " + Str(i + 1) + " = Word, Value = " + Str(V_ARG(i)\w)
			EndSelect
		EndWith
	Next
EndProcedure

Dim para_array.V_ARG(0)

Define Text.s
Text = "Feel the ..Pure.. Power"
V_ARG_Add(para_array(), Text)

Define pi.d = #PI
V_ARG_Add(para_array(), pi)

Define word.w = 65535
V_ARG_Add(para_array(), word)
V_ARG_Add(para_array(), word)

Foo(para_array())
Benutzeravatar
N_Gnom
Beiträge: 149
Registriert: 11.09.2013 19:52

Re: Prozedur mit beliebig vielen Argumenten? Möglich?

Beitrag von N_Gnom »

Vielen lieben dank, aber für mein Vorhaben ist das doch etwas zu überdimensioniert.
Das werd ich dann ein bisschen einfacher lösen.

Aber es ist immer wieder schön etwas dazuzulernen und überhaupt vielen dank an alle die ebenso gerne einfach mal helfen.
Laptop: Win10@64bit - i3 2x2Ghz - 8GB Ram - 1TB HDD
Desktop: Win10@64bit - AMD Ryzen 5 2400G - MSI B450 Tomahawk - 8GB Ram - 240GB SSD
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8837
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: Prozedur mit beliebig vielen Argumenten? Möglich?

Beitrag von NicTheQuick »

Durch einen Hinweis im englischen Forum, hab ich jetzt auch verstanden, warum da noch ein Fehler war. Wenn man eine Variable hat, die den selben Namen hat wie eine vorhandene Structure, dann gibt TypeOf() immer #PB_Structure zurück anstatt den Typ der gleichnamigen Variablen. Ich habe das jetzt durch einen CompilerError behoben, der ausgelöst wird, wenn man 'V_ARG_Add()' eine strukturierte Variable oder eben aus Versehen einen Strukturnamen übergibt.

Code: Alles auswählen

;==================================================================
; ###  Example to use variable parameters for Procedures    ###
; Author:            Thomas <ts-soft> Schulz & <NicTheQuick>
; Date:              Mrz 16, 2012
; Version:           1.1
; Target OS:         All
; Target Compiler:   PureBasic 5.10 and later
;==================================================================

EnableExplicit

Structure V_ARG
   Type.l
   StructureUnion
      a.a
      b.b
      c.c
      d.d
      f.f
      i.i
      l.l
      q.q
      u.u
      w.w
   EndStructureUnion
   s.s
EndStructure

Procedure V_ARG_Add_(Array V_ARG.V_ARG(1), Type.l, size.i, *value)
   Protected index = ArraySize(V_ARG())
   ReDim V_ARG(index + 1)
   
   With V_ARG(index)
      \Type = Type
      If (Type = #PB_String)
         \s = PeekS(*value)
      Else
         CopyMemory(*value, @V_ARG(index) + OffsetOf(V_ARG\a), size)
      EndIf
   EndWith
EndProcedure

Macro V_ARG_Add(v_arg, value)
CompilerIf TypeOf(value) = #PB_Structure
	CompilerError "The variable has no native type. This is not supported."
CompilerEndIf
   V_ARG_Add_(v_arg, TypeOf(value), SizeOf(value), @value)
EndMacro

; example
Procedure Foo(Array V_ARG.V_ARG(1))
   Protected i.i
   Protected count.i = ArraySize(V_ARG())
   Debug "Count of parameters: " + Str(count)
   Debug ""
   For i = 0 To count - 1
      With V_ARG(i)
         Debug \Type
         Select \Type
            Case #PB_Ascii
               Debug "Parameter " + Str(i + 1) + " = UByte, Value = " + Str(V_ARG(i)\a)
            Case #PB_Byte
               Debug "Parameter " + Str(i + 1) + " = Byte, Value = " + Str(V_ARG(i)\b)
            Case #PB_Character
               Debug "Parameter " + Str(i + 1) + " = Char, Value = " + Str(V_ARG(i)\c)
            Case #PB_Double
               Debug "Parameter " + Str(i + 1) + " = Double, Value = " + StrD(V_ARG(i)\d)
            Case #PB_Float
               Debug "Parameter " + Str(i + 1) + " = FLoat, Value = " + StrF(V_ARG(i)\f)
            Case #PB_Integer
               Debug "Parameter " + Str(i + 1) + " = Integer, Value = " + Str(V_ARG(i)\i)
            Case #PB_Long
               Debug "Parameter " + Str(i + 1) + " = Long, Value = " + Str(V_ARG(i)\l)
            Case #PB_Quad
               Debug "Parameter" + Str(i + 1) + " = Quad, Value = " + Str(V_ARG(i)\q)
            Case #PB_String
               Debug "Parameter " + Str(i + 1) + " = String, Value = " + V_ARG(i)\s
            Case #PB_Unicode
               Debug "Parameter " + Str(i + 1) + " = UWord, Value = " + Str(V_ARG(i)\u)
            Case #PB_Word
               Debug "Parameter " + Str(i + 1) + " = Word, Value = " + Str(V_ARG(i)\w)
         EndSelect
      EndWith
   Next
EndProcedure

Dim para_array.V_ARG(0)

Define Text.s
Text = "Feel the ..Pure.. Power"
V_ARG_Add(para_array(), Text)

Define pi.d = #PI
V_ARG_Add(para_array(), pi)

Define word1.w = 65535
V_ARG_Add(para_array(), word1)
V_ARG_Add(para_array(), word1)

Foo(para_array()) 
Antworten