Counting the number of elements in a dynamic array?

Started by Quin, July 20, 2024, 07:23:23 PM

Previous topic - Next topic

Quin

Quote from: MrBcx on July 21, 2024, 08:10:39 PM
Quote from: MrBcx on July 21, 2024, 05:58:29 PM
UPDATE:  The fix is in, regression tested, and will be included in 8.1.2

To my knowledge, the following has -NEVER- been possible in BCX. 
It compiles and and runs as it should in my beta copy of BCX 8.1.2

Godly, sir. Very looking forward to the next release then

MrBcx

Quote from: MrBcx on July 21, 2024, 05:58:29 PM
UPDATE:  The fix is in, regression tested, and will be included in 8.1.2

To my knowledge, the following has -NEVER- been possible in BCX. 
It compiles and and runs as it should in my beta copy of BCX 8.1.2



'*************************************************************
' For BCX version 8.1.2 and newer.  Example by MrBcx July 2024
' Demonstrates declaring, passing, and redimensioning a local
' array of User-Defined-Type inside a foreign SUB or FUNCTION.
'*************************************************************

CALL STEP_ONE()
PAUSE
END


SUB STEP_ONE

    TYPE UDTFOO
        a AS DOUBLE
        b AS INT
        c AS STRING
    END TYPE

    LOCAL DYNAMIC F[1] AS UDTFOO    ' This array is LOCAL to this SUB

    F[0].a = 1.123456789
    F[0].b = 2
    F[0].c = "Hello World"

    PRINT "These are our initial values:"
    PRINT F[0].a
    PRINT F[0].b
    PRINT F[0].c
    PRINT

    CALL STEP_TWO(F, UBOUND(F)) ' Pass info about our LOCAL array to another SUB

    PRINT
    PRINT "These were passed back from the SUB:"
    PRINT F[1].a ' newly added to the array
    PRINT F[1].b ' ditto
    PRINT F[1].c ' ditto
    PRINT
END SUB



SUB STEP_TWO (z[] AS UDTFOO, ub AS INT)
    PRINT "These were passed to SUB STEP_TWO"
    PRINT z[ub].a
    PRINT z[ub].b
    PRINT z[ub].c
    PRINT

    DIM RAW idx = ub + 1

    REDIM PRESERVE z[ub + 1] AS UDTFOO ' Now re-dimension the array passed in from SUB ONE()

    INPUT "Enter a DOUBLE:   ", z[idx].a
    INPUT "Enter an INTEGER: ", z[idx].b
    INPUT "Enter a STRING:   ", z[idx].c
END SUB





MrBcx

UPDATE:  The fix is in, regression tested, and will be included in 8.1.2

MrBcx

Referring to my last example, the following is a much simpler way of passing a
dynamically dimensioned array of UDT that can be REDIM'd inside a remote SUB
or FUNCTION without referencing the GLOBAL array variable explicitly.

DIM DYNAMIC F[1] AS UDTFOO

SUB TestUDT (z[] AS UDTFOO, ub AS INT)  ' z[] refers to F[]
    PRINT "These were passed to this SUB"
    PRINT z[ub].a
    PRINT z[ub].b
    PRINT z[ub].c
    PRINT

    DIM RAW idx = ub + 1

    REDIM PRESERVE z [ub + 1] AS UDTFOO ' Now re-dimension the UDT array that was passed by argument
   
    INPUT "Enter a DOUBLE:   ", z[idx].a
    INPUT "Enter an INTEGER: ", z[idx].b
    INPUT "Enter a STRING:   ", z[idx].c
END SUB


The problem is there's a BUG in BCX that's preventing the REDIM statement from being processed correctly.

If I comment out the REDIM PRESERVE statement and code it manually inline with what the REDIM PRESERVE
statement is -SUPPOSED- to produce,  everything works.

'  REDIM PRESERVE z[ub + 1] AS UDTFOO ' Now re-dimension the passed array

    !  size_t dimensions[1] = { (size_t)ub+1 };
    !  z = (UDTFOO*)CreateArr (z, sizeof(UDTFOO), 1, 1, dimensions);



This is probably more info than anyone was looking for, but it gives me a new homework assignment and
it shows again that one never knows where a bug might be hiding until it suddenly rears its ugly head at us.

Quin

In classic me style, I looked at your code, and that was enough to get the gears turning and get me to use a global set that just gets initialized once on program init :)
thanks for all the help as always!

MrBcx

Quote from: Quin on July 20, 2024, 09:52:29 PM
Kevin,
I have a UDT like so:

dim function get_val$()

type infobyte
    name as string
    func as get_val_TYPE
end type

And I have this in my formload sub:

    global dynamic infobytes[50] as infobyte
    add_infobyte("OS name", get_os_name)
    add_infobyte("OS version", get_os_version)
    for integer i = 0 to 50
        SendMessage(list_box, LB_ADDSTRING, 0, (LPARAM)infobyte_str(&infobytes[i]))
    next

