## Returning Arrays

General FreeBASIC programming questions.
dodicat
Posts: 6690
Joined: Jan 10, 2006 20:30
Location: Scotland

### Re: Returning Arrays

Using macros can make your code general.
Here is an example of a general arrayinsert/arraydelete for a udt via macros.
Please note, the whole udt is transferred, i.e. all the fields at once.
To show the results, as before, stipulate the fields.
(If you want to be generic, it is either macros or overloaded procedures, I would say!)

Code: Select all

`type udt    as single f    as zstring * 30 stend typetype array    as any ptr p(any)end type#define value(U,datatype,UDT_Field) *cast(datatype ptr,u.p(n)) UDT_Field#macro show(u,datatype,UDT_Field)print #datatype; #UDT_field    for n as long=lbound(u.p) to ubound(u.p)        print value(u,datatype,UDT_Field);" ";    next    print#endmacro#macro transfer(u,a)redim (u.p)(lbound(a) to ubound(a)) as typeof(a)    for z as long=lbound(a) to ubound(a)        u.p(z)=@a(z)    next#endmacro#macro arrayinsert(a,index,insert)If index>=Lbound(a) And index<=Ubound(a)+1 Then    Var index2=index-Lbound(a)    Redim Preserve a(Lbound(a) To  Ubound(a)+1)    For x As Integer= Ubound(a) To Lbound(a)+index2+1 Step -1        Swap a(x),a(x-1)    Next x    a(Lbound(a)+index2)=insertEnd If#endmacro#macro arraydelete(a,index)If index>=Lbound(a) And index<=Ubound(a) Then    For x As Integer=index To Ubound(a)-1        a(x)=a(x+1)    Next x    Redim Preserve a(Lbound(a) To Ubound(a)-1)End If #endmacrodim as double d(...)={1.5,2.5,3.5}dim as long L(...)={1,2,3,4,5,6,7,8,9,0}dim as string s(...)={"Free","BASIC"}redim as udt g(1 to 2)g(1)=type(13.3,"ABC")g(2)=type(14.4,"DEF")dim as array x(1 to 4)'fill up the array of pointerstransfer(x(1),d)transfer(x(2),l)transfer(x(3),s)transfer(x(4),g)'show the resultsshow(x(1),double,)show(x(2),long,)show(x(3),string,)show(x(4),udt,.f)show(x(4),udt,.st)print'use the insert/delete macros with the array of udt's (which was g into x(4))arrayinsert(g,1,type(99.9,"HELLO"))'transfer the new vaues and show themtransfer(x(4),g)show(x(4),udt,.f)show(x(4),udt,.st)arraydelete(g,2)'transfer the new vaues and show themtransfer(x(4),g)show(x(4),udt,.f)show(x(4),udt,.st)sleep `
grindstone
Posts: 752
Joined: May 05, 2015 5:35
Location: Germany

### Re: Returning Arrays

Only as a suggestion: What about a Union of all desired types?

Code: Select all

`Union universal   i As Integer   ui As UInteger   l As Long   ul As ULong   s As Single   d As Double   c As ZString*20   '...End UnionDim As universal valuevalue.i = 20? value.ivalue.d = 5.38? value.dvalue.c = "Hello"? value.cSleep`
Then the data type would be a component of the variable name, similar to the hungarian notation.
fxm
Posts: 9948
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

### Re: Returning Arrays

Around this topic:

Referring to my other topic How accessing to the array's descriptor structure?, we can get the address of the descriptor of any dynamic array, and then return this address from of a function in which the array has been created.

By the means of a Type containing a non-sized array, the initial array can be easily recovered from the function return (as a array field of an object pointed by the returned value), fully usable (with Redim [Preserve], L/Ubound, ...), and even duplicated into a pure array with few instructions only (2 lines).

Example (for 64-bit, compile with '-exx'):

Code: Select all

