SHARED Array values with SUBs and FUNCTIONs
#1
Hello All,

I usually use GOSUB for all my subroutines mainly because I'm comfortable with them and know how to use them. But there are times when I must be careful not to use the same variable names for loops when I inside a loop with the same name. For this reason, it seems SUBs and FUNCTIONs would help to prevent this problem. However, I don't know how to access ARRAYs created in the main code and SHARE it with SUBs and FUNCTIONs. I can find no examples in the WIKI.

Donald
Reply
#2
(06-22-2023, 02:39 AM)Donald Foster.. Wrote: Hello All,

I usually use GOSUB for all my subroutines mainly because I'm comfortable with them and know how to use them. But there are times when I must be careful not to use the same variable names for loops when I inside a loop with the same name. For this reason, it seems SUBs and FUNCTIONs would help to prevent this problem. However, I don't know how to access ARRAYs created in the main code and SHARE it with SUBs and FUNCTIONs. I can find no examples in the WIKI.

Donald
Go to TerryRitchie's Tutorial - Chapter 6. He gives examples and explain how GOSUBS and FUNCTIONS works. I went to the wiki today to find out about FUNCTIONS and I needed more than it provided. TerryRitchie helped out on that with his Tutorial. That's what I found out today. I hope this helps you out.
Reply
#3
@Donald Foster
all variables to functions and sub's are passed by reference, meaning that they can and likely will be modified by the sub or function
I hope that this simple example will make it clear, note that the variables in the sub's declaration don't need to be the same as the variable that you intend to pass to the sub
there are two ways that you can call a sub
call times2 (m())
and
times2 m()
I prefer the latter
Code: (Select All)

Dim As Long m(10)
Dim As Long i

For i = 0 To 10
m(i) = i
Next

times2 m()

For i = 0 To 10
Print "i = "; i, "m("; i; ") = "; m(i)
Next

Sub times2 (mtwo() As Long)
Dim As Long i, u, l ' this are local variables
l = LBound(mtwo)
u = UBound(mtwo)
For i = l To u
mtwo(i) = 2 * mtwo(i)
Next
End Sub
Reply
#4
A quick example of a Shared array declared in main code and how to pass an array out from a Function along with another value
Code: (Select All)
Dim Shared mySharedArray(1 To 20) As Long

For i = 1 To 20
    mySharedArray(i) = i * i
Next

ReDim out10(1 To 10) As Integer
first10Plus5 = first10squaresPlus&(5, out10())
For i = 1 To 10
    Print out10(i)
Next
Print "Total was: "; first10Plus5

Function first10squaresPlus& (X, outputFirst10() As Integer)
    For i = 1 To 10
        outputFirst10(i) = mySharedArray(i) + X
        tot& = tot& + outputFirst10(i)
    Next
    first10squaresPlus& = tot&
End Function
b = b + ...
Reply
#5
(06-22-2023, 03:48 AM)GareBear Wrote:
(06-22-2023, 02:39 AM)Donald Foster.. Wrote: Hello All,
I usually use GOSUB for all my subroutines mainly because I'm comfortable with them and know how to use them. But there are times when I must be careful not to use the same variable names for loops when I inside a loop with the same name. For this reason, it seems SUBs and FUNCTIONs would help to prevent this problem. However, I don't know how to access ARRAYs created in the main code and SHARE it with SUBs and FUNCTIONs. I can find no examples in the WIKI.
Donald
Go to TerryRitchie's Tutorial - Chapter 6. He gives examples and explain how GOSUBS and FUNCTIONS works. I went to the wiki today to find out about FUNCTIONS and I needed more than it provided. TerryRitchie helped out on that with his Tutorial. That's what I found out today. I hope this helps you out.
The lesson in the tutorial is located here: https://www.qb64tutorial.com/lesson6

The code below shows the many ways SUBs and FUNCTIONs can be used to pass values in and out:

Code: (Select All)

TYPE StarType '              definition of a star
    x AS INTEGER '            x coordinate
    y AS INTEGER '            y coordinate
END TYPE

DIM Star(100) AS StarType '  star array      (LOCAL to the main program level)
DIM s AS INTEGER '            generic counter  (LOCAL to the main program level)
DIM ScreenWidth AS INTEGER '  width of screen  (LOCAL to the main program level)
DIM ScreenHeight AS INTEGER ' height of screen (LOCAL to the main program level)

RANDOMIZE TIMER '            seed random number generator
ScreenWidth = 640 '          set screen width
ScreenHeight = 480 '          set screen height

'-----------------------------------------------------------------------------------
' A subroutine using GOSUB and a local array
GOSUB PopulateStars
PRINT UBOUND(Star); "stars created (array LOCAL at main program level using GOSUB)"
'-----------------------------------------------------------------------------------