add_infobyte is just a simple function that takes an infobyte ptr and ads it to the list. The part I'm stuck on is how to tell how many elements the infobytes array contains when inserting (e.g. what number do I pass to redim and what do I make the for loop cound to?).

UBOUND tells you how many cells are in your array and SIZEOF tells you how large each cell is in your array.


Here is an updated version of my previous example that shows how to pass and REDIM dynamic arrays of UDT's.

ChatGPT helped me out a bit. This subject gets tricky ...



TYPE UDTFOO
    a AS DOUBLE
    b AS INT
    c AS STRING
END TYPE

DIM DYNAMIC F[1] AS UDTFOO

F[0].a = 1.123456789
F[0].b = 2
F[0].c = "Hello World"

PRINT "These are our initial values:"
PRINT F[0].a
PRINT F[0].b
PRINT F[0].c
PRINT

CALL TestUDT (ADDRESSOF(F), UBOUND(F))

PRINT
PRINT "These were passed back from the SUB:"
PRINT F[1].a ' newly added to the array
PRINT F[1].b ' ditto
PRINT F[1].c ' ditto
PRINT
PAUSE


SUB TestUDT (z AS LPUDTFOO PTR, ub AS INT)
    DIM K AS UDTFOO
    DIM idx AS INT

    ' Reallocate the array to add one more element
    REDIM PRESERVE F[ub + 1] AS UDTFOO

    ' Get the index of the newly added element
    idx = ub + 1

    ' Copy the original UDTFOO to K
    COPY_UDT(z[0], ADDRESSOF(K), SIZEOF(UDTFOO))

    PRINT "These were passed to this SUB"
    PRINT K.a
    PRINT K.b
    PRINT K.c
    PRINT

    ' Get new values from user
    INPUT "Enter a DOUBLE:  ", K.a
    INPUT "Enter an INTEGER: ", K.b
    INPUT "Enter a STRING:  ", K.c

    ' Copy the modified UDTFOO back to the newly added element in the array
    COPY_UDT(ADDRESSOF(K), ADDRESSOF(F[idx]), SIZEOF(UDTFOO))
END SUB


SUB COPY_UDT (Source AS PVOID, Destination AS PVOID, Count AS INT)
    POKE(Destination, PEEK$(Source, Count), Count)
END SUB








Quin

Kevin,
I have a UDT like so:

dim function get_val$()

type infobyte
    name as string
    func as get_val_TYPE
end type

And I have this in my formload sub:

    global dynamic infobytes[50] as infobyte
    add_infobyte("OS name", get_os_name)
    add_infobyte("OS version", get_os_version)
    for integer i = 0 to 50
        SendMessage(list_box, LB_ADDSTRING, 0, (LPARAM)infobyte_str(&infobytes[i]))
    next

add_infobyte is just a simple function that takes an infobyte ptr and ads it to the list. The part I'm stuck on is how to tell how many elements the infobytes array contains when inserting (e.g. what number do I pass to redim and what do I make the for loop cound to?).

MrBcx

Quin,

Providing a skeleton that shows what you're trying to do might help, even if it can't compile yet.

To answer one of your questions, SIZEOF can be used to get the size of a data object, including UDTs.


Here is one of my personal snippets that might provide some ideas:



TYPE UDTFOO
   a AS DOUBLE
   b AS INT
   c AS STRING
END TYPE

DIM F AS UDTFOO

F.a = 1.123456789
F.b = 2
F.c = "Hello World"

PRINT "These are our initial values:"
PRINT F.a
PRINT F.b
PRINT F.c
PRINT

CALL TestUDT (ADDRESSOF(F))

PRINT
PRINT "These were passed back from the SUB:"
PRINT F.a
PRINT F.b
PRINT F.c
PRINT


SUB TestUDT (z AS LPUDTFOO)
   DIM K AS UDTFOO

   COPY_UDT(z, ADDRESSOF(K), SIZEOF(UDTFOO))

   PRINT "These were passed to this SUB"
   PRINT K.a
   PRINT K.b
   PRINT K.c
   PRINT

   INPUT "Enter a DOUBLE:  ", K.a
   INPUT "Enter a INTEGER: ", K.b
   INPUT "Enter a STRING:  ", K.c

   COPY_UDT(ADDRESSOF(K), z, SIZEOF(UDTFOO))
END SUB


SUB COPY_UDT (Source AS PVOID, Destination AS PVOID, Count AS INT)
   POKE(Destination, PEEK$(Source, Count), Count)
END SUB




Quin

In my app, I need to have a dynamic array of user-defined types. I'm trying to add a subroutine to my app that adds one, like sub add_to_list(name as string, func_ptr as callback_TYPE). However, I can't figure out how to resize the array and push my new element onto it. I can resize them just fine with redim, but how do I actually get the size to resize it to?

Sorry for all the seemingly newbish questions, I thought I knew how to program...  ;D