Danks
(Just in Town)
2013-04-02 08:55 AM
Array reference out of bounds error

Hello
I have the following problem. I am getting the following error "array refrence out of bounse" and I can not quite figure out the cause.
Does anyone has a suggestion on how to solve the problem.

The error occurs in the following code in the line( $Groups[$Count] = $Group - marked with red):

PS. I'm not a big KIX script guru ;-)


If (GetFileSize($ULTmpFile + ".iso8859") > 0)

$Err = Open(9,$ULTmpFile + ".iso8859")

$Readln = Readline(9)
While (@Error = 0)

If(InStr($Readln,"cn:"))
$Group = SubStr($Readln, 5,Len($Readln)-4)
; ?"$Group $Count" GET$

$Groups[$Count] = $Group
$Count = $Count + 1
EndIf
$Readln = Readline(9)
Loop

$ULCount = $Count - 1 ; Antallet af Grupper, startende ved 0
; ?"$UlCount"
$ULResult = 0
$Err = Close(9)
Else
$ULResult = 1
EndIf


BradV
(Seasoned Scripter)
2013-04-02 12:21 PM
Re: Array reference out of bounds error

Where do you set $Count initially? Also, you probably have to REDIM PRESERVE it each time you try to increase the size.

Glenn BarnasAdministrator
(KiX Supporter)
2013-04-02 01:15 PM
Re: Array reference out of bounds error

Welcome to KORG!

There are two common methods for working with arrays of unknown size. One is to set the size of the array to an excessively large value, like
Dim $aData[500]
when you know there will be less than 500 elements. A better way is to use ReDim, as Brad referenced..
 Code:
Dim $aData         ; declare array var, no size
Dim $Ptr           ; pointer var

$Ptr = -1          ; set to negative first

; Time to add an element to the array, possibly in a loop
$Line = ReadLine(9)
While Not @ERROR
  $Ptr = $Ptr + 1  ; increase pointer
  ; increase the array size to hold the new data
  ReDim Preserve $aData[$Ptr]
  ; put the data from the file in the array
  $aData[$Ptf] = $Line
  ; read the next data line
  ReadLine(9)
Loop
This method is much preferred as it accurately maintains the size of the array. Of course, you might add logic to this to only add certain lines of data to the array, but the basic concept is the same

Glenn


LonkeroAdministrator
(KiX Master Guru)
2013-04-02 01:38 PM
Re: Array reference out of bounds error

oh, there is a third one:
 Code:
$Readln = Readline(9)
While @Error = 0
 If InStr($Readln,"cn:")
  $Group = SubStr($Readln, 5,Len($Readln)-4)
  $Groupster = $Groupster+chr(9)+$Group
 EndIf
 $Readln = Readline(9)
Loop
$groups=split(substr($groupster,2))


Danks
(Just in Town)
2013-04-04 04:06 PM
Re: Array reference out of bounds error

Thank you for your response. It teased a bit because I did not originally written the code. ;-)
Found out that the size of the array was underestimated and overlooked that it was placed further up in code .....

Is there any reason why Gleen argue that an array must not exceed 500 I can see it's possibil to dimension a array higher .....?


Glenn BarnasAdministrator
(KiX Supporter)
2013-04-04 04:24 PM
Re: Array reference out of bounds error

That was an example.. if you expect an array to hold LESS THAN 500 elements, you can Dim it to 500 and feel safe. It's a common method - overstate your required array size, but any unexpected condition can overload your array and cause an error.

Lonk's method is good for smaller arrays because you need to deal with potential string limits (especially in other languages!). It also can't accommodate Arrays of Arrays, although this is less common.

The second method that I illustrated is usually preferred because it can accommodate any data type in the array, and doesn't result in bound errors if your data exceeds your expectation.

Glenn (with 2 "N"'s and 1 "e"! \:D


AllenAdministrator
(KiX Supporter)
2013-04-04 04:50 PM
Re: Array reference out of bounds error

Ha... the return of Gleen. Where have you been my friend.

ChristopheM
(Hey THIS is FUN)
2013-04-04 07:04 PM
Re: Array reference out of bounds error

I use an other solution to load file because resizing array at each line can be expensive in time and memory.
 Code:
function LoadArrayFromFile( $filename, optional $PtrMax, optional $PtrInc )
  if vartype($PtrMax)=0    $PtrMax = 1024   endif    ; initialize max size
  if vartype($PtrInc)=0    $PtrInc = 256    endif    ; initialize increment size

  dim $Ptr                 $Ptr = -1                 ; set pointer to negative first
  dim $handle              $handle = freefilehandle()

  if open( $handle, $filename )=0
    redim $LoadArrayFromFile[$PtrMax] ; declare array var with a predefined size
    dim $line

    ; Time to add an element to the array, possibly in a loop
    $Line = ReadLine($handle)
    While Not @ERROR
      $Ptr = $Ptr + 1                                ; increase pointer
      if $Ptr > $PtrMax
	    $PtrMax = $PtrMax + $PtrInc                  ; increase array max size
        ReDim Preserve $LoadArrayFromFile[$PtrMax]   ; resize array
      endif

      $LoadArrayFromFile[$Ptr] = $Line               ; put data in array
      $Line = ReadLine($handle)                      ; read the next data line
    Loop

    $ = close($handle)
  endif

  if $Ptr=-1
    ; nothing read in the file or file not opened
	$LoadArrayFromFile = ""
	exit 1
  else
    ReDim Preserve $LoadArrayFromFile[$Ptr]
	exit 0
  endif
endfunction
This is a function that allows to define initial size of the array and increment size when array becomes too small to load next data.

See below how to test with differents sizes of buffer and increment
 Code:
$=SetOption( "Explicit", "ON" )

dim $filename, $arr, $start

$filename = "<name of a large file for test>"

$start=@TICKS
$arr = LoadArrayFromFile( $filename, 0, 1 )
$start=@TICKS-$start
"Loaded line by line (   0,   1) in " $start " ms" ?

$start=@TICKS
$arr = LoadArrayFromFile( $filename )
$start=@TICKS-$start
"Loaded with default (1024, 512) in " $start " ms" ?

$start=@TICKS
$arr = LoadArrayFromFile( $filename, 4096, 4096 )
$start=@TICKS-$start
"Loaded with buffer  (4096,4096) in " $start " ms" ?


with a file of 32000 lines (1,1MB), here are the results :
 Code:
Loaded line by line (    0,   1) in 469 ms
Loaded with default ( 1024, 512) in 312 ms
Loaded with default ( 4096,4096) in 297 ms


Glenn BarnasAdministrator
(KiX Supporter)
2013-04-04 07:23 PM
Re: Array reference out of bounds error

LOL - I was going to mention this concept to improve performance but decided it was too complex for this discussion. So - there it is - nicely done! \:\)

Glenn BarnasAdministrator
(KiX Supporter)
2013-04-15 09:43 PM
Re: Array reference out of bounds error

Just to follow-up on this, I revisited the FileIO UDF that I had written some time ago. I found that I had used Lonk's "build a delimited string and split" method. I had been planning on updating it to use a stepped-dynamic array method and finally got around to it today.

To compare the performance of the old and new methods, I created a simple text file of about 380KB, with just under 5000 lines. The old "build & split" method took 28.157 seconds to load this file into the array and resulted in an array with an extra, empty element. Using the newer "Stepped-dynamic" method that Christophe illustrated above (with a base/increment of 500 elements), loading the same file took a whopping 0.125 seconds (yes, an eighth of a second!).

Bottom line, I should have updated the UDF to this method years ago!

Glenn