suggestion: initialize array values within the DIM statement
#1
How difficult would it be to implement something similar to this in QB64PE? 

OPTION _EXPLICIT
DIM AS LONG LNUMS(5) = {1, 2, 5, 8, 4000}

This is syntax similar to C, and it is also supported to an extent by FreeBASIC. I have used this construct in FreeBASIC, and I have found it useful when initializing short arrays of 'fixed' data in a program.

(I always use OPTION _EXPLICIT, it has saved me more than a few times from fat-fingered typing.)
Reply
#2
I suppose there are a couple of ways it could be coded into a function...

Code: (Select All)
DIM AS LONG LNUMS(5)
RESTORE mytmp
DIM a AS LONG
FOR i = 1 TO UBOUND(LNUMS)
    READ a
    LNUMS(i) = a
NEXT

mytmp:
DATA 1,2,5,8,4000

' Proof.
FOR i = 1 TO UBOUND(LNUMS)
    PRINT LNUMS(i)
NEXT

'--------------------- Next method...
ERASE LNUMS
'--------------------- Begin...

a$ = "{1, 2, 5, 8, 4000}"
a$ = MID$(a$, 2, LEN(a$) - 2)

FOR i = 1 TO UBOUND(LNUMS)
    j = INSTR(seed, a$ + ",", ",")
    LNUMS(i) = VAL(MID$(a$, seed + 1, j - seed - 1))
    seed = j + 1
NEXT

' Proof
FOR i = 1 TO UBOUND(LNUMS)
    PRINT LNUMS(i)
NEXT

I suppose it all depends on finding a dev who could use it frequently enough to include it in a future release.

Pete
If eggs are brain food, Biden takes his scrambled.
Reply
#3
Could code a subprogram that takes two arguments: a string which is the list of values to initialize, and a dynamic array (which will be changed) to take the individual values from the list. Decide what will be the delimeter of the list. For mine I chose semicolon. Must also decide which type, even if it's integer. Sadly, for general purpose must choose "_INTEGER64".

The advantage of this is that the programmer doesn't have to worry about the array's size. The trade-off is that it's difficult this way to work with static arrays. It's clunky sometimes working with strings and having to parse them, but there's no other way to support an user's subprogram which accepts a number of parameters unknown to the compiler, something like the fabled "printf()" function in C runtime library.

Wait a moment -- @bobalooie why do you want to initialize an array with subscript zero as the first element? :O

I was hoping SMcNeill would come over to show off one of his functions... but here is my attempt.

Code: (Select All)
redim l(1 to 1) as integer
dim i as integer

fillinteger "1;2;5;8;4000", l()
for i = 1 to ubound(l)
    print i, l(i)
next
end

sub fillinteger (slist as string, li() as integer)
    static as long u, v, k
    if slist = "" then exit sub
    u = 1
    v = instr(slist, ";")
    k = 0
    do while v > 0
        k = k + 1
        redim _preserve li(1 to k) as integer
        li(k) = val(mid$(slist, u, v - u))
        u = v + 1
        v = instr(u + 1, slist, ";")
    loop
    k = k + 1
    redim _preserve li(1 to k) as integer
    li(k) = val(mid$(slist, u))
end sub
Reply
#4
@bobalooie I, too, am an advocate for OPTION _EXPLICIT usage. If only it had been used in the QB64 source code.
Ask me about Windows API and maybe some Linux stuff
Reply
#5
(12-21-2022, 03:59 PM)mnrvovrfc Wrote: Wait a moment -- @bobalooie why do you want to initialize an array with subscript zero as the first element? :O

Well, in this case I am interested in just iterating through the array as a lookup table of sorts, so it doesn't really matter if the first element is at 0 or 1. If I was working in C, I could use the syntax I showed or perhaps make a doubly-linked list so I could iterate either direction.

Your example works well, but I perceive that I would need a new fill function for every data type I want to store. Not really a challenge of course, except for a list of CONST values.

Soldiering on.
Reply
#6
(12-21-2022, 05:23 AM)Pete Wrote: I suppose there are a couple of ways it could be coded into a function...

Code: (Select All)
DIM AS LONG LNUMS(5)
RESTORE mytmp
DIM a AS LONG
FOR i = 1 TO UBOUND(LNUMS)
    READ a
    LNUMS(i) = a
