Array in an array
#41
(02-21-2023, 06:04 PM)Kernelpanic Wrote: Erase can also be used for dynamic arrays, but it is redundant there as Redim includes Dim & Erase.  Wink

(02-21-2023, 02:16 PM)bplus Wrote: The easy answer for Dynamic array is to just REDIM it again.

The same thing was said in two different ways(*). However, it depends on the application. Q(uick)BASIC had to be more competitive because interpreted BASIC was falling behind C too much, and therefore M$ allowed the concept of dynamic memory. So "$DYNAMIC" and "REDIM" and declaring an array with "DIM" with variable subscript were the only ways to have anything like "calloc()" and "malloc()" in C. I'm not sure if "ERASE" existed in GW-BASIC/BASICA but its meaning was changed where it came to dynamic arrays. There had to be some way to free the dynamic memory if it was no longer to be used, because when the first version of QuickBASIC came out, computers couldn't have much more than 640KB RAM for a reasonable price.

(*) But (a big one) that is true as long as the number of dimensions is the same.

Cannot just "REDIM" an already-existing dynamic array changing it from single- to double-dimension, for example. It is not allowed even if "ERASE" were used before a second or further "REDIM". The programming system firmly sticks to the number of dimensions for an array identifier.

From this program:

Code: (Select All)
redim a(1 to 10, 1 to 10)
a(8, 8) = 8
print a(8, 8)
redim a(1 to 8)
a(8) = 64
print a(8)
end

I get this output from QB64PE compiler:

Code: (Select All)
[~/zapp/qbpe]$ ./qb64pe -x fd21.bas
QB64-PE Compiler V3.6.0

Beginning C++ output from QB64 code...
[....................                              ] 40%
Cannot change the number of elements an array has!
Caused by (or after):REDIM A ( 1 TO 8 )
LINE 4:redim a(1 to 8)
Reply
#42
Hard to see how Erase "erases" an array if you can't reuse the name after Erase.
Code: (Select All)
ReDim a(1 To 10, 1 To 10)
a(8, 8) = 8
Print a(8, 8)
Erase a
redim a(1 to 8) '<<< red lines
(8) = 64
print a(8)
End

Must be purely to save memory space.
b = b + ...
Reply
#43
(02-21-2023, 11:13 PM)bplus Wrote: Hard to see how Erase "erases" an array if you can't reuse the name after Erase.
Code: (Select All)
ReDim a(1 To 10, 1 To 10)
a(8, 8) = 8
Print a(8, 8)
Erase a
redim a(1 to 8) '<<< red lines
(8) = 64
print a(8)
End

Must be purely to save memory space.

Yes, you can use the same name of the ERASEd dynamic array at the condition that you do not change the number of dimensions of the array (monodimensional stays with monodimensional , bidimensional stays with bidimensional etc etc), so you can "REDIM a "  array with the same 2 dimensions that it has at beginning., but you can change the range of dimensions (bottom-upper limits)
It is a pity that wiki has no example for ERASE!
Reply
#44
Again to static and dynamic array.
A static array is assigned a fixed, immutable memory location when compiled by the compiler. This can neither be deleted (Erase) nor re-dimensioned. The Erase command just reinitializes the array new with zeros.

In the case of dynamic arrays, the storage space is not determined until the program is running, so it does not have a fixed storage area. Therefore, a dynamic array can also be re-dimensioned with Redim (Erase & Dim): A 4 * 4 array can become a 4 * 6 array, but the dimensions must be observed. A two-dimensional array cannot become a three-dimensional one.

If only the Erase command is applied to a dynamic array, then it no longer exists because it has no a fixed memory area, so it was really deleted, so nothing can be seen anymore.


Code: (Select All)
'Static - Dynamic array -- 27. Feb. 2023

Option _Explicit

Dim a(1 To 20)
Dim As Integer z, i

'Dynamisches Feld
Dim As Integer dynamischFeld(20)