`Function arrayDescriptorPtrFunction (Byval p As Any Ptr) As Any Ptr  Return pEnd function#Define arrayDescriptorPtr(array) Cast(Function (() As Typeof((array))) As Any Ptr, @arrayDescriptorPtrFunction)(array())Function test () As Any Ptr  Static As Integer array(Any)  Function = arrayDescriptorPtr(array)  Redim array(-3 To +5)  For I As Integer = Lbound(array) To Ubound(array)    array(I) = I * 10  Next IEnd FunctionType UDT  Dim As Integer _array(Any)End TypeDim As UDT Ptr pu1 = test()For I As Integer = Lbound(pu1->_array) To Ubound(pu1->_array)  Print pu1->_array(I)Next IPrintDim As Integer array(Any)Dim As UDT Ptr pu2 = arrayDescriptorPtr(array)*pu2 = *pu1For I As Integer = Lbound(array) To Ubound(array)  Print array(I)Next ISleep`

Explaining notes:
- A Type containing a dynamic array contains a field which is in fact only the array descriptor (similarly to a var-len string field).
- When a dynamic array is declared, even still non-sized, its descriptor is created immediately.
- In the above example, none UDT object has been created but only UDT-typed pointers to the existing array descriptors.
Last edited by fxm on May 19, 2017 15:56, edited 3 times in total.
fxm
Posts: 9948
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

### Re: Returning Arrays

I had thought of making a syntax challenge around the same principle as above, in order to copy an array in another in a global way, but I found it a little too hard!
(for 64-bit, compile with '-exx')

Code: Select all

`Function arrayDescriptorPtrFunction (Byval p As Any Ptr) As Any Ptr  Return pEnd function#Define arrayDescriptorPtr(array) Cast(Function (() As Typeof((array))) As Any Ptr, @arrayDescriptorPtrFunction)(array())Dim As Integer array1(Any)Redim array1(-3 To +5)For I As Integer = Lbound(array1) To Ubound(array1)  array1(I) = I * 10Next IFor I As Integer = Lbound(array1) To Ubound(array1)  Print array1(I)Next IPrintDim As Integer array2(Any)Type UDT  Dim As Integer array(Any)End TypeDim As UDT Ptr pu1 = arrayDescriptorPtr(array1)Dim As UDT Ptr pu2 = arrayDescriptorPtr(array2)*pu2 = *pu1For I As Integer = Lbound(array2) To Ubound(array2)  Print array2(I)Next ISleep`
Last edited by fxm on May 20, 2017 18:52, edited 4 times in total.
Tourist Trap
Posts: 2933
Joined: Jun 02, 2015 16:24

### Re: Returning Arrays

fxm wrote:I had thought of making a syntax challenge around the same principle as above, in order to copy an array in another in a global way, but I found it a little too hard!

It's between the too hard and the impossible.

By the way I'm not sure if it's me or something already corrected, or where I'm mistaken but after an array has been erased it seems to me quite weird that in some cases we still can evaluate array(0). I've posted there an example, in some other context, but the things are the same in general (no this is only in byref context, I was mistaken, but still weird):
viewtopic.php?p=229018#p229018
dodicat
Posts: 6690
Joined: Jan 10, 2006 20:30
Location: Scotland

### Re: Returning Arrays

The use of the ANY keyword with arrays seems strange.
truths and falsehoods seem not to pan out, as in politics.

Code: Select all

`dim as boolean a(1 to 300)=anydim as long nfor z as long=1 to 300    if a(z)=true then n+=1     print a(z);",";nextprintprintprint "Number of true results =  ";nprintfor z as long=1 to 300    print a(z);",";nextsleep  `
fxm
Posts: 9948
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

### Re: Returning Arrays

Code: Select all

`    if a(z) then n+=1  '' or: if a(z)<>false then n+=1`

The above behavior is not specific to array:

Code: Select all

`Dim As Boolean b = AnyPrint Cast(Byte, b)PrintPrint bIf b = True Then Print True Else Print FalseIf b Then Print True Else Print FalseIf b <> False Then Print True Else Print FalseSleep`