Jump to content

variable variables


Recommended Posts

I need to read in some values from an INI file that looks something like this:

[JOBS]

JOB1 = whatever

JOB2 = blah blah

JOB3 = yadda

[JOB1]

INC1 = a

INC2 = b

INC3 = c

[JOB2]

INC1 = d

INC2 = e

INC3 = f

INC4 = g

[JOB 3]

INC1 = h

INC2 = i

But each "JOB" section has an unknown number of entries, plus there are an unknown number of JOBS ("unknown" isn't the right word... "variable")

My first thought is to use IniReadSection nested like this:

$jobs = IniReadSection ( $INI, "JOBS" )
Global $NumJobs = $jobs[0][0]
For $i = 1 To $NumJobs
    $includes = IniReadSection ( $INI, "JOB" & $i )
    If Not @error Then
        $NumIncludes = $includes[0][0]
        Global $jobinclude[$NumJobs+1][$NumIncludes+1]
        For $j = 1 To $NumIncludes
            $jobinclude[$i][$j] = $includes[$j][1]
        Next
    EndIf
Next
MsgBox ( 0, "TEST", $jobinclude[2][2] ); answer should be "e"

But I get problems with the array since the number of secondary elements varies. I thought from there I'd be able to grab any combination , say $jobinclude[2][2] would give me "e"... and $jobinclude[3][1] would be "h". It doesn't work though, at least not as I've scripted it... no error... just gives me a blank value unless I check within the nested loop... then it will give me the proper value at the corresponding iteration of the loop - but it does not seem to remember the values outside of the loop. I can't figure out why this is the case.

So if I can't use a two-dimensional array, then I figured I could just use a bunch of variables, but I wouldn't know how many to declare or what syntax, if any, is appropriate. Eg.

For $i = 1 to $x
   Dim $variable$i
Next
is the idea but won't work.

Thoughts? Thanks.

LD

Link to comment
Share on other sites

$INI = "C:\Temp\Myfile.ini"
Dim $i, $j
$jobs = IniReadSectionNames($INI)

For $i = 1 To $jobs[0]
    $includes = IniReadSection ( $INI, $jobs[$i])
    If Not @error Then
        For $j = 1 To $includes[0][0]
            MsgBox ( 64, $jobs[$i],"Key: " & $includes[$j][0] & @CRLF & " Value: " & $includes[$j][1])
        Next
    EndIf
Next
MsgBox ( 0, "TEST", $includes[2][1] ); answer should be "i" - because $includes is in the loop of "jobs" and re-read on every "i" to $jobs

8)

NEWHeader1.png

Link to comment
Share on other sites

You mean answer should be $i, no "i" - right? From my sample ini it would be "d". Thanks - I didn't think about using the IniReadSectionNames function. However, that reads in ALL section names so I'd have to introduce some control statements to weed out the non "JobX" sections.

I also realized what I was doing wrong in my initial script. The line that read:

Global $jobinclude[$NumJobs+1][$NumIncludes+1]

of course was in side the For $i loop so it was constantly clearing the array... setting a value within it, and clearing it again, and so on. So I have to bring that outside of the for $i loop. Unfortunately, I would have no way of knowing what $NumIncludes was then (because it is generated within the loop) so instead I have to declare the variable like so:

Global $jobincludes[$NumJobs+1][99]

and do so before the For $i loop. I'd rather not do that, because I don't want to impose some artificial limit on the number of includes a job can have... Valuator's idea is pretty clean. So I'll either modify that (thank you!) or live with artificial limits.

Thanks a lot for giving me something to go on.

LD

Link to comment
Share on other sites

Still having problems. After working with your code Valuator, I'm not sure it really solves it... I'm still stuck not knowing how large to declare the two-dimensional array.

So can I declare the first dimension, and then the second dimension later? Probably not.

Basically, I can tell how big $i will be - but I have no idea how big $j will be for each $i until after the fact... and unfortunately, the array[$i][$j] needs to be declared first with the number of elements in each.

LD

Link to comment
Share on other sites

  • Moderators

Hi London... do you have a test.ini to work with that you can upload?

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

Posted at the top... pretty simple format really... the first section lists the jobs and the later sections named JOBx list the includes for each job.

But anyway, I figured out the key to the problem... the "redim" function.

original code:

$jobs = IniReadSection ( $INI, "JOBS" )
Global $NumJobs = $jobs[0][0]
For $i = 1 To $NumJobs
    $includes = IniReadSection ( $INI, "JOB" & $i )
    If Not @error Then
        $NumIncludes = $includes[0][0]
        Global $jobinclude[$NumJobs+1][$NumIncludes+1]
        For $j = 1 To $NumIncludes
            $jobinclude[$i][$j] = $includes[$j][1]
        Next
    EndIf
Next
MsgBox ( 0, "TEST", $jobinclude[2][2] ); answer should be "e"

working code:

$jobs = IniReadSection ( $INI, "JOBS" )
Global $NumJobs = $jobs[0][0]
Global $jobinclude[$NumJobs+1][1];Declare variable here with an arbitrary 2nd dimension.
For $i = 1 To $NumJobs
    $includes = IniReadSection ( $INI, "JOB" & $i )
    If Not @error Then
        $NumIncludes[$i] = $includes[0][0]
        If ($NumIncludes[$i] > $NumIncludes[$i-1]) Or $i = 1 Then
                Redim $jobinclude[$NumJobs+1][$NumIncludes[$i]+1]
        EndIf
        For $j = 1 To $NumIncludes[$i]
            $jobinclude[$i][$j] = $includes[$j][1]
        Next
    EndIf
