Arrays problem

Need help with a macro you are writing? Ask here!

Moderator: MacroQuest Developers

[40oz]
a hill giant
a hill giant
Posts: 156
Joined: Tue Nov 12, 2002 12:14 pm

Arrays problem

Post by [40oz] » Mon Oct 11, 2004 9:34 pm

Ok, so I got a wierd problem, I'm trying to fix a macro that I've been updating and I've run across this problme with arrays

Heres what I got, a splitstring sub that makes a global array and populates that array with each string inbetween a defined splitter such as |

Problem is, I get this error when running my macro:

Code: Select all

/varset 'targets[-1]' failed, out of bounds on array

@1609 (SplitString(string varname, string inputstring, string splitter)): /varset ${varname}[${C}] ${inputstring.Left[${i}]}

@262 (Main): /call SplitString targets "${Param0}" "|"
Here is my splitstring sub (yes, it's from nbh)

Code: Select all

|----------------------------------------------------------------------------
|SUB: SplitString - A generic string splitter.
|----------------------------------------------------------------------------
Sub SplitString(string varname, string inputstring, string splitter)
    |A variable with name in varname will be declared and filled
    /declare i int local
    /declare i2 int local
    /declare c int local
    /declare stringcnt int local

    /varcalc stringcnt ${inputstring.Count["|"]} + 1
    
    /if (!${Defined[${varname}]}) { 
        /declare ${varname}[${stringcnt}] string global
    } else {
        /deletevar ${varname}
        /declare ${varname}[${stringcnt}] string global
    }
    
    /varset c 1
:nextsubstring
    /varcalc i ${inputstring.Find["${splitter}"]} - 1
    |/echo ${inputstring}:${splitter} ${inputstring.Find["${splitter}"]}
    /if ( ${i}>-1 ) {
    	|/echo iii: ${inputstring.Length} ${inputstring} ${i}
         /varcalc i2 ${inputstring.Length} - ${i} +1
        | /varcalc i2 ${inputstring.Length} - ${i} - 1 BUGFIX?????
        /varset ${varname}[${c}] ${inputstring.Left[${i}]}
        /varcalc c ${c} + 1
        |/echo stringarray[${c}] ${inputstring.Left[${i}]}

        /varset inputstring ${inputstring.Right[${i2}]}
         
         /goto :nextsubstring

     } else {
          |/echo stringarray[${c}] ${inputstring}
          /varset ${varname}[${c}] ${inputstring}
     }

/return
sorry about the debug echos, been trying to figure out what the cause of my issue is

I thought maybe the issue was needing to force the first param in as a string as such:

Code: Select all

/call SplitString "targets" "${Param0}" "|"
This did not fix the issue. Calling it the way I used to:

Code: Select all

/call SplitString targets "${Param0}" "|"
Does not work either.

Also, here is some test input that I've used

/call mac skele|pawn
/call mac lion|spider
/call mac skele

no good on any of em

Am I missing something?

edit: added error message that made me title thread way i did.
edit2: adding in the input i'm using specifically for this particular array error, though i've tried many different entires for testing
Last edited by [40oz] on Tue Oct 12, 2004 1:30 am, edited 2 times in total.

User avatar
dont_know_at_all
Developer
Developer
Posts: 5450
Joined: Sun Dec 01, 2002 4:15 am
Location: Florida, USA
Contact:

Post by dont_know_at_all » Mon Oct 11, 2004 11:58 pm

What's the actual error?

[40oz]
a hill giant
a hill giant
Posts: 156
Joined: Tue Nov 12, 2002 12:14 pm

Post by [40oz] » Tue Oct 12, 2004 1:25 am

oh, heh sorry. looking it up and editing my first post. can't believe i forgot to post the stinkin error 0.o

edit: Also felt this necessary to mention; I took this from an unmodified macro that worked a couple months ago. It is making me think that something has changed with one of the member functions I am using, and thus I need to modify my code to work around that. A dev would know best if some of the string member functions are not working as intended, or have been changed. But on top of it all I don't understand why I'm getting the problem as an out of bounds issue. Gonna do some oneliner testing in game and see if I can figure it out.

User avatar
dont_know_at_all
Developer
Developer
Posts: 5450
Joined: Sun Dec 01, 2002 4:15 am
Location: Florida, USA
Contact:

Post by dont_know_at_all » Tue Oct 12, 2004 1:46 am

/varcalc i ${inputstring.Find["${splitter}"]} - 1

The find is returning NULL, so inputstring has no |.

[40oz]
a hill giant
a hill giant
Posts: 156
Joined: Tue Nov 12, 2002 12:14 pm

Post by [40oz] » Tue Oct 12, 2004 1:47 am

Heres some more info on the subject, I ran this little puppy in game as a test:

Code: Select all

Sub Main

   /declare test string local  "Hello"

   /echo ${test.Find["e"]}
   /echo ${test.Count["l"]}

/return
and my responses were

Code: Select all

[MQ2] 3
[MQ2] 2
now, 2 'l's is correct. But the first occurance of 'e' being in string position 3 makes no sense, if you subtract 1, then you have the non-zero offset for the first occurance of e.

Unless when you declare a string like this it includes the quotation marks, which is now making me shake my head in agony

edit: indeed it does, an /echo of ${test} in above example puts out exactly: "Hello" don't know if that relates to my problem but it's good to know

[40oz]
a hill giant
a hill giant
Posts: 156
Joined: Tue Nov 12, 2002 12:14 pm

Post by [40oz] » Tue Oct 12, 2004 1:50 am

Ah, DKAA - I think between your response and my string messing, I have an idea - working on it.

[40oz]
a hill giant
a hill giant
Posts: 156
Joined: Tue Nov 12, 2002 12:14 pm

Post by [40oz] » Tue Oct 12, 2004 2:04 am

Ok using this strategically placed /mqpause

Code: Select all

|----------------------------------------------------------------------------
|SUB: SplitString - A generic string splitter.
|----------------------------------------------------------------------------
Sub SplitString(string varname, string inputstring, string splitter)
    |A variable with name in varname will be declared and filled
    /declare i int local
    /declare i2 int local
    /declare c int local
    /declare stringcnt int local

    /varcalc stringcnt ${inputstring.Count["|"]} + 1
    
    /if (!${Defined[${varname}]}) { 
        /declare ${varname}[${stringcnt}] string global
    } else {
        /deletevar ${varname}
        /declare ${varname}[${stringcnt}] string global
    }
    
    /varset c 1

:nextsubstring
    /varcalc i ${inputstring.Find["${splitter}"]} - 1


    /echo stringcnt: ${stringcnt}  splitter: ${splitter}  inputstring: ${inputstring}  /echo i: ${i}
    /mqpause

    /if ( ${i}>-1 ) {
        /varcalc i2 ${inputstring.Length} - ${i} +1

        | /varcalc i2 ${inputstring.Length} - ${i} - 1 BUGFIX?????

        /varset ${varname}[${c}] ${inputstring.Left[${i}]}
        /varcalc c ${c} + 1

        /varset inputstring ${inputstring.Right[${i2}]}
         
        /goto :nextsubstring

     } else {
          /varset ${varname}[${c}] ${inputstring}
     }

/return
and calling the macro with

Code: Select all

/mac mac Hello|World
Heres what I get:

Code: Select all

[MQ2] stringcnt: 2  splitter: |  inputstring: Hello|World  /echo i: 5
Macro is paused.
Macro is running again.
[MQ2] stringcnt: 2  splitter: |  inputstring: o|World  /echo i: 1
Macro is paused.
Macro is running again.
[MQ2] stringcnt: 2  splitter: |  inputstring: o|World  /echo i: 1
Macro is paused.
Macro is running again.
/varset 'targets[-1]' failed, out of bounds on array
This tells me that the first word isn't getting removed completely, for whatever reason, so it tries thes econd word more than once, and it knows it only needs to get 2 words, so when it tries the third of course it's out of range.

Now to fix it. Sometimes all I have to do is spell this out in writing to somebody else and I figure it out. Thanks for reading, even though you probably don't care ^_^

edit: fixed a critical grammar error, and still looking for suggestion on best fix.

[40oz]
a hill giant
a hill giant
Posts: 156
Joined: Tue Nov 12, 2002 12:14 pm

Post by [40oz] » Tue Oct 12, 2004 2:11 am

Fixed it, uncommented the BUGFIX line i had in there, and commented out the corresponding line above it, and the math work out, now to test it to hell and back

[40oz]
a hill giant
a hill giant
Posts: 156
Joined: Tue Nov 12, 2002 12:14 pm

Post by [40oz] » Tue Oct 12, 2004 2:24 am

Ok, so my fix worked short term, but it wasn't providing the right logic I needed. I found another version of this function and ehre it is:

Code: Select all

|----------------------------------------------------------------------------
|SUB: SplitString - A generic string splitter.
|----------------------------------------------------------------------------
Sub SplitString(string varname, string inputstring, string splitter)
    |/echo varname: "${varname}", inputstring: "${inputstring}", splitter: "${splitter}"
    /declare i int local
    /declare stringcnt int local
    
    |The normal splitter. Splitter string is just 1 in length.
    /if (${splitter.Length}==1) {
        /varcalc stringcnt ${inputstring.Count["${splitter}"]} + 1
        
        /if (!${Defined[${varname}]}) { 
            /declare ${varname}[${stringcnt}] string outer
        } else {
            /deletevar ${varname}
            /declare ${varname}[${stringcnt}] string outer
        }
        
        /for i 1 to ${stringcnt}
            /varset ${varname}[${i}] ${inputstring.Token[${i},"${splitter}"]}
        /next i
    } else {
    
        |The TOKEN method on string does not support splitters of length>1
        /declare tmp string local
        /varset tmp ${inputstring}
        /declare i2 int local
:FindCount
        /if ( ${tmp.Find["${splitter}"]} ) {
            /varset i ${tmp.Find["${splitter}"]}
            /varset tmp ${tmp.Left[${Math.Calc[${i}-1]}]}${tmp.Right[${Math.Calc[${tmp.Length}-${i}-${splitter.Length} +1]}]}
            /varcalc stringcnt ${stringcnt} + 1
            /if ( ${tmp.Find["${splitter}"]} ) /goto :FindCount
        }
        /varcalc stringcnt ${stringcnt} + 1

        /if (!${Defined[${varname}]}) { 
            /declare ${varname}[${stringcnt}] string outer
        } else {
            /deletevar ${varname}
            /declare ${varname}[${stringcnt}] string outer
        }

        |Find the parts.
        /varset tmp ${inputstring}
        /for i 1 to ${stringcnt}
            /if ( ${tmp.Find["${splitter}"]} ) {
                /varset i2 ${tmp.Find["${splitter}"]}
                /varset ${varname}[${i}] ${tmp.Left[${Math.Calc[${i2}-1]}]}
                /varset tmp ${tmp.Right[${Math.Calc[${tmp.Length}-${i2}-${splitter.Length} +1]}]}
            } else {
                /varset ${varname}[${i}] ${tmp}
            }
        /next i
    }
/return
This works, but it seems way to bloated for me. It's 1:30 am here, I don't feel like messing with my less bloated version anymore, gonna conk off for the night. If anyone wants to see if they can unbloat that, be my guess.

User avatar
Cr4zyb4rd
Plugins Czar
Posts: 1449
Joined: Tue Jul 20, 2004 11:46 am

Post by Cr4zyb4rd » Tue Oct 12, 2004 3:19 am

Unless when you declare a string like this it includes the quotation marks, which is now making me shake my head in agony
Quotation marks are almost never stripped by MQ2. It makes a lot of sense for a macro language to handle the strings "raw", (too many functions take multi-word strings as a single argument) but I've also found it to be a pain in the arse on occasion.