Locate CsrLin + 2, 2
Print "Statisches Array"

z = 1
For i = 1 To 20
  a(i) = z
  Print Using "## "; a(i);
  z = z + 1
Next

Erase a

Locate CsrLin + 2, 2
Print "Erase just reinitializes the array"

For i = 1 To 20
  Print Using "## "; a(i);
Next

Locate CsrLin + 2, 2
Print "Dynamisches Array"

Locate CsrLin, 2

'Dynamisches Feld initialisieren
z = 1
For i = 1 To 20
  dynamischFeld(i) = z
  Print Using "## "; dynamischFeld(i);
  z = z + 1
Next
Print: Locate , 2

Erase dynamischFeld

Locate CsrLin + 1, 2

'Ergibt Fehlermeldung, da es nicht mehr existiert.
Beep: Print "Error message because the danamic array after Erase no longer exists."
Print Using "## "; dynamischFeld(i);

End

PS: Note concretized.
Reply
#45
(02-17-2023, 11:42 PM)SMcNeill Wrote:
(02-17-2023, 09:12 PM)TerryRitchie Wrote:
(02-17-2023, 06:32 PM)bplus Wrote:
(02-17-2023, 05:43 PM)Balderdash Wrote: Obligatory MySQL/SQLite suggestion.
Ah yes, we still await the tut! Smile  maybe Terry?
I thought someone had already built an SQL library for QB64. Wasn't it steve? I know he built one for Dbase.
That was Spriggsy.  Smile

This thread had me thinking of SQL too, but in the spirit of BASIC, the SPLIT & JOIN delimited text approach is nice and simple.

I see 2 related but separate requirements:
  • We want to store nested information. 
  • We want to save & retrieve this data structure to & from a file system.

I might suggest aiming for a solution that is more general purpose: 
  • simple to use, easy to store and retrieve values
  • easy to understand (no complex memory commands or hacks)
  • not too heavy on resources (e.g. a 2-D array where there are large sections of empty array)

In a language like JavaScript this would be simple to do with objects which can be saved in plain text as JSON. 
These "objects" are more structures than true objects - a lot like UDTs in QB. 
It's not OOP with classes, methods, polymorphism, etc. Just a way to store & retrieve nested values.
So if we consider them just as data structures, the "objects" in JavaScript are a lot like UDTs in QB64, 
only without the limitations - you can do arrays of arrays, arrays of structures, structures containing arrays, etc. 
And it all can be converted to/from plain text JSON. 

Now this could be a springboard to conversations about when can we get features in QB64PE like
  • associative arrays (dictionaries)
  • arrays inside UDTs
  • or why not just support data structures similar to the objects in JavaScript, with native serialization commands to/from JSON? 

BUT adding new features to the language is alot of work and takes time, and everyone would have to agree. 

So instead I might suggest using the current QB64PE language to just make a library to implement JavaScript-like structures & associative arrays, that can hold nested data, and serialize/deserialize to/from JSON. We have played with dictionaries, linked lists, and similar stuff before on the old QB64.org site, with hashed keys and other optimizations. Those would be the building blocks. Such a library should help not only NasaCow, but be useful for lots of things. I think there is value there. 

I can look through my code and try and find some of those dictionary and linked list projects, and see what can be done, but if anyone has any code that can be put to this use, feel free to speak up! For now I found this, which could serve as a starting point:
Using Associative Arrays in QBasic
Reply
#46
There is a small error in the first code on the page. Thats how it works:
Code: (Select All)
'Assosziatives Array: https://jeff.win/qbhash/
'28. Feb. 2023

Type element
  tag As String * 10
  value As String * 10
End Type
Dim Shared aa(10) As element
Dim Shared aalast ' Last occupied AA() element

setvalue "foo", "bar"
Print getvalue$("foo") ' prints bar

End

