Author Topic: New guy intro and question on REDIMing arrays in QB64  (Read 4376 times)

0 Members and 1 Guest are viewing this topic.

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
New guy intro and question on REDIMing arrays in QB64
« on: August 09, 2018, 08:56:59 pm »
Hello,
I'm Andy, a farmer and RPG gamer living in the Mid-Atlantic area.

To date I have a number of programs that I use for work or gaming aids. One that keeps a data base of truck loads and harvest yields, and a number of RPG character generators.
I've been programming off and on since the days of Applesoft Basic and after some years discovered QBasic. I even once took a college course in Assembly for the 8088, but mainly it taught me that such things are beyond my pay grade.

I tend toward data manipulation programs and have little experience with graphics. My aps tend to use SCREEN 0 and have that clunky DOS look to them, but they tell me what I need to know.

My main reference in learning QB is....appropriately enough...QBasic for Dummies

[pause for laughter to fade...] ;)

I have recently dusted off my meager skills and am tackling yet another PC generator. This time for the new release of a game called Runequest. Only in this case the application is to handle multiple characters at once. Conceived to be a gamemaster aid to handle the tedium of CharGen, eliminating the page flipping, table referencing and tallying of skills, and keep track of the rather large amount of data associated with each PC.

and now for my question.

In the olden days redimensioning an array required iterating the original array into a temporary one, redimensioning the original to the larger size and then iterating the temporary array back into the original one, leaving space in the uppermost element for new entries. This is particularly tedious in this program since my approach is to use about 30 one dimensional arrays, and 3 two dimensional arrays, all of them shared globally with an original DIM SHARED in the main module.

I noticed QB64 includes the _PRESERVE command, if I'm reading it right, would this overcome the need for all the array swapping and iterating?

Is this as simple as:
REM $DYNAMIC 'metacommand in the main module then....
REDIM _PRESERVE array(increment element in question by 1)  'in a SUB dedicated to the redimensioning?

then going on business as usual adding the new PC in the uppermost elements?

I'd love to have it be so and dispense with all the FOR..NEXT iterations.

Thank you.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: New guy intro and question on REDIMing arrays in QB64
« Reply #1 on: August 10, 2018, 12:45:12 am »
Hi Andy,

Welcome to the forum.

_PRESERVE works with Dynamic arrays that are set up with REDIM instead of DIM.

Here is a link to a very handy resource you might like better than the Editor's Help:
http://qb64.org/wiki/PRESERVE

From here, you can access the Main Page (see left column) and bookmark the site on your browser (if you haven't already).
« Last Edit: August 10, 2018, 12:46:52 am by bplus »

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: New guy intro and question on REDIMing arrays in QB64
« Reply #2 on: August 10, 2018, 01:00:44 am »
Ok, so I should be using REDIM in my original declarations instead of DIM.

Thanks.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: New guy intro and question on REDIMing arrays in QB64
« Reply #3 on: August 10, 2018, 01:56:12 am »
A few tricks which might help you:

Don't REDIM by increments of 1, unless you just have too.  Making, moving, expanding, freeing the memblock takes time.  Do it in a loop and you'll experience quite a slowdown in your program.

Instead, raise the limit by a larger amount and reduce the call to REDIM as much as possible, like so:

Instead of: 

REDIM _PRESERVE array(UBOUND(array) + 1)

Instead, try something like:

IF index < UBOUND(array) THEN REDIM _PRESERVE array(UBOUND(array) + 100)

Multiple calls to REDIM increases program lag for you, and should generally be avoided when possible.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline RhoSigma

  • QB64 Developer
  • Forum Resident
  • Posts: 565
    • View Profile
Re: New guy intro and question on REDIMing arrays in QB64
« Reply #4 on: August 10, 2018, 03:49:13 am »
Welcome to the forum OldMoses,
it should also be mentioned, that in multi-dimensional arrays you should organize your data in such a fashion, that you only need to change the index of last dimension with _PRESERVE, otherwise it will scramble up your existing data, moving values into other array elements.

Here are two short examples to illustrate the wrong and right behaviour with multi-dim arrays:

wrong.bas
Code: QB64: [Select]
  1. REDIM x(1, 1)
  2. x(0, 0) = 0.0
  3. x(0, 1) = 0.1
  4. x(1, 0) = 1.0
  5. x(1, 1) = 1.1
  6.  
  7. x(2, 0) = 2.0
  8. x(2, 1) = 2.1
  9.  
  10. PRINT USING "x(0,0) = #.#"; x(0, 0)
  11. PRINT USING "x(0,1) = #.#"; x(0, 1)
  12. PRINT USING "x(1,0) = #.#"; x(1, 0)
  13. PRINT USING "x(1,1) = #.#"; x(1, 1)
  14. PRINT USING "x(2,0) = #.#"; x(2, 0)
  15. PRINT USING "x(2,1) = #.#"; x(2, 1)
  16.  

right.bas
Code: QB64: [Select]
  1. REDIM x(1, 1)
  2. x(0, 0) = 0.0
  3. x(0, 1) = 0.1
  4. x(1, 0) = 1.0
  5. x(1, 1) = 1.1
  6.  
  7. x(0, 2) = 0.2
  8. x(1, 2) = 1.2
  9.  
  10. PRINT USING "x(0,0) = #.#"; x(0, 0)
  11. PRINT USING "x(0,1) = #.#"; x(0, 1)
  12. PRINT USING "x(0,2) = #.#"; x(0, 2)
  13. PRINT USING "x(1,0) = #.#"; x(1, 0)
  14. PRINT USING "x(1,1) = #.#"; x(1, 1)
  15. PRINT USING "x(1,2) = #.#"; x(1, 2)
  16.  
« Last Edit: January 02, 2019, 09:07:15 am by RhoSigma »
My Projects:   https://qb64forum.alephc.xyz/index.php?topic=809
GuiTools - A graphic UI framework (can do multiple UI forms/windows in one program)
Libraries - ImageProcess, StringBuffers (virt. files), MD5/SHA2-Hash, LZW etc.
Bonus - Blankers, QB64/Notepad++ setup pack

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: New guy intro and question on REDIMing arrays in QB64
« Reply #5 on: August 10, 2018, 07:20:49 am »
Welcome to the forum OldMoses,
it should also be mentioned, that in multi-dimensional arrays you should organize your data in such a fashion, that you only need to change the index of last dimension with _PRESERVE, otherwise it will scramble up your existing data, moving values into other array elements.

That's precisely what happened to me last night after I tried it. I noticed disappearing data fields with no apparent pattern. Thank you, I would likely have wracked my brains for weeks trying to figure out what happened, and I would have never suspected that.

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: New guy intro and question on REDIMing arrays in QB64
« Reply #6 on: August 10, 2018, 07:31:00 am »
A few tricks which might help you:

Don't REDIM by increments of 1, unless you just have too.  Making, moving, expanding, freeing the memblock takes time.  Do it in a loop and you'll experience quite a slowdown in your program.

Instead, raise the limit by a larger amount and reduce the call to REDIM as much as possible, like so:

Thank you, I will probably implement that in steps of 10 to see what my screen space does with it, then end up writing another scrolling routine. ;)