'-----------------------------------------------------------------------------------
' A subroutine using SUB and an array passed by reference
Populate_Stars Star()
PRINT UBOUND(Star); "stars created (array passed by reference into SUB)"
'-----------------------------------------------------------------------------------

'-----------------------------------------------------------------------------------
' A subroutine using SUB and an array that has been SHARED
Populate__Stars
PRINT UBOUND(Star); "stars created (array SHARED in SUB)"
'-----------------------------------------------------------------------------------

'-----------------------------------------------------------------------------------
' A function using FUNCTION and an array passed by reference
PRINT Populate_and_count_Stars(Star()); "stars created (array passed by reference into FUNCTION)"
'-----------------------------------------------------------------------------------

'-----------------------------------------------------------------------------------
' A function using FUNCTION and an array that has been SHARED
PRINT Populate_and_count_Stars2; "stars created (array SHARED in FUNCTION)"
'-----------------------------------------------------------------------------------

END


'-----------------------------------------------------------------------------------
' Everything LOCAL to the main program level
'-----------------------------------------------------------------------------------
PopulateStars: ' subroutine to populate Star() array

FOR s = 1 TO UBOUND(Star) '                cycle through array
    Star(s).x = INT(RND * ScreenWidth) '  create random star coordinates
    Star(s).y = INT(RND * ScreenHeight)
NEXT s

RETURN '                                  return to next command statement
'-----------------------------------------------------------------------------------

'-----------------------------------------------------------------------------------
' An array passed into a subroutine by reference
'-----------------------------------------------------------------------------------
SUB Populate_Stars (Array() AS StarType)

    ' Any changes in Array() will be passed back to Star()
    ' Star() has been passed 'by reference' into Array()

    SHARED ScreenWidth AS INTEGER '  share the variable from main program level
    SHARED ScreenHeight AS INTEGER ' share the variable from main program level
    DIM s AS INTEGER '              generic counter (LOCAL to this subroutine)

    FOR s = 1 TO UBOUND(Array) '              cycle through array
        Array(s).x = INT(RND * ScreenWidth) ' create random star coordinates
        Array(s).y = INT(RND * ScreenHeight)
    NEXT s

END SUB '                                    return to next command statement
'-----------------------------------------------------------------------------------

'-----------------------------------------------------------------------------------
' A SHARED array from the main program level
'-----------------------------------------------------------------------------------
SUB Populate__Stars ()

    ' Any changes in Star() will be saved when subroutine exits

    SHARED ScreenWidth AS INTEGER '  share the variable from main program level
    SHARED ScreenHeight AS INTEGER ' share the variable from main program level
    SHARED Star() AS StarType '      share the array from the main program level
    DIM s AS INTEGER '              generic counter (LOCAL to this subroutine)

    FOR s = 1 TO UBOUND(Star) '              cycle through array
        Star(s).x = INT(RND * ScreenWidth) ' create random star coordinates
        Star(s).y = INT(RND * ScreenHeight)
    NEXT s

END SUB '                                    return to the next command statement
'-----------------------------------------------------------------------------------

'-----------------------------------------------------------------------------------
' An array passed into a function by reference
'-----------------------------------------------------------------------------------
FUNCTION Populate_and_count_Stars (Array() AS StarType)

    ' Any changes in Array() will be passed back to Star()
    ' Star() has been passed 'by reference' into Array()

    SHARED ScreenWidth AS INTEGER '  share the variable from main program level
    SHARED ScreenHeight AS INTEGER ' share the variable from main program level
    DIM s AS INTEGER '              generic counter (LOCAL to this subroutine)

    FOR s = 1 TO UBOUND(Array) '              cycle through array
        Array(s).x = INT(RND * ScreenWidth) '  create random star coordinates
        Array(s).y = INT(RND * ScreenHeight)
    NEXT s
    Populate_and_count_Stars = UBOUND(Array) ' return size of the array passed in

END FUNCTION '                                return to the next command statement
'-----------------------------------------------------------------------------------

'-----------------------------------------------------------------------------------
' A SHARED array from the main program level
'-----------------------------------------------------------------------------------
FUNCTION Populate_and_count_Stars2 ()

    ' Any changes in Star() will be saved when function exits

    SHARED ScreenWidth AS INTEGER '  share the variable from main program level
    SHARED ScreenHeight AS INTEGER ' share the variable from main program level
    SHARED Star() AS StarType '      share the array from the main program level
    DIM s AS INTEGER '              generic counter (LOCAL to this subroutine)

    FOR s = 1 TO UBOUND(Star) '                cycle through array
        Star(s).x = INT(RND * ScreenWidth) '  create random star coordinates
        Star(s).y = INT(RND * ScreenHeight)
    NEXT s
    Populate_and_count_Stars2 = UBOUND(Star) ' return size of the array passed in

