quickest way to fill arrays without a macro

Just starting out? Need help? Post your questions and find answers here.
nsstudios
Enthusiast
Enthusiast
Posts: 275
Joined: Wed Aug 28, 2019 1:01 pm
Location: Serbia
Contact:

quickest way to fill arrays without a macro

Post by nsstudios »

Hi,

I'm wondering what is the quickest way to fill arrays without using a macro or a function.
The quickest way I've found is:

Code: Select all

DataSection
arr:
Data.i @"this",@"is",@"a",@"test"
arrEnd:
EndDataSection
Dim arr.s(3)
CopyMemory(?arr, arr(), ?arrEnd-?arr)

For i=0 To ArraySize(arr())
Debug arr(i)
Next
but I don't understand why it doesn't work with real string data. Is there a way to make it do, or is there a better way?
Also, I wonder if it'd be possible to automatically resize the array while copying the data?
If I use a static array in a structure it does it, but not with the dynamic one.

Code: Select all

Structure sarr
s.s[0]
endStructure
CopyMemory(?arr, s.sarr, ?arrEnd-?arr)
I've seen other tricks, e.g., fill macro, json hack, but all of those are lengthy compared to this that is technically two lines if I could have the labels on the same line.
Of course, something like array()=("this","is","a","test") would be a dream come true, but a man can dream, I guess.
:cry:
:lol:
User avatar
NicTheQuick
Addict
Addict
Posts: 1227
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: quickest way to fill arrays without a macro

Post by NicTheQuick »

Code: Select all

Structure sarr
s.s[0]
endStructure
CopyMemory(?arr, s.sarr, ?arrEnd-?arr)
The structure "sarr" has a length of 0. You need to allocate enough space to copy the pointers of the strings in the datasection into "s". Like so:

Code: Select all

DataSection
	arr:
	Data.i @"this",@"is",@"a",@"test"
	arrEnd:
EndDataSection

Structure sarr
	s.s[0]
EndStructure

Define *s.sarr = AllocateMemory(SizeOf(String) * 4)

CopyMemory(?arr, *s, ?arrEnd-?arr)

For i=0 To 3
	Debug *s\s[i]
Next
Or without copying like so:

Code: Select all

DataSection
	arr:
	Data.i @"this",@"is",@"a",@"test"
	arrEnd:
EndDataSection

Structure sarr
	s.s[0]
EndStructure

Define *s.sarr = ?arr

For i = 0 To (?arrEnd - ?arr) / SizeOf(String) - 1
	Debug *s\s[i]
Next
But you should only use this dirty trick to read the strings, not for changing it.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
User avatar
mk-soft
Always Here
Always Here
Posts: 5409
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: quickest way to fill arrays without a macro

Post by mk-soft »

This has been requested several times.

Look out! With your method, the array can only be read. NOTHING ELSE.

With Purebasic you can manipulate pointers very well. So you can manipulate pointers that don't fit together.
You have to be very careful yourself.

Code: Select all

Structure IntegerArray
  i.i[0]
EndStructure

Structure StringArray
  s.s[0]
EndStructure

DataSection
arr:
Data.i @"this",@"is",@"a",@"test",@"with",@"array"
arrEnd:
Data.i #Null
EndDataSection

Procedure FillStringArray(sBegin.i, sEnd.i, Array String.s(1))
  Protected cnt, i, *String.String
  cnt = (sEnd - sBegin) / SizeOf(Integer) - 1
  Dim String(cnt)
  *string = sBegin
  For i = 0 To cnt
    String(i) = *String\s
    *String + SizeOf(Integer)
  Next
  ProcedureReturn cnt
EndProcedure

Debug "*** Create copy for change string ***"
Dim arr.s(0)
FillStringArray(?arr, ?arrEnd, arr())

For i=0 To ArraySize(arr())
Debug arr(i)
Next

FreeArray(arr())

Debug "*** Read Only !!! ***"
*arr.StringArray = ?arr
i = 0
Repeat
  If *arr\s[i] = ""
    Break
  EndIf
  Debug *arr\s[i]
  i + 1
ForEver

My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
nsstudios
Enthusiast
Enthusiast
Posts: 275
Joined: Wed Aug 28, 2019 1:01 pm
Location: Serbia
Contact:

Re: quickest way to fill arrays without a macro

Post by nsstudios »

Wow.
Thanks for the help and for pointing out the read-only problem.
My original idea was to have something that would make it faster to access and easier to type than string field with a delimited string.
Why is it impossible to write to an element after doing that, though?
Even more importantly, why does the executable just die without a debugger error if I try to do it anyway?
Also, what I meant was: why can't I do the same trick with pure string data instead of addresses?

Code: Select all

arr:
data.s "this","is","a","test"
arrEnd:
When I try to copy arr to either sarr or the dynamic array, it gives me invalid memory access.
BTW, I know it's been requested.
:cry:
I stumbled across great requests/improvements, and it makes me sad/frustrated at times to see that a lot of them haven't been implemented, particularly things like quick initializing of arrays, ternary operator-like functionality (which I use all the time, except it's a macro/function pair so there's a performance hit), faster string concatenation, the if map("key")=value bug that erroneously adds a new element, etc.
alaphate
New User
New User
Posts: 4
Joined: Tue May 12, 2020 10:06 am

Re: quickest way to fill arrays without a macro

Post by alaphate »

I'm newbie for purebasic.
The code below can only split a string to a string-type array.

Code: Select all

Procedure split(Array myArray.s(1),fromStr$, delimiter$=",")
  Protected i, uBound
  uBound = CountString(fromStr$, delimiter$)
  ReDim myArray(uBound)
  For i = 1 To uBound+1
    myArray(i-1) = Trim(StringField(fromStr$, i, delimiter$))
  Next i
EndProcedure

;;;;; how To use the Procedure
Dim fruits.s(1)
split(fruits(), "apple, banana, orange")

;;;;; test the array
Define i
For i = 0 To ArraySize(fruits())
  Debug fruits(i)
Next i
Post Reply