Jump to content

The usual "Array" of problems


 Share

Recommended Posts

So I had a piece of code that was giving the dreaded error:

"Array variable has incorrect number of subscripts or subscript dimension range exceeded"

I read the forums searching for the answer...found many answers, just not the one I needed. I spent several hours fiddling and wondered what could be going on. Frustrating! Mystifying. If it were a complex script this might be expected...but it all seemed so simple....

Finally I found the answer, and I want to share it...I would call what I found a bug, but perhaps it is simply a lack of fastidious programming on my part. What do you think?

#include <Array.au3>
#include <file.au3>

$logfile="c:\logfile"
$datfile="c:\datfile"

Dim $alist[50000]
Dim $foundfiles[300]

If _FileReadToArray ( $logfile, $foundfiles ) Then
    ;define some variables
    ;ReDim $foundfiles[300]
EndIf


If Not _FileReadToArray($datfile, $alist) Then
    MsgBox(4096,"Error", " Error reading alist to Array     error:" & @error)
    Exit
EndIf

For $x = 1 to 10 ; scan the last 10 records.
    $ID = $alist[$alist[0]-8*$x] ;records are in 8 line chunks, read backwards through the chunks
    If _ArraySearch ( $foundfiles, $ID, 1 ) == -1 Then ;record not found in array
        $foundfiles[0] += 1   ;increment the number of elements in the array
        $foundfiles[$foundfiles[0]] = $ID   ;add to array
        FileWrite ($logfile, $ID & @CRLF)
    Else
            ;the ID was already added.
    EndIf
Next

This is a stripped down version that should illustrate the issue.

logfile contains a list of ID numbers that were found by the program. They are saved as they are found, and when the program is run, the logfile is loaded into memory so we can be sure we are not re-adding ones we've found before.

datfile contains records. We are exracting the ID from each record and saving it. There are 8 lines per record, ID is the first line.

The script would load all the elements from logfile easily. The For - Next loop was itself within a loop that would monitor for changes in datfile periodically (by scanning the last 10 records). When new records were found, it would grab those ID's. But I would get "the error" after getting 1 or 2 new records. The line:

$foundfiles[$foundfiles[0]] = $ID ;add to array

was the source of the error. I tried:

Global $foundfiles[300]

and other simple things that didn't help. Finally I realized that despite my declaration of:

Dim $foundfiles[300] or Global $foundfiles[300]

the _FileReadToArray was returning an array containing only the number of elements it read from $logfile. I added the ReDim command (that is commented out):

ReDim $foundfiles[300]

and viola...it worked.

So, is this a bug in the way the array is being passed to and from _FileReadToArray (UDF)? Perhaps an error in the StringSplit function at the heart of the UDF? Or do I in fact deserve a slap on the back of my hand?

Edited by wonderer
Link to comment
Share on other sites

#include <Array.au3>
#include <file.au3>

$logfile="c:\logfile"
$datfile="c:\datfile"

;Dim $alist[50000];<<<<<<< Removed and replaced with following
$aList = ""
;Dim $foundfiles[300];<<<<<<<< Removed and replaced with following
$FoundFiles = ""

If _FileReadToArray ( $logfile, $foundfiles ) Then
  ;define some variables
  ;ReDim $foundfiles[300]
EndIf


If Not _FileReadToArray($datfile, $alist) Then
    MsgBox(4096,"Error", " Error reading alist to Array  error:" & @error)
    Exit
EndIf

For $x = 1 to 10; scan the last 10 records.
    $ID = $alist[$alist[0]-8*$x];records are in 8 line chunks, read backwards through the chunks
    If _ArraySearch ( $foundfiles, $ID, 1 ) == -1 Then;record not found in array
        $foundfiles[0] += 1 ;increment the number of elements in the array
        $foundfiles[$foundfiles[0]] = $ID ;add to array
        FileWrite ($logfile, $ID & @CRLF)
    Else
          ;the ID was already added.
    EndIf
Next

If _FileReadToArray() is the only function you are using from File.au3 Then you might want to try this modified version. It does not require that you pre-declare the array at all

Func _FileReadToArray($sFilePath)
Local $hFile
    $hFile = FileOpen($sFilePath, 0)
    If $hFile = -1 Then
        SetError(1)
        Return 0
    EndIf
    $aArray = StringSplit( StringStripCR( FileRead($hFile, FileGetSize($sFilePath))), @LF)
    FileClose($hFile)
    Return $aArray
EndFunc

Edit:

I should have showed how to call the function

$foundFiles = _FileReadToArray($logfile)
Edited by GEOSoft

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Link to comment
Share on other sites

;...

Finally I realized that despite my declaration of:

Dim $foundfiles[300] or Global $foundfiles[300]

the _FileReadToArray was returning an array containing only the number of elements it read from $logfile. I added the ReDim command (that is commented out):

ReDim $foundfiles[300]

and viola...it worked.

So, is this a bug in the way the array is being passed to and from _FileReadToArray (UDF)? Perhaps an error in the StringSplit function at the heart of the UDF? Or do I in fact deserve a slap on the back of my hand?

You get the slap. _FileReadToArray() did exactly what it was supposed to do, completely replaced the specified array with a new one of the file's lines. The variable name needed to be declared before hand, but didn't even have to be declared as an array. Nothing about the variable, including its type or length, are preserved. That is normal for AutoIt's variables, they are not "strongly typed" as might be expected from dealing with other languages.

<_<

P.S. The modified function posted by GeoSoft will do the same (replace the old Type/Size/Content of the variable the return is saved to).

Edited by PsaltyDS
Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law
Link to comment
Share on other sites

You get the slap.

<_< Thanks...i needed that!

P.S. The modified function posted by GeoSoft will do the same (replace the old Type/Size/Content of the variable the return is saved to).

I figured as much. It would be nice if it were more explicit in the documentation that this was the behavior. Perhaps it does exist and I haven't studied the documentation thoroughly enough.

Anyhow, hope this discussion will help someone else...perhaps I'll post a tutorial at some point on the various ways to elicit / repair this error.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...