This thing has grown from a simple one character number cruncher to over 3000 LOC, no point in stopping now as long as I'm still bit by the bug...

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: New guy intro and question on REDIMing arrays in QB64
« Reply #7 on: August 10, 2018, 09:03:15 am »
Welcome to the forum OldMoses,
it should also be mentioned, that in multi-dimensional arrays you should organize your data in such a fashion, that you only need to change the index of last dimension with _PRESERVE, otherwise it will scramble up your existing data, moving values into other array elements.

That's precisely what happened to me last night after I tried it. I noticed disappearing data fields with no apparent pattern. Thank you, I would likely have wracked my brains for weeks trying to figure out what happened, and I would have never suspected that.

Take a moment to look at my replies to the topic here, if you will: https://www.qb64.org/forum/index.php?topic=310.msg2015#msg2015

I think they should illustrate and explain what's going on with multidimensional arrays and REDIM _PRESERVE, but if you're still confused at all afterwards, feel free to ask any questions and I'll do my best to answer them for you.   
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: New guy intro and question on REDIMing arrays in QB64
« Reply #8 on: August 10, 2018, 09:21:06 am »
It should be noted now that Static arrays can act like dynamic ones specially if you are just adding items to top of array and they would have the best speed performance but you could not use UBOUND to track the top item (that has value), you would do it manually:
Code: QB64: [Select]
  1. 'For OPTIMAL speed performance (maybe not optimal memory storage):
  2.  
  3. ' A Static array would likely be best choice:
  4. ' 1. Use a top limit variable to control the absolute maximum size you would allow program to go.
  5. ' 2. Use a top index variable to track the current "upper" bound of your array.
  6.  
  7. topLimit = 10 '<<< absolute maximum number of elements you would allow
  8. topIndex = 0 ' <<< current "upper" bound of the array, the number of items that are actually assigned values by program.
  9. DIM myStaticArr(1 TO topLimit) '<<<< this assigns the maximum size you would allow the array to go IM THE BEGINNING.
  10.  
  11. FOR addItem = 1 TO topLimit
  12.     item = addItem ^ 2
  13.     topIndex = topIndex + 1
  14.     myStaticArr(topIndex) = item
  15.     PRINT "For Top index ="; topIndex; " The array contains:"
  16.     FOR i = 1 TO topIndex
  17.         PRINT myStaticArr(i);
  18.     NEXT
  19.     PRINT: PRINT
  20.     INPUT "Continue show? Just press Enter for yes, any other entered quits > "; cont$
  21.     IF LEN(cont$) THEN END
  22. PRINT "We've reached the preset Top Limit for the Static Array."
  23.  
  24.  


Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: New guy intro and question on REDIMing arrays in QB64
« Reply #9 on: August 10, 2018, 10:31:33 am »
Oh, in the above reply, you should check if increasing the topIndex by 1 puts you over the topLimit value for the array, ie don't increase topIndex past the topLimit.

BTW, I think I used this trick with Aquarium with swaying kelp for number of fish drawing from 2 to 1024.
« Last Edit: August 10, 2018, 10:36:10 am by bplus »