Page 1 of 4 123 ... LastLast
Results 1 to 10 of 40

Thread: Dim myArray() as Long At StrPtr(myString(Index))?

  1. #1
    thinBasic MVPs
    Join Date
    Oct 2012
    Location
    Germany
    Age
    54
    Posts
    1,530
    Rep Power
    171

    Dim myArray() as Long At StrPtr(myString(Index))?

    Can I create an array of Strings and copy the content of the String to an array of Numbers as this

    Dim myString() as String : Redim myString(2)
    Dim myNumbers() as Long
    
    'even though it seems stupid, but just to fill it right
    myString(1) = "0123012301230123" '...
    myString(2) = "123412341234123412341234" '...
    
    ReDim myNumbers(Len(myString(1))/SizeOf(LONG)) as Long At strPtr(myString(1))
    
    now myNumbers(1 to 3) will hold the CVL of "0123" ???

    can I do this thereafter:
    ReDim myNumbers(Len(myString(2))/SizeOf(LONG)) as Long At strPtr(myString(2))
    
    myNumbers() can be set to manipulate the string-content at myNumbers(Position) also?
    I think there are missing some Forum-sections as beta-testing and support

  2. #2
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    57
    Posts
    8,777
    Rep Power
    10
    There are two things to get

    1.
    In thinBasic Dynamic Strings OLE32 strings or (like they are called in C/C++) BSTR strings
    An OLE32 string is a pointer to a pointer that points to a dynamic allocated area
    VARPTR of a dynamic string will return the pointer to the string
    STRPTR of a dynamic string will return the pointer to the dynamic allocated area


    An array of strings is in reality a sequence of DWORD pointers all of them pointing to a dynamic memory area.
    VARPTR of a dynamic string will never change (the pointer of a string will never change)
    STRPTR of a dynamic string will change every time the dynamic string is changed (every time the string is de-allocated and allocated again)

    More info here: http://oreilly.com/catalog/win32api/chapter/ch06.html

    2.
    Numbers (LONG or whatever type) are stored as binary representation and not human readable form
    So you cannot just map a "123" string into a LONG and have it as LONG number
    Attached Images Attached Images
    www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
    Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000

  3. #3
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    57
    Posts
    8,777
    Rep Power
    10
    Maybe this will clarify:

    Uses "console"
    
    Dim Counter     As Long
    Dim myString()  As String
    ReDim myString(2)
     
    'even though it seems stupid, but just to fill it right
    myString(1) = "0123456701234567" '...
    myString(2) = "123412341234123412341234" '...
     
    Dim myNumbers(Len(myString(1))/SizeOf(Long)) As String * 4 At StrPtr(myString(1))
    For counter = 1 To UBound(myNumbers)
      PrintL Counter, myNumbers(Counter) 
    Next
    PrintL "---Press a key---"
    WaitKey
    
    
    
    
    '---Instead what you can do is to use a dynamic string to store whatever you would like
    '---Imagine you want to store 1000 longs into a dynamic area
    %NLONGS = 10
    '---allocate a String able To store %NLONGS longs
    myString(1) = String$(SizeOf(Long), %NLONGS)
    '---Overimpose an array of %NLONGS longs over the same memory area of the dynamic string
    Dim MyLongs(%NLONGS) As Long At StrPtr(myString(1))
    '---Fill you array of longs
    For Counter = 1 To %NLONGS
      MyLongs(Counter) = Counter
      PrintL Counter, MyLongs(Counter)
    Next
    '---Each 4 bytes of the string is the binary representation of a long
    For Counter = 1 To %NLONGS
      PrintL Counter, CVL(myString(1), SizeOf(Long) * (Counter-1))
    Next
    PrintL "---Press a key---"
    WaitKey
    
    www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
    Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000

  4. #4
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    57
    Posts
    8,777
    Rep Power
    10
    Here another example using DIM/REDIM ... AT ...
    Use dynamic strings inside UDT (not many languages allows this) to dynamically allocate memory buffers for dummy arrays.

    Use thinBasic debugger to inspect dummy data.

    Type MyType
      nLongs        As Long
      sLongArray    As String
      nStrings      As Long
      sStringArray  As String
    End Type
    
    
    Dim MyData As MyType
    
    
    '---Allocate room for ... longs using a string buffer
    MyData.nLongs     = 10
    MyData.sLongArray = String$(MyData.nLongs * SizeOf(Long), $NUL)
    
    
    '---Allocate room for ... dynamic string using a string buffer
    '---Remember: a dynamic string is apointer to a pointer that points to dynamic memory
    MyData.nStrings     = 10
    MyData.sStringArray = String$(MyData.nStrings * SizeOf(Long), $NUL)
    
    
    '---Now define some dummy arrays
    Dim DummyLongs  (MyData.nLongs  ) As Long   At StrPtr(MyData.sLongArray   )
    Dim DummyStrings(MyData.nStrings) As String At StrPtr(MyData.sStringArray )
    
    
    
    
    Dim Counter As Long
    '---Fill data in dummy long array
    For Counter = 1 To MyData.nLongs
      DummyLongs(Counter) = Counter
    Next
    
    
    '---Fill data in dummy string array
    For Counter = 1 To MyData.nStrings
      DummyStrings(Counter) = "String " & Counter
    Next
    
    
    
    
    '---How to re-dimension arrays????
    '---Simple, just redimension the UDT string buffer and redim the dummy arrays
    '---Here we will add other 10 elements
    MyData.sStringArray = MyData.sStringArray & String$(10 * SizeOf(Long), $NUL)
    MyData.nStrings     = 20
    '---and remap the dummy string
    ReDim DummyStrings(MyData.nStrings) As String At StrPtr(MyData.sStringArray )
    '---Fill data in dummy string array
    For Counter = 11 To MyData.nStrings
      DummyStrings(Counter) = "String " & Counter
    Next
    
    www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
    Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000

  5. #5
    thinBasic MVPs
    Join Date
    Oct 2012
    Location
    Germany
    Age
    54
    Posts
    1,530
    Rep Power
    171
    Thanks for your replies, the last example ist the "most fitting" for my purpose but I'm still in doubt about which way would be the best.

    Imagine I have a document (as a Mesh or a Bitmap or whatever) and I have stored all documents in memory as some string-array, like myBitmaps$(123) = I have 123 diffferent Bitmaps in memory. (do not worry about Bitmapheader or details it's just an example - in truth i want to use it to edit my own mesh-format, but that would make it too complicated here)

    Now the user wants to perform common actions on myBitmap(1) so he has to choose myBitmap(1) as the current one to work with.

    At that moment I want myNumbers()-Array to "contain" the data of myBitmap$(1), so for example myNumbers(24) will access the data of pixel 24 on currently active myBitmap$(1).
    If user is done editing "myBitmap$(1)" and chooses to edit "myBitmap$(27)" the myNumbers() are supposed to access the myBitmap$(27)-data.

    I could surely just count the data in into myNumbers() by parsing through the data-string and vice versa when the user changes the document to work with - but I thought using like a "mask" for the data-string, dimensioned at the same position in memory will perform this data-exchange much faster than I could do in a basic-count-in-loop, especially when those strings get very long.

    Is it valid to ReDim myNumbers(123) At some different position?
    Will Redim ... At... always Preserve the memory?
    Is there some similar method as "Union" for this purpose which I have overseen?
    Would it be better way for this, to just copy the memory as myCurrent$= myBitmap$(27) and let just myCurrent$ always share the same memory with myNumbers()?
    I think there are missing some Forum-sections as beta-testing and support

  6. #6
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    57
    Posts
    8,777
    Rep Power
    10
    Sorry I'm on travel driving so I cannot completely reply ...

    Dim ... At
    Redim ... At
    SetAt ...
    GetAt ...
    Are all methods that define/redefine/map virtual variables over some memory allocated and handled somewhere else.
    They just gives programmer the possibility to interpret some continuous memory area the way he/she prefer.

    Virtual variables NEVER allocate or de-allocate memory even when virtual variables finish their life scope.
    Virtual variables just use memory already allocated.

    You can always change and redefine a virtual variable using redim ... At or SetAt ... to a new memory location.

    The only important thing to remember in to map a virtual variable to a memory location that is fully allocated (using the method you prefer) otherwise GPF is just around the corner



    Sent from my iPhone using Tapatalk
    www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
    Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000

  7. #7
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    57
    Posts
    8,777
    Rep Power
    10
    Here another interesting way to store big amount of data and quickly retrieve it: thinBasic Dictionary and dynamic strings

    Uses "Dictionary"
    
    
    Dim myDict    As DWord
    Dim pData     As DWord
    Dim MyString  As String At 0  '---< Dummy virtual string. Its memory location will be set later when needed
    
    
    '---Create a new thinBasic dictionary (collection of key/data pairs
    myDict = Dictionary_Create(1000)
    
    
    '---Add few key/data but you can add thoudands
    '---Data can be any kind, even binary data of whatever len
    Dictionary_Add(myDict, "KEY1", "ABCDEFGHIJKLMNO")
    Dictionary_Add(myDict, "KEY2", "12345678901234567890")
    
    
    '---Find a key and if found return a pointer to the dynamic string that holds data
    pData = Dictionary_Exists(myDict, "KEY1")
    If pData Then
      '---Let the dummy string be placed over the real string ptr
      SetAt(MyString, pData)
      MsgBox 0, MyString
    End If
    
    
    '---Find another key and if found return a pointer to the dynamic string that holds data
    pData = Dictionary_Exists(myDict, "KEY2")
    If pData Then
      '---Let the dummy string be placed over the real string ptr
      SetAt(MyString, pData)
      MsgBox 0, MyString
    End If
    
    '---IMPORTANT:
    Dictionary_Free(MyDict)
    
    www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
    Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000

  8. #8
    thinBasic MVPs
    Join Date
    Oct 2012
    Location
    Germany
    Age
    54
    Posts
    1,530
    Rep Power
    171
    Dictionary is cool.
    Another quest how to track/convert data then correct/fastest:

    Assume I have a numerical UDT-Array as this:
    Uses "Dictionary"
    
    Type t_Vec3d
     X as Double
     Y as Double
     Z as Double
    End Type
    
    Dim Positions() as t_Vec3d: Redim Positions(123)
    Dim nPositions  as Long = 123            ' this not urgently needed since there's Ubound()...
    Dim myDict      as Dword = Dictionary_Create(234)
    
    Which way would be the fastest/correct one to convert Positions()-Array into a String at once so can I store it to Dictionary and how restore it fast from there without looping through the whole array of positions() using CVD/MKD$ on .X,.Y and .Z?

    Do I need to convert it at all? Can't I just poke/peek that whole udt-array in one simple call into/from dictionary somehow? I guess there's a trick to it...
    I think there are missing some Forum-sections as beta-testing and support

  9. #9
    thinBasic author ErosOlmi's Avatar
    Join Date
    Sep 2004
    Location
    Milan - Italy
    Age
    57
    Posts
    8,777
    Rep Power
    10
    I always prefer not to use PEEK/POKE but try to use Virtual Variables.
    Below an example that I hope will clarify something more.
    It is long because I added many comment to explain various steps. Please read comments as a continuous speech.

    In general the message I would like to give is: memory is just a sequence of bytes regardless the way you access or interpret it !
    Using Virtual Variables you can interpret memory the way you want in different ways all at the same time.

    Uses "Dictionary"
     
    '---Here you structure
    Type t_Vec3d
     X As Double
     Y As Double
     Z As Double
    End Type
    
    
     
    'Dim Positions() As t_Vec3d
    Dim MaxPositions  As Long = 123
    'ReDim Positions(nPositions)
    
    
    '---Here we define a dictionary able to create 1000 buckets
    '---1000 is not the max number of keys the dictionary will be able to store 
    '---but is the number of pre-allocated buckets for the internal hash table value calculation.
    '---If different keys will produce the same hash value, dictionary will create
    '---a linked list of keys for the same bucket
    Dim myData As DWord = Dictionary_Create(1000)
    
    
    '---We want to use this dictionary to store all main application info
    '---So we store some of them
    Dictionary_Add(MyData, "APP_NAME"     , "Test dictionary power")
    Dictionary_Add(MyData, "APP_AUTHOR"   , "Rene Miner")
    Dictionary_Add(MyData, "APP_COAUTHOR" , "Eros Olmi")
    
    
    '---Ok, after few APP info, some real data
    '---To store an array of t_Vec3d we just need to allocate the correct memory for it
    '---If we know the definitive number of elements, it is quite simple to
    '---calculate the needed memory: SizeOf(t_Vec3d) * MaxPositions
    '---So we create a dictionary element (key + memory) for this
    '---We will call it DATA_POS and will allocate enough memory full of nulls so
    '---all memory will be initualized to nul 
    '---For later fast usage, we will also save a pointer to the first data byte
    Dim pDataPos As DWord
    pDataPos = Dictionary_Add(MyData, "DATA_POS" , String$(SizeOf(t_Vec3d) * MaxPositions, $NUL))
    
    
    '---Dictionary_Exists can be also used to get back pDataPos
    'pDataPos = Dictionary_Exists(MyData, "DATA_POS")
    
    
    If pDataPos Then
      '---All is OK
    Else  
      '---Something went wrong, better to give error
    End If
                                                          
    '---Here we assume all went OK
    
    
    '----------------------------------------------------------
    '---Now how to access single t_Vec3d element in the array? 
    '----------------------------------------------------------
    
    
    '---Imagine we want to access t_Vec3d(100) element
    Dim ThePosWeWant As Long = 100
    '---1. easy way: create a DUMMY VIRTUAL t_Vec3d array variable
    '---   pointing its memory to the correct memory position
    Dim lVec3d(MaxPositions) As t_Vec3d At pDataPos
    lVec3d(ThePosWeWant).x = 1
    lVec3d(ThePosWeWant).y = 2
    lVec3d(ThePosWeWant).z = 3
    '---DIM ... AT will never allocate or de-allocate any memory but will only
    '---create a dummy variable that uses the memory allocated by others
    
    
    '---2. little less easy way: create a DUMMY VIRTUAL t_Vec3d single variable
    '---   pointing its memory to the correct memory position making some element calculation
    Dim lVec3dElem As t_Vec3d At pDataPos + (SizeOf(t_Vec3d) * (ThePosWeWant - 1))
    lVec3dElem.x = 4
    lVec3dElem.y = 5
    lVec3dElem.z = 6
                             
    '---You can always set the memory to which a dummy variable point using SetAt
    '---so if you want to access position 10 ...
    ThePosWeWant = 10
    SetAt(lVec3dElem, pDataPos + (SizeOf(t_Vec3d) * (ThePosWeWant - 1)) ) 
    '---Now we have pointed lVec3dElem at position 10
    lVec3dElem.x = 10
    lVec3dElem.y = 20
    lVec3dElem.z = 30
    
    www.thinbasic.com | www.thinbasic.com/community/ | help.thinbasic.com
    Windows 10 Pro for Workstations 64bit - 32 GB - Intel(R) Xeon(R) W-10855M CPU @ 2.80GHz - NVIDIA Quadro RTX 3000

  10. #10
    thinBasic MVPs
    Join Date
    Oct 2012
    Location
    Germany
    Age
    54
    Posts
    1,530
    Rep Power
    171
    I tried, but won't work to copy the data in one step from Dicitonary to myUDT.
    This is the script I'm testing - not working - how can I copy the Array now?

    ' Empty thinBasic CONSOLE file template
    
    Uses "Console", "Dictionary"
    
    
    Type t_myType
      X As Double
      Y As Double
      Z As Double
    End Type
     
    Dim myGlobalUDT() As t_myType
    Dim myDict As DWord = Dictionary_Create(1000)
    Dim lCount As Long
     
    ' fill udt with random elements
    FillUDTRandom()
    ' display what we got
    For lCount = 1 To UBound(myGlobalUDT)
      PrintL "Element" + Str$(lCount) 
      PrintL " X=" + Str$(myGlobalUDT(lCount).X) + " Y=" + Str$(myGlobalUDT(lCount).Y) + " Z=" + Str$(myGlobalUDT(lCount).Z)
    Next lCount
    ' should "write" data from my UDT to Dictionary-Slot "myKey01"
    StoreMyData("myKey01")
     
    FillUDTRandom()
    For lCount = 1 To UBound(myGlobalUDT)
      PrintL "Element" + Str$(lCount) 
      PrintL " X=" + Str$(myGlobalUDT(lCount).X) + " Y=" + Str$(myGlobalUDT(lCount).Y) + " Z=" + Str$(myGlobalUDT(lCount).Z)
    Next lCount
    
    ' and put data away now
    StoreMyData("myKey02")
     
    If RestoreMyData("myKey01") Then
      For lCount = 1 To UBound(myGlobalUDT)
        PrintL "Element" + Str$(lCount) 
        PrintL " X=" + Str$(myGlobalUDT(lCount).X) + " Y=" + Str$(myGlobalUDT(lCount).Y) + " Z=" + Str$(myGlobalUDT(lCount).Z)
      Next lCount
    EndIf
    
    WaitKey
    ' ----------------------------------------------------
    Sub FillUdtRandom()               
      ' just assign some random elements filled with rnd-numbers
      Local i       As Long
      Randomize
      Local nFields As Long = Rnd(2, 9)  
    
      ReDim myGlobalUDT(nFields)   
      
      For i = 1 To nFields
        myGlobalUDT(i).X = Rnd
        myGlobalUDT(i).Y = Rnd
        myGlobalUDT(i).Z = Rnd
      Next i
      
    End Sub 
    ' -------------------------------------------------
    Sub StoreMyData(ByVal sKey As String)
     
      Local pData As DWord = Dictionary_Add(myDict, sKey, String$(UBound(myGlobalUDT) * SizeOf(t_myType),$NUL))
       
      Local lDummy(UBound(myGlobalUDT)) As t_myType At pData
      
    ' next line causes Error, also if I omit the parens 
      lDummy() = myGlobalUDT()
     
    End Sub
    ' --------------------------------------------------
    Function RestoreMyData(ByVal sKey As String) As Boolean
       
      Local pData As DWord = Dictionary_Exists(myDict, sKey)
       
      If Not pData Then Return FALSE
       
      Local lDummy(StrPtrLen(StrPtr(pData))/SizeOf(t_myType)) As t_myType At pData
      ReDim myGlobalUDT(UBound(lDummy))
    
       
      myGlobalUDT() = lDummy()
    
      Function = TRUE 
    
    End Function
    
    Is there an undocumented Heap_Copy or similar that I've overseen?
    Last edited by ReneMiner; 16-03-2013 at 13:09.
    I think there are missing some Forum-sections as beta-testing and support

Page 1 of 4 123 ... LastLast

Similar Threads

  1. Body Mass Index Calculator with Gridlayout for infos
    By largo_winch in forum UI (User Interface)
    Replies: 0
    Last Post: 28-12-2011, 17:47
  2. using byref + strptr
    By largo_winch in forum Tips and Tricks
    Replies: 0
    Last Post: 16-11-2011, 11:40
  3. How to parse a parameter of a LONG type?
    By Michael Hartlef in forum Module SDK (Power Basic version)
    Replies: 7
    Last Post: 27-02-2007, 21:59

Members who have read this thread: 0

There are no members to list at the moment.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •