Seite 1 von 1
Prozedur mit beliebig vielen Argumenten? Möglich?
Verfasst: 12.01.2014 02:24
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.
Re: Prozedur mit beliebig vielen Argumenten? Möglich?
Verfasst: 12.01.2014 04:12
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...
Re: Prozedur mit beliebig vielen Argumenten? Möglich?
Verfasst: 12.01.2014 11:29
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)
Re: Prozedur mit beliebig vielen Argumenten? Möglich?
Verfasst: 12.01.2014 14:04
von Lambda
Einfach einen Pointer auf eine Struktur übergeben, ist meiner Meinung nach wesentlich sauberer.
Re: Prozedur mit beliebig vielen Argumenten? Möglich?
Verfasst: 12.01.2014 14:28
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()
Re: Prozedur mit beliebig vielen Argumenten? Möglich?
Verfasst: 12.01.2014 14:40
von ts-soft
Re: Prozedur mit beliebig vielen Argumenten? Möglich?
Verfasst: 12.01.2014 15:16
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())
Re: Prozedur mit beliebig vielen Argumenten? Möglich?
Verfasst: 12.01.2014 19:05
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.
Re: Prozedur mit beliebig vielen Argumenten? Möglich?
Verfasst: 12.01.2014 19:43
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())