NEXT

mytmp:
DATA 1,2,5,8,4000

' Proof.
FOR i = 1 TO UBOUND(LNUMS)
    PRINT LNUMS(i)
NEXT

'--------------------- Next method...
ERASE LNUMS
'--------------------- Begin...

a$ = "{1, 2, 5, 8, 4000}"
a$ = MID$(a$, 2, LEN(a$) - 2)

FOR i = 1 TO UBOUND(LNUMS)
    j = INSTR(seed, a$ + ",", ",")
    LNUMS(i) = VAL(MID$(a$, seed + 1, j - seed - 1))
    seed = j + 1
NEXT

' Proof
FOR i = 1 TO UBOUND(LNUMS)
    PRINT LNUMS(i)
NEXT

I suppose it all depends on finding a dev who could use it frequently enough to include it in a future release.

Pete

Yup, both good approaches. I'm just trying to be lazy and not have to type all that extra code.  Big Grin
Reply
#7
(12-21-2022, 03:36 AM)bobalooie Wrote: How difficult would it be to implement something similar to this in QB64PE? 

OPTION _EXPLICIT
DIM AS LONG LNUMS(5) = {1, 2, 5, 8, 4000}

This is syntax similar to C, and it is also supported to an extent by FreeBASIC. I have used this construct in FreeBASIC, and I have found it useful when initializing short arrays of 'fixed' data in a program.

(I always use OPTION _EXPLICIT, it has saved me more than a few times from fat-fingered typing.)

This would definitely be a nice feature - a function like what @mnrvovrfc (how do you pronounce that anyway?!) should work. When I am at my PC, I'll give it a try. Thanks mnrvovrfc!
Reply
#8
(12-21-2022, 03:59 PM)mnrvovrfc Wrote: I was hoping SMcNeill would come over to show off one of his functions... but here is my attempt.

My way of doing this type of thing is really, really simple:

Code: (Select All)
DIM foo(10) AS INTEGER

foodata: DATA 1,2,4,6,8000,12,56,23,45,89,12

Restore foodata
FOR i = 1 to 10: Read foo(i): Next

The label and restore aren't required in the code above, but it's just one of them things that I've gotten into the habit of always using.  I *NEVER* do a READ with my DATA, without doing a RESTORE first.  I do too much work with library files and other such things, so I never go under the assumption that the data I want to read is necessarily the first data in the program (or the next data in the program).  Restore always puts you at the data you want, and I'm just in the habit of always using it.  Skip it, if you don't think you need it for your own uses.  Smile

A lot simpler than a function and parsing a string and all that complicated stuff.  Wink
Reply
#9
I liked mn's example.

Well, I don't see a function, because we are returning a set of array values, not just a single value; so a sub seems a more likely choice...

Code: (Select All)
REDIM LNUMS(0): myray LNUMS(), "1, 2, 5, 8, 4000"

FOR i = 1 TO 5
    PRINT lNUMS(i)
NEXT

SUB myray (myarray(), myarray_elements AS STRING)
    DO
        i = i + 1
        j = INSTR(seed, myarray_elements + ",", ",")
        IF j = 0 THEN EXIT DO
        REDIM _PRESERVE myarray(i)
        myarray(i) = VAL(MID$(myarray_elements, seed + 1, j - seed - 1))
        seed = j + 1
    LOOP
END SUB

Now I think we need to restrict it to dynamic arrays, to avoid a duplicate definition. Maybe this could be expanded on to handle string arrays, too. As far as how to define them by type, single, long, etc. That's more complicated.

Edit: Steve was posting while I was writing. I se the same method.In fact, just recently in my replies to the password thread.

Pete
Reply
#10
(12-21-2022, 07:01 PM)Pete Wrote: Well, I don't see a function, because we are returning a set of array values, not just a single value; so a sub seems a more likely choice...

You should do your loop from 0 to 4, not 1 to 5 because you started an array at subscript zero...

Also the subprogram that you wrote doesn't initialize the array at subscript zero, it just increases local "i" by one. Then its value is one at first pass.

Even better (in main program) do:

Code: (Select All)
FOR i = LBOUND(LNUMS) to UBOUND(LNUMS)
Reply




Users browsing this thread: 12 Guest(s)