Next
MsgBox ( 0, "TEST", $jobinclude[2][2] ); answer should be "e"

This now works because before I was re-declaring the $jobinclude array and it was wiping out its contents on each iteration... with "Redim" (which keeps the "Global" scope, btw) it changes the size of the dimension without wiping out the contents! I add that last If statement because there's no reason to Redim unless the array is getting larger in the current iteration - if it is the same size (ie same number of includes as the previous job) then it doesn't have to be re-declared at all.

I haven't fully tested this yet, but it seems to work.

LD

*edit* I also realized I was thinking of $NumIncludes as a scalar originally, when it is an array itself.... ie. $NumIncludes[1] = 3, $NumIncludes[2] = 4, $NumIncludes[3] = 2 (from the sample INI at the top)

Edited by LondonNDIB
Link to comment
Share on other sites

this worked also

#include <GuiConstants.au3>

$INI = "C:\Temp\Myfile.ini"
Dim $max = 7; number of maximum labels needed
Dim $i, $j
Dim $label[8]
Dim $input[8]
Dim $top = 50
$jobs = IniReadSectionNames($INI)

$win = GUICreate("My GUI")

$combo1 = GUICtrlCreateCombo("", 50, 10, 200, 20)
for $p = 1 to $jobs[0]
    If $jobs[$p] = "JOBS" Then ContinueLoop
    GUICtrlSetData( $combo1, $jobs[$p] & "|", 1)
Next

$view = GUICtrlCreateButton("View List", 270, 10, 80, 20)

for $t = 1 to $max; the max number of labels needed
    $label[$t] = GUICtrlCreateLabel("XXX", 20, $top, 100, 20)
    $input[$t] = GUICtrlCreateInput("", 150, $top, 150, 20)
    $top = $top + 50
Next

GUISetState()

While 1
    $msg = GUIGetMsg()
    Select
; Main window controls
        Case $msg = $GUI_EVENT_CLOSE 
            ExitLoop
        Case $msg = $View
            View()
    EndSelect
WEnd

Func View()
    $jobs = IniReadSectionNames($INI)
For $i = 1 To $jobs[0]
    If $jobs[$i] = GUICtrlRead($combo1) Then
        $includes = IniReadSection ( $INI, $jobs[$i])
        For $j = 1 To $includes[0][0]
           GUICtrlSetData($label[$j], $includes[$j][0])
           GUICtrlSetData($input[$j], $includes[$j][1])
        Next
       If $j < $max Then
           For $r = $j to $max
               GUICtrlSetData($label[$r], "")
                GUICtrlSetData($input[$r], "")
            Next
        EndIf
        Return
    EndIf
Next

EndFunc

1

this removes "JOBS" from the list

2

I am trying to show you that you dont NEED to set the $array length to use the info

Hope that helps

8)

Edited by Valuater

NEWHeader1.png

Link to comment
Share on other sites

1) I appreciate that! But in my particular case, I need the JOBS section any way for a bunch more info outside of this "includes" business. So for my purposes, its there anyway and was handy to use... but I agree it is not necessary to solve my problem as described.

2) Not really. Your method still has the distinct problem of not being valid outside of the loop. The include[j] values aren't persistent. In other words, add

MsgBox ( 0, "", $includes[1][1] )
immediately before your "return" in the loop and you will see that it returns whatever the first value for that particular job is instead of the proper
constant value of "a" (at least in the example INI posted at the top of this thread). Try to get $includes[2][2] and you get a fault in the code because the second dimension can never be higher than "1" in your code... thereby effectively making it a single-dimensional array. To make it truely multi-dimensional (instead of a single dimensional that constantly over-writes itself - the same problem I was struggling with to begin with) you need to either know/declare its size ahead of time, or use the Redim function as I "discovered"

Thank you so very much for your efforts!

LD

Edited by LondonNDIB
Link to comment
Share on other sites

Both, I suppose. As a multi-dimensional array, the data can be called up and used/modified whenever and wherever I want later on in the script.

I feel its the better method for solving the problem of "variable variables"... your solution definately solves the specific example I posed. What I probably didn't clarify enough was that the example ini was really stripped down for this post - it doesn't resemble my actual situation at all - and it was the overall concept I needed help with - that of multidimensional arrays. Recall that from my first post, I wrote:

But I get problems with the array since the number of secondary elements varies. I thought from there I'd be able to grab any combination , say $jobinclude[2][2] would give me "e"... and $jobinclude[3][1] would be "h". It doesn't work though, at least not as I've scripted it... no error... just gives me a blank value unless I check within the nested loop... then it will give me the proper value at the corresponding iteration of the loop - but it does not seem to remember the values outside of the loop. I can't figure out why this is the case.

So I thought it was clear I would require a method for grabbing a specific $jobinclude[x][y] value. Redim, as it turns out, was the key to making that possible.

LD

Link to comment
Share on other sites

Thank you. And seriously.... thank you for your help! I didn't mean to belittle your efforts at all and I hope I didn't - I just think that my self-discovered solution worked better in my particular situation... but it was your original suggestion that led me in that direction anyway!

I appreciate it.

LD

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...