Jagged Array UDT (macro-generable for any data-type)

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
fxm
Moderator
Posts: 12131
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Jagged Array UDT (macro-generable for any data-type)

Post by fxm »

A jagged (or ragged) array is an array of arrays of which the member arrays can be of different sizes and producing rows of jagged edges when visualized as output.
In contrast, a two-dimensional array is always rectangular.

The file 'jaggedarray.bi' below to include allows to macro-generate a Jagged Array UDT structure depending on the user Datatype:
  • - A constructor 'jaggedArrayDatatype(() As Integer)' allocates memory/datatype and sizes the instance ('array' for example), from a 1D array containing the number of columns for each row.
    - The syntax for accessing an element '(r, c)' of the jagged array is 'array[r][c]' ('array' being the constructed instance).
    - A destructor automatically frees the memory when the constructed instance is going out of scope.
'jaggedarray.bi':

Code: Select all

#macro jaggedArray(typename)

    #ifndef jaggedArray##typename

        Type jaggedArray_##typename
            Public:
                Declare Constructor (Byval size As Integer)
                Declare Operator [] (Byval index As Integer) Byref As typename
            Private:
            Dim As typename array(Any)
        End Type

        Constructor jaggedArray_##typename (Byval size As Integer)
            Redim This.array(size - 1)
        End Constructor

        Operator jaggedArray_##typename.[] (Byval index As Integer) Byref As typename
            Return This.array(index)
        End Operator

        Type jaggedArray##typename
            Public:
                Declare Constructor (size() As Integer)
                Declare Destructor ()
                Declare Operator [] (Byval index As Integer) Byref As jaggedArray_##typename
            Private:
                Dim As jaggedArray_##typename Ptr array(Any)
        End Type

        Constructor jaggedArray##typename (size() As Integer)
            Redim This.array(Ubound(size) - Lbound(size))
            For I As Integer = Lbound(size) To Ubound(size)
                This.array(I - Lbound(size)) = New jaggedArray_##typename(size(I))
            Next I
        End Constructor

        Destructor jaggedArray##typename ()
            For I As Integer = Lbound(This.array) To Ubound(This.array)
                Delete This.array(I)
            Next I
        End Destructor

        Operator jaggedArray##typename.[] (Byval index As Integer) Byref As jaggedArray_##typename
            Return *This.array(index)
        End Operator

    #endif

#endmacro
Example:
  • - Construct a jagged array of String of 3 rows:
    • - first row has 5 columns,
      - second row has 3 columns,
      - third row has 4 columns.
    - Initialize each element with a string of two digits containing its row index followed with its column index.
    - Check the values of all elements.
'main.bas':

Code: Select all

#include "jaggedarray.bi"

jaggedArray(String)

Dim As Integer size(...) = {5, 3, 4}
Dim As jaggedArrayString array = size()

For I As Integer = Lbound(size) To Ubound(size)
    For J As Integer = 0 To size(I) - 1
        array[I - Lbound(size)][J] = Str(I - Lbound(size)) & Str(J)
    Next J
Next I

For I As Integer = Lbound(size) To Ubound(size)
    For J As Integer = 0 To size(I) - 1
        Print array[I - Lbound(size)][J],
    Next J
    Print
Next I

Sleep
  • Output:

    Code: Select all

    00            01            02            03            04
    10            11            12
    20            21            22            23
    
Last edited by fxm on Jul 24, 2020 7:31, edited 3 times in total.
fxm
Moderator
Posts: 12131
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Jagged Array UDT (macro-generable for any data-type)

Post by fxm »

Other file 'jaggedarray.bi' to be included, full compatible with the previous, having shorter code (a single UDT and using memory allocation with NEWs instead of dynamic arrays), but there is no possibility of outbounds checking like with the first version (by compiling with '-exx').

'jaggedarray.bi' (version 2):

Code: Select all

