Passing fixed length string array to function
#1
Forgive me if this is an obvious issue, but...this is the first time I recall encountering it.

While using the function that I posted at: https://staging.qb64phoenix.com/showthread.php?tid=657

I tried the following bit of code as a set up for it, from a larger subroutine:

    ...
    REDIM ss(8) AS STRING * 8
    ss(1) = "1:Ia": ss(2) = "2:Ib": ss(3) = "3:II": ss(4) = "4:III"
    ss(5) = "5:IV": ss(6) = "6:V": ss(7) = "7:VI": ss(8) = "8Big Grin" ' <<<colon D throws the smilie... dwarf stars are happy bastards.
    SELECT CASE specindex
        CASE IS > 50
            DIM m AS _MEM: m = _MEM(ss): MemSmush m, 5: _MEMFREE m 'removes 5th element by copying upper ones down over it
            REDIM _PRESERVE ss(UBOUND(ss) - 1) AS STRING * 8
            ss(0) = "1234678"
        CASE IS <= 34
            DIM m1 AS _MEM: m1 = _MEM(ss): MemSmush m1, 7: _MEMFREE m1 'removes the 7th ""    """  """
            REDIM _PRESERVE ss(UBOUND(ss) - 1) AS STRING * 8
            ss(0) = "1234568"
        CASE ELSE
            ss(0) = "12345678"
    END SELECT
    ch% = Chs_Key_Button(ss(0), "h", 540, UBOUND(ss), 50, 50, 5, scrw / 2, ss()) ' <<<This last parameter is the issue
    ...

The idea of this is to filter out certain stellar size choices that don't occur with certain spectral classes (passed by specindex), if anyone is wondering the purpose of it all. The "MemSmush" sub copies all array elements above its second parameter down over that element, and zeros out the uppermost element, saving having to iterate through the array, which is why I opted for a fixed length string array in this instance.

The IDE says 'incorrect array type passed to function on current line' and references the last one shown, i.e. 'ch% = Chs_Key_...'
I've used non-fixed length string arrays with no issues and even did so here with an earlier defined one, in lieu of ss(), which it accepted. Is there a problem passing a fixed length string array to a function? Am I just forgetting some minor syntatic etiquette or what?

I could just load a variable length array in each CASE differently with no more typed code, but it seems a rather clumsy fallback position.

Thanks for looking.
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#2
I'm thinking it's a type mismatch issue. Try this:

DIM a(10) AS STRING * 8

foo a()

SUB foo (a() AS STRING)
END SUB

One is variable length, the other is fixed length, and I'm not 100% certain they'll pass back and forth with that difference between them.
Reply
#3
Thanks Steve,
I tried it and it screwed up all the other places where I used variable strings. It's just down to the limits of my function I guess.
I replaced it with the clumsy solution which worked fine. Chalk one up to experience.

    REDIM ss$(8)
    SELECT CASE specindex
        CASE IS > 50
            ss$(0) = "1234567"
            ss$(1) = "1:Ia": ss$(2) = "2:Ib": ss$(3) = "3:II": ss$(4) = "4:III"
            ss$(5) = "5:V": ss$(6) = "6:VI": ss$(7) = "7Big Grin"
            REDIM _PRESERVE ss$(UBOUND(ss$) - 1)
        CASE IS <= 34
            ss$(0) = "1234567"
            ss$(1) = "1:Ia": ss$(2) = "2:Ib": ss$(3) = "3:II": ss$(4) = "4:III"
            ss$(5) = "5:IV": ss$(6) = "6:V": ss$(7) = "8Big Grin"
            REDIM _PRESERVE ss$(UBOUND(ss$) - 1)
        CASE ELSE
            ss$(0) = "12345678"
            ss$(1) = "1:Ia": ss$(2) = "2:Ib": ss$(3) = "3:II": ss$(4) = "4:III"
            ss$(5) = "5:IV": ss$(6) = "6:V": ss$(7) = "7:VI": ss$(8) = "8Big Grin"
    END SELECT
    hvns(var).siz = _TRIM$(MID$(ss$(Chs_Key_Button(_TRIM$(ss$(0)), "h", 540, UBOUND(ss$), 50, 50, 5, scrw / 2, ss$())), 3))