Function getvalue$ (tag As String)
  tag = LTrim$(RTrim$(tag))
  tag = tag + String$(10 - Len(tag), " ")
  For i = 0 To aalast
    If (tag = aa(i).tag) Then
      getvalue$ = aa(i).value
      Exit Function
    End If
  Next
End Function

Sub setvalue (tag As String, value As String)
  aa(aalast).tag = tag
  aa(aalast).value = value
  aalast = aalast + 1
End Sub

One advantage of associative arrays didn't in moment become clear to me. Similar to a two-dimensional random access array. . . That's how I understood it.
Reply
#47
(02-28-2023, 03:33 PM)Kernelpanic Wrote: There is a small error in the first code on the page. Thats how it works:
Code: (Select All)
'Assosziatives Array: https://jeff.win/qbhash/
'28. Feb. 2023

Type element
  tag As String * 10
  value As String * 10
End Type
Dim Shared aa(10) As element
Dim Shared aalast ' Last occupied AA() element

setvalue "foo", "bar"
Print getvalue$("foo") ' prints bar

End

Function getvalue$ (tag As String)
  tag = LTrim$(RTrim$(tag))
  tag = tag + String$(10 - Len(tag), " ")
  For i = 0 To aalast
    If (tag = aa(i).tag) Then
      getvalue$ = aa(i).value
      Exit Function
    End If
  Next
End Function

Sub setvalue (tag As String, value As String)
  aa(aalast).tag = tag
  aa(aalast).value = value
  aalast = aalast + 1
End Sub

One advantage of associative arrays didn't in moment become clear to me. Similar to a two-dimensional random access array. . . That's how I understood it.

Yes that can be quite useful in a lot of cases. 
I haven't had a chance to test that code sample - is it broken? 
Were you able to fix it? 
I can give it a look later, and provide better examples that I did run and were working (at least they were a year or two ago, LoL!)
Reply
#48
Quote:I haven't had a chance to test that code sample - is it broken? 
Were you able to fix it? 

The error was just this part:
setvalue "foo", "bar"
Print getvalue$("foo") ' prints bar

It was at the end of the program and that was wrong. Otherwise the program only outputs "bar". Nice!  Rolleyes
[Image: Assoziativ-Array29-Feb-2023.jpg]
Reply
#49
(02-28-2023, 11:14 PM)Kernelpanic Wrote:
Quote:I haven't had a chance to test that code sample - is it broken? 
Were you able to fix it? 

The error was just this part:
setvalue "foo", "bar"
Print getvalue$("foo") ' prints bar

It was at the end of the program and that was wrong. Otherwise the program only outputs "bar". Nice!  Rolleyes
[Image: Assoziativ-Array29-Feb-2023.jpg]


The only part I'm not sure about was this comment in the final code:

Quote:' Warning: Don't expect this to work all the time, keys may overlap with
'          others.  Test thoughly.

Normally an associative array / dictionary shouldn't have issues with overlapping keys. 
In the examples we had going last year, I don't think that was an issue. 
I still have to find the code, to compare and see how they avoid this problem.
Reply
#50
It was just a simple example. To make an associate array emulation useful, must keep the list of keys sorted and use a binary search. Otherwise searching for keys sequentially could be intolerable even on the multi-core large-screen big-RAM computers of today that cost a few thousand dollars each one.

Could use the binary search in order to register the key and its related value, in case the key doesn't exist already in the array.

"Overlapping" keys might be the requirement for unique representation, which means case sensitive, which might not sit well with some people who are willing to use as much as a whole sentence as key rather than being forced to tell "KEY" from "key" and "KeY". Use the binary search for a request to enter a value. If the key (sanitized by LCASE$() or UCASE$()) exists then it's up to the user to replace the associated value, or try again with another key.

Another possibility, which is more difficult to program, is hash table. This is employed by the QB64 source code, for example. That case would make it impossible to go through the whole associate array expecting to get a listing of sorted keys or values.
Reply




Users browsing this thread: 25 Guest(s)