#macro jaggedArray(typename)

    #ifndef jaggedArray##typename
    
        Type jaggedArray##typename
            Public:
                Declare Constructor (size() As Integer)
                Declare Destructor ()
                Declare Operator [] (Byval index As Integer) As typename Ptr
            Private:
                Dim As typename Ptr Ptr p
                Dim As Integer rowsize
        End Type

        Constructor jaggedArray##typename (size() As Integer)
            This.rowsize = Ubound(size) - Lbound(size) + 1
            This.p = New typename Ptr[rowsize]
            For I As Integer = 0 To rowsize - 1
                p[I] = New typename[size(I + Lbound(size))]
            Next I
        End Constructor

        Destructor jaggedArray##typename ()
            For I As Integer = 0 To This.rowsize - 1
                Delete p[I]
            Next I
            Delete p
        End Destructor

        Operator jaggedArray##typename.[] (Byval index As Integer) As typename Ptr
            Return This.p[index]
        End Operator

    #endif

#endmacro
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Jagged Array UDT (macro-generable for any data-type)

Post by dodicat »

Thank you fxm.
A minimalistic method.

Code: Select all

'======================
#macro set(datatype)
Type jagged##datatype
	As datatype a(Any)
End Type
#endmacro

#macro SetUp(_j_,_a_...)
Scope
    Var s= #_a_
    Dim As Long _c_,_i_=Instr(s,",")
    For n As Long=0 To Len(s)-1
        If s[n]=Asc(",") Then _c_+=1
    Next
    Redim _j_(1 To _c_+1)
    For n As Long=1 To _c_+1
        Redim (_j_(n).a)(1 To Val(s))
        s=Mid(s,_i_+1)
        _i_=Instr(s,",")
    Next n
End Scope
#endmacro

#define retrieve(_a_,_n1_,_n2_)  _a_(_n1_).a(_n2_)
#define setvalue(_a_,_n1_,_n2_,_v_)  _a_(_n1_).a(_n2_)=_v_
#define printout(_a_,_n1_,_n2_)  print _a_(_n1_).a(_n2_)
'=======================

set(String)
set(Double)

Redim As jaggedstring x()
SetUp(x,3,6,7,3,2,9,27)
Print "bounds"
For n As Long=Lbound(x) To Ubound(x)
    Print Lbound(x(n).a);"  to  ";Ubound(x(n).a)
Next
Print 
Print "Filled values"
For n As Long=Lbound(x) To Ubound(x)
    For m As Long=Lbound(x(n).a)To Ubound(x(n).a)
        setvalue(x,n,m,Chr(97+Rnd*25))
        printout(x,n,m);" ";
    Next m
    Print
Next n
Print
Print "get x(3,5)"
Print retrieve(x,3,5)
Print

'=====================
Redim As jaggeddouble z()
SetUp(z,2,3,1)
Print "bounds"
For n As Long=Lbound(z) To Ubound(z)
    Print Lbound(z(n).a);"  to  ";Ubound(z(n).a)
Next
Print
Print "Filled values"
For n As Long=Lbound(z) To Ubound(z)
    For m As Long= Lbound(z(n).a) To Ubound(z(n).a)
        setvalue(z,n,m,Sqr(n*m))
    Next m
Next n
Print
For n As Long=Lbound(z) To Ubound(z)
    For m As Long=Lbound(z(n).a)To Ubound(z(n).a)
        printout(z,n,m);" ";
    Next m
    Print
Next n
Print
Print "get z(2,2)^2"
Print retrieve(z,2,2)^2
Print
Print "press a key . . ."
Sleep

'====================
Type Circle
    As Long x,y,r
    As Ulong colour
End Type


set(Circle)

Redim As jaggedcircle c()
SetUp(c,1,2,3,4,5)
For n As Long=Lbound(c) To Ubound(c)
    For m As Long= Lbound(c(n).a) To Ubound(c(n).a)
        setvalue(c,n,m,Type(n*100,600-m*100,50,Rnd*Rgb(n*100,m*100,222-n*m)))
    Next m
Next n

Screen 19,32
For n As Long=Lbound(c) To Ubound(c)
    For m As Long= Lbound(c(n).a) To Ubound(c(n).a)
        Circle(retrieve(c,n,m).x,retrieve(c,n,m).y),retrieve(c,n,m).r,retrieve(c,n,m).colour,,,,f
    Next m
Next n
Sleep

 
Post Reply