At least my code seems much happier Big Grin
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#4
You can always insert it into a [code] block.  Just:

[code]
your code next...
]/code[   (Without reversing the brackets as I've done here so as to not actually create a code block.  Wink
Reply
#5
I'm guessing that what you're trying to do with STRING * 8 is just make certain to properly align the data?

If so, try something like this:

Code: (Select All)
Dim ss(8) As String
ss(1) = "One"
ss(2) = "Two"
ss(3) = "Three"

Color 4, 1 'so we can see our spaces

For i = 1 To 8 'to right align the data
    temp$ = "        "
    Mid$(temp$, 9 - Len(ss(i))) = ss(i)
    ss(i) = temp$
Next


For i = 1 To 8
    Print ss(i)
Next

'reset the data
ss(1) = "One"
ss(2) = "Two"
ss(3) = "Three"


For i = 1 To 8 'to left align the data
    ss(i) = ss(i) + Space$(8 - Len(ss(i)))
Next


For i = 1 To 8
    Print ss(i)
Next
Reply
#6
I'll take a whack at it, but I didn't have the subs and functions to ref...

Code: (Select All)
REDIM ss(8) AS STRING * 8
ss(1) = "1:Ia": ss(2) = "2:Ib": ss(3) = "3:II": ss(4) = "4:III"
ss(5) = "5:IV": ss(6) = "6:V": ss(7) = "7:VI": ss(8) = "8:D"
SELECT CASE specindex
    CASE IS > 50
        DIM m AS _MEM: m = _MEM(ss)
        memsmush m, 5
        _MEMFREE m 'removes 5th element by copying upper ones down over it
        REDIM _PRESERVE ss(UBOUND(ss) - 1) AS STRING * 8
        ss(0) = "1234678"
    CASE IS <= 34
        DIM m1 AS _MEM: m1 = _MEM(ss): memsmush m1, 7: _MEMFREE m1 'removes the 7th ""    """  """
        REDIM _PRESERVE ss(UBOUND(ss) - 1) AS STRING * 8
        ss(0) = "1234568"
    CASE ELSE
        ss(0) = "12345678"
END SELECT

ch% = Chs_Key_Button("h", 540, UBOUND(ss), 50, 50, 5, scrw / 2, ss()) ' <<<This last parameter is the issue
SUB memsmush (m AS _MEM, b)
END SUB

FUNCTION Chs_Key_Button (h AS STRING, n1, ubss, n2, n3, n4, n5, ss() AS STRING * 8)
END FUNCTION
Reply
#7
(08-25-2022, 04:16 AM)SMcNeill Wrote: I'm guessing that what you're trying to do with STRING * 8 is just make certain to properly align the data? 




It was for the _MEM sub mainly, which was simply



Code: (Select All)
SUB MemSmush (m AS _MEM, x%) '                                  move array elements above x% down over x%. Fill uppermost with null
    _MEMCOPY m, m.OFFSET + (m.ELEMENTSIZE * (x% + 1)), m.SIZE - (m.ELEMENTSIZE * (x% + 1)) TO m, m.OFFSET + (m.ELEMENTSIZE * x%)
    _MEMFILL m, m.OFFSET + m.ELEMENTSIZE * ((m.SIZE / m.ELEMENTSIZE) - 1), m.ELEMENTSIZE, 0 AS _BYTE
END SUB




Kind of like yankin' a box out from under a stack of boxes. Just that the boxes have to be the same size for the mem commands to work. The whole point of that being to avoid unnecessary iterations to remove and pancake a series of array elements. I tried your "foo" example from earlier as a function and it behaved the same way. It's obvious that the IDE sees AS STRING and AS STRING * 8 as two different types and I just can't do that.
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#8
Thanks for looking Pete, and your solution I think is correct for this instance. The trouble is, when I tried it, it breaks it for a half dozen other instances in a 2000+ line program with layers of SUB/FUNCTION dependencies and an include of Spriggsy's Pipecom. I thought that was a bit much to dump on you guys for a problem that was relatively simple to fix by sticking to the variable length string array. It wasn't that much more typing either, just a bit less self gratifying.

I didn't get to strut about the room crowing like a rooster while my family looked on in horror. Wink

I don't recall running into this issue before, but I haven't worked a lot with passing arrays to functions without them already being SHARED beforehand.
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply
#9
SUB MemSmush (m AS _MEM, x%) '                                  move array elements above x% down over x%. Fill uppermost with null
    _MEMCOPY m, m.OFFSET + (m.ELEMENTSIZE * (x% + 1)), m.SIZE - (m.ELEMENTSIZE * (x% + 1)) TO m, m.OFFSET + (m.ELEMENTSIZE * x%)
    _MEMFILL m, m.OFFSET + m.ELEMENTSIZE * ((m.SIZE / m.ELEMENTSIZE) - 1), m.ELEMENTSIZE, 0 AS _BYTE
END SUB


Seems to me like this would be a mem routine where you could speed up the performance on it considerably, with just a little reworking of the math.  (This is a nice example of what I was talking about with the Optimizing Code section of my QB64 Bible.)


SUB MemSmush (m AS _MEM, x%) '                                  move array elements above x% down over x%. Fill uppermost with null
    DIM o AS _OFFSET
    o = (m.ELEMENTSIZE * x%)
    'Would not m.ELEMENTSIZE * (x% +1) be equivelant to (o + m.ELEMENTSIZE)?? <-- removes the multiplication from the math
    'And I just predistributed the minus to the -(o + m.ELEMENTSIZE) for after the second comma 

    _MEMCOPY m, m.OFFSET + o + m.ELEMENTSIZE), m.SIZE - o - m.ELEMENTSIZE TO m, m.OFFSET + o <-- 3 multiplication calculations less than previously used
    _MEMFILL m, m.OFFSET + m.ELEMENTSIZE * ((m.SIZE / m.ELEMENTSIZE) - 1), m.ELEMENTSIZE, 0 AS _BYTE
END SUB


Also seems to me that "m.ELEMENTSIZE * ((m.SIZE / m.ELEMENTSIZE) - 1)" could be simplified down some.

x * ((y / x) - 1)  (to simplify typing)
x* (y/x) - x  'distribute the x
y - x 'the x's cancel
y - x

Or, back to the original:   m.SIZE - m.ELEMENTSIZE

SUB MemSmush (m AS _MEM, x%) '                                  move array elements above x% down over x%. Fill uppermost with null
    DIM o AS _OFFSET
    o = (m.ELEMENTSIZE * x%) 'replace those two simple equations with a single variable to do the math once.
    'Would not m.ELEMENTSIZE * (x% +1) be equivelant to (o + m.ELEMENTSIZE)?? <-- removes the multiplication from the math
    'And I just predistributed the minus to the -(o + m.ELEMENTSIZE) for after the second comma 

    _MEMCOPY m, m.OFFSET + o + m.ELEMENTSIZE), m.SIZE - o - m.ELEMENTSIZE TO m, m.OFFSET + o '<-- 3 multiplication calculations and 1 negation less than previously used
    _MEMFILL m, m.OFFSET + m.SIZE - m.ELEMENTSIZE, m.ELEMENTSIZE, 0 AS _BYTE '<-- Removed multiplication and division operation
END SUB


Now, I don't have your whole program to swap things in to test it out with, but unless our math gurus see something which I've did wrong, I'd think that that final routine should be the exact same as the first one, except without it having to do a lot of the math calculations with those mem routines.  The final MemSmush should be quite a bit faster and more efficient than the original MemSmush you posted.  Wink
Reply
#10
Ooooo, that's outstanding! Thanks for the optimization. I'm so focused on the _MEM command thing that I'm not always seeing the broader picture.
DO: LOOP: DO: LOOP
sha_na_na_na_na_na_na_na_na_na:
Reply




Users browsing this thread: 3 Guest(s)