Usually, global/local declarations are placed right below the method header, not somewhere in some subsequent code block. After all, these declarations apply only to the entire function.
You have to distinguish between simple loop counter variables and variables holding the actual size of the array. In your code, CaseNumberArrayCount describes the size of CaseNumberArray whereas in the answer to which you're referring, it's a counter only used to iterate over the array, which might as well be local.
But you don't have to use two "variables" anyway. Your pseudo array (which can be accessed like CaseNumberArray1, CaseNumberArray2, CaseNumberArray2, ...) has an unused CaseNumberArray0, why not not store the size there?
A pseudo array is actually a collection of sequentially numbered variables. global CaseNumberArray (which by the way you didn't seem to try) will only allow access to the variable named CaseNumberArray, but not CaseNumberArray1 or CaseNumberArray2 and so on.
One solution would be to use Assume-global mode which makes every global variable accessible by default:
; Now, CaseNumberArray0 will hold the array length,
; rendering CaseNumberArrayCount unnecessary
CaseNumberArray0 := 0
; Helper function to load the case number into the array
ReadInputFile() {
; We want to access every global variable we have,
; beware of name conflicts within your function!
global
Loop, Read, test.txt
{
CaseNumberArray0 += 1
CaseNumberArray%CaseNumberArray0% := A_LoopReadLine
}
}
; Here's an alternative: Let AHK build the pseudo array!
ReadInputFileAlternative() {
global caseAlt0
FileRead, fileCont, test.txt
StringSplit, caseAlt, fileCont, `n, `r
}
ReadInputFile()
out := ""
Loop, %CaseNumberArray0%
{
out .= CaseNumberArray%A_Index% "`n"
}
MsgBox, There are %CaseNumberArray0% case(s) in the file:`n`n%out%
; Now, let's test the alternative!
ReadInputFileAlternative()
out := ""
Loop, %caseAlt0%
{
out .= caseAlt%A_Index% "`n"
}
MsgBox, There are %caseAlt0% case(s) in the alternative pseudo-array:`n`n%out%
Edit: "Real Arrays"
As suggested in the comments, here's what I would do instead: I would convince my boss to allow the use of an up-to-date version of AHK and then work with real arrays. This comes with several benefits:
- Real arrays are fully managed by AHK, which means that things like inserting, removing, iterating and indexing can all automagically be done by AHK.
- A real array resides in one real variable, meaning that you can pass it along functions and anywhere you want, without having to worry about the current scope and whether you can access it in the first place.
- The array syntax is very similar to most other languages, making your code intuitive and easier to read. And maybe it helps you in the future when dealing with another language.
- Primitive n-dimensional arrays (and primitive AHK objects in general) can be expressed using JSON. This provides you with an easy way to (de-)serialize AHK objects.
The following code snippet shows the two methods used above (reading loop and splitting), but with real arrays. You will notice that we don't need any global declarations anymore, since we now can declare the array inside our function, and simply pass it back to the caller. In my opinion, this is what functions should really look like: A "black box" that doesn't affect its surroundings.
; Method 1: Line by line
ReadLineByLine(file) {
out := []
Loop, Read, % file
{
out.Insert(A_LoopReadLine)
}
return out
}
; Method 2: StrSplit
ReadAndSplit(file) {
FileRead, fileCont, % file
return StrSplit(fileCont, "`n", "`r")
}
caseNumbers := ReadLineByLine("test.txt")
out := "ReadLineByLine() yields " caseNumbers.MaxIndex() " entries:`n`n"
; using the for loop
for idx, caseNumber in caseNumbers
{
out .= caseNumber "`n"
}
MsgBox % out
caseNumbers := ReadAndSplit("test.txt")
out := "ReadAndSplit() yields " caseNumbers.MaxIndex() " entries:`n`n"
; using the normal loop
Loop % caseNumbers.MaxIndex()
{
out .= caseNumbers[A_Index] "`n"
}
MsgBox % out
MsgBox % "The second item is " caseNumbers[2]