END FUNCTION '                                return to the next command statement
'-----------------------------------------------------------------------------------
Software and cathedrals are much the same — first we build them, then we pray.
QB64 Tutorial
Reply
#6
@bplus - "ReDim" is useless here, since it has not yet been initialized. - The output is interesting. I know how that happens, but was that intentional? I don't really understand what you're trying to show.  Huh

Code: (Select All)
$Console:Only

Dim Shared mySharedArray(1 To 20) As Long

For i = 1 To 20
  mySharedArray(i) = i * i
Next

Dim out10(1 To 10) As Integer

first10Plus5 = first10squaresPlus&(5, out10())
For i = 1 To 10
  Print out10(i)
Next
Print "Total was: "; first10Plus5

End

Function first10squaresPlus& (X, outputFirst10() As Integer)
  Print X
  Print
  For i = 1 To 10
    outputFirst10(i) = mySharedArray(i) + X
    Print outputFirst10(i)
    tot& = tot& + outputFirst10(i)
    Print Tab(5); tot&
  Next
  Print
  first10squaresPlus& = tot&
End Function

tot$ is also redundant   Tongue
Code: (Select All)
Function first10squaresPlus& (X, outputFirst10() As Integer)
  Print X
  Print
  For i = 1 To 10
    outputFirst10(i) = mySharedArray(i) + X
    outputFirst10 = outputFirst10 + outputFirst10(i)   
  Next
  Print
  first10squaresPlus& = outputFirst10 'tot&
End Function

The edition
1st row: 6 + 3 = 9 + 5 = 14 + 7 = 21 . . . always 2 more.
2nd row: 6 + 9 = 15 + 14 = 29 + 21 = 50 . . .
In the 2nd row, the results of the addition from the 1st row are added. The end result is correct in both cases, but I find the whole thing quite confusing.

[Image: Shared-Array2023-06-22.jpg]
Reply
#7
Quote:@bplus - "ReDim" is useless here, since it has not yet been initialized. - The output is interesting. I know how that happens, but was that intentional? I don't really understand what you're trying to show.  [Image: huh.png]


KP,

I was just trying to show an example of a function using a shared array of first 10 squares with 5 added to each square for a non trivial though totally made up example.

ReDim was not needed in this example, no, but who gives a flying fur ball?! ReDim is good habit to use for output arrays from Subs and Functions so they can change the dimensions if that is their function or routine to do. Why restrict to Static arrays when Dynamic ones are so much more flexible with upper and lower bounds?
b = b + ...
Reply
#8
(06-22-2023, 04:05 PM)bplus Wrote:
Quote:@bplus - "ReDim" is useless here, since it has not yet been initialized. - The output is interesting. I know how that happens, but was that intentional? I don't really understand what you're trying to show.  [Image: huh.png]


KP,

ReDim was not needed in this example, no, but who gives a flying fur ball?! ReDim is good habit to use for output arrays from Subs and Functions so they can change the dimensions if that is their function or routine to do. Why restrict to Static arrays when Dynamic ones are so much more flexible with upper and lower bounds?
We had a long discussion about "ReDim" & Co. ReDim has nothing to do with static or dynamic arrays, first of all. Everything is up for discussion.
ReDim is only used to resize a dynamic array. Ultimately, if you use that for declaration, the confusion is total.

Again, dynamic arrays are created whenever no constant value is specified in the DIM statement.
Code: (Select All)
Dim As Integer rows, cols

rows = 10
cols = 12
Dim grid(row, cols) 'Dynamic array

ReDim grid(14, 10)

Dim out10(1 To 10) As Integer is no a dynamic array.
[Image: Re-Dim-Array2023-06-22.jpg]
Reply
#9
KP, you can not resize an array that is Dim'd makes it static (= no resizable) only an array that is ReDim'd from the start maybe resized because made Dynamic from the start.

This is without the use of Static$ or Dynamic$ metacommands that I never use.

So how to you start a Dynamic array without the Dynamic$ metacommand? Update: Answered nice!

"When the $DYNAMIC metacommand or REDIM is used, array element sizes are changeable (not $STATIC)." from Wiki Dim

Update:
OK so you can make an array dynamic with variable dimensions, nice, here is anther way:
Code: (Select All)
Dim As Integer rows, cols

rows = 10
cols = 12
Dim grid(row, cols) 'Dynamic array

ReDim grid(14, 10)

' OK   that's one way


' heres another

rows = 10
cols = 12
ReDim grid2(row, cols) 'Dynamic array

ReDim grid2(14, 10)

If you ReDim the array from the start, you know it's Dynamic from the start.
b = b + ...
Reply
#10
Quote:If you ReDim the array from the start, you know it's Dynamic from the start.
No! - Your example doesn't bring anything, the output is missing. Declaring an array with ReDim doesn't do anything, but if you enjoy it then do it, but don't be surprised by undefined, sudden errors.

Like this (The program gets confused):

[Image: Redim-Redim-Juni2023.jpg]
Reply




Users browsing this thread: 10 Guest(s)