Jump to content

Problem with Arrays


Recommended Posts

Wow, i thought i was done with my "Array" of problems

Here's my code:

#Include <File.au3>
#Include <Array.au3>

_CleanupHostFile()



Func _CleanupHostFile($sPath = "C:\WINDOWS\system32\drivers\etc\hosts")
    Local $avHost
    If $sPath = "" Then
        Return -1
    EndIf
    _FileReadToArray($sPath, $avHost)
    If IsArray($avHost) Then
        For $i = 1 to UBound($avHost)
            If StringInStr($avHost[$i], "#") Then
                _ArrayDelete($avHost, $i)
            EndIf
        Next
        _FileWriteFromArray($sPath, $avHost)
    EndIf
EndFunc

It keeps on saying

C:\Documents and Settings\Owner\Desktop\hostfile.au3 (17) : ==> Array variable has incorrect number of subscripts or subscript dimension range exceeded.: 
If StringInStr($avHost[$i], "#") Then 
If StringInStr(^ ERROR

Anybody know what's wrong?

EDIT: This is supposed to automatically remove lines in the host file that contain the # sign.

Edited by Senton-Bomb
Link to comment
Share on other sites

  • Developers

You should loop till UBound($avHost)-1 because:

When Ubound is equal to 10 it means the array has "bucket" 0-9

:)

SciTE4AutoIt3 Full installer Download page   - Beta files       Read before posting     How to post scriptsource   Forum etiquette  Forum Rules 
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Link to comment
Share on other sites

thanks. I will try it in a little bit. im posting from my psp right now.

EDIT: Same Error :)

I'm not sure, but i believe it is because you are "ArrayDeleting" as you go.

it makes the arrays get smaller, so you end up exceeding the bounds. Perhaps if you go from high to low it will work better.

Try something like this:

#Include <File.au3>
#Include <Array.au3>

_CleanupHostFile()

Func _CleanupHostFile($sPath = "C:\WINDOWS\system32\drivers\etc\hosts")
    Local $avHost
    If $sPath = "" Then
        Return -1
    EndIf
    _FileReadToArray($sPath, $avHost)
    If IsArray($avHost) Then
        For $i = Ubound($avHost)-1 to 1 step -1;go from high to low     
            If StringInStr($avHost[$i], "#") Then
            _ArrayDelete($avHost, $i)
            EndIf
        Next
        _FileWriteFromArray($sPath, $avHost)
    EndIf
EndFunc
Edited by Paulie
Link to comment
Share on other sites

I'm not sure, but i believe it is because you are "ArrayDeleting" as you go.

it makes the arrays get smaller, so you end up exceeding the bounds. Perhaps if you go from high to low it will work better.

Paulie called it! When trimming things out of an array with _ArrayDelete() loop through it in reverse order, so the index of the next one to work on doesn't change.

:)

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

Using ArrayDelete seem to me a little more complicated.

This would have worked well without any headaches :)

#Include <File.au3>
#Include <Array.au3>

_CleanupHostFile()

Func _CleanupHostFile($sPath = "C:\WINDOWS\system32\drivers\etc\hosts")
    Local $avHost
    If $sPath = "" Then
        Return -1
    EndIf
    _FileReadToArray($sPath, $avHost)
    If IsArray($avHost) Then
        $fhandle = FileOpen($sPath, 2)
        For $i = 1 to Ubound($avHost)-1 
            If Not StringInStr($avHost[$i], "#") Then
                FileWriteLine($sPath, $avHost[$i])
            EndIf
        Next
       FileClose($fhandle)
    EndIf
EndFunc

It is useless now once you got the solution. When dealing with simple (short) scripts I prefer to write my own part instead of using an UDF and this is always the case when using things like FileCountLines or FileCreate or other simple things; this way I avoid including like hundred lines into my script when I could do it in like 10 lines of my own :P

Of course, when the function I want to use is more complex, I include the UDF :)

SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script

wannabe "Unbeatable" Tic-Tac-Toe

Paper-Scissor-Rock ... try to beat it anyway :)

Link to comment
Share on other sites

Yippe. New Problem!

When i run this, i get an error: Badly formatted variable or macro. I thought you could dynamically reference array elements through a variable (Which is what i do many times in the script. I don't see why it is erroring)

Func _ParseHostFile($sPath = "C:\WINDOWS\system32\drivers\etc\hosts")
    Local $avHost, $avParsed
    _FileReadToArray($sPath, $avHost)
    If Not IsArray($avHost) Then
        Return -1
    EndIf
    For $i = 1 To UBound($avHost) - 1
        $avParsed[$i] = StringSplit($avHost[$i], " ")
        ReDim $avParsed[$i]
    Next
    If Not IsArray($avParsed) Then
        Return -1
    Else
        Return $avParsed
    EndIf
EndFunc   ;==>_ParseHostFile

PS: This is a part of a big project i am working on :)

Link to comment
Share on other sites

Yippe. New Problem!

When i run this, i get an error: Badly formatted variable or macro. I thought you could dynamically reference array elements through a variable (Which is what i do many times in the script. I don't see why it is erroring)

Func _ParseHostFile($sPath = "C:\WINDOWS\system32\drivers\etc\hosts")
    Local $avHost, $avParsed
    _FileReadToArray($sPath, $avHost)
    If Not IsArray($avHost) Then
        Return -1
    EndIf
    For $i = 1 To UBound($avHost) - 1
        $avParsed[$i] = StringSplit($avHost[$i], " ")
        ReDim $avParsed[$i]
    Next
    If Not IsArray($avParsed) Then
        Return -1
    Else
        Return $avParsed
    EndIf
EndFunc   ;==>_ParseHostFile

PS: This is a part of a big project i am working on :)

I see several problems (I think)

-You defined $avParsed, but as a variable, not as an array. You should use Local $avParsed[1] in your second line. This may not be an issue (I'm not sure), but it's 'good practice'.

-Note that the first index of an array is [0] not [1]...but you're trying to assign a value to $avParsed[$i] when $i starts out at 1. You should assign to $avParsed[$i-1], start $i at 0 (this depends on the format of the source array) or else Dim $avParsed at being two elements big ([0] and [1]) initially, and just assume that [0] will always be blank.

-When you ReDim, you should either use ReDim $avParsed[$i+1] or ReDim $avParsed[uBound($avParsed)+1], since your current method, after the loop ran once, would leave $avParsed at one element big, since $i=1. That doesn't leave any room for the next loop, which will be trying to assign a second value (either to [1] or to [2], depending on how you apply my previous point).

-I'm not sure, but I don't think you can contain an array in an array element. I don't think your line $avParsed[$i] = StringSplit($avHost[$i], " ") will ever work, no matter how large $avParsed is, since StringSplit returns an array. I could be wrong about this one, but I don't know how you'd reference a value within that...would it be $avParsed[1[1]]? Or maybe this is supported, and it just makes it a two-dimensional array. Like I said, I'm not positive about this one.

Edited by james3mg
"There are 10 types of people in this world - those who can read binary, and those who can't.""We've heard that a million monkeys at a million keyboards could produce the complete works of Shakespeare; now, thanks to the Internet, we know that is not true." ~Robert Wilensky0101101 1001010 1100001 1101101 1100101 1110011 0110011 1001101 10001110000101 0000111 0001000 0001110 0001101 0010010 1010110 0100001 1101110
Link to comment
Share on other sites

But i just declare $avParsed, and then StringSplit sets a value to it

Ugh. This _ParseHostFile thing is way to complicated. I will dig up one of my old methods :)

Thanks anyway

EDIT: New qustion: Is there a way to count how many spaces are on one line of a file, then reduce that to 1 space?

Edited by Senton-Bomb
Link to comment
Share on other sites

But i just declare $avParsed, and then StringSplit sets a value to it

No, that would be (without the subscript):

$avParsed = StringSplit($avHost[$i], " ")

If that had workded the way you had it, you would have stored the split array into the $avParsed array. NOT what you wanted.

Ugh. This _ParseHostFile thing is way to complicated. I will dig up one of my old methods :)

Quitter! :)

EDIT: New qustion: Is there a way to count how many spaces are on one line of a file, then reduce that to 1 space?

StringStripWS($sLine, 4)

:P

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

Ok. Heres my code now.

Func _CleanupHostFile($sPath = "C:\WINDOWS\system32\drivers\etc\hosts")
    Local $avHost
    If $sPath = "" Then
        Return -1
    EndIf
    _FileReadToArray($sPath, $avHost)
    If IsArray($avHost) Then
        For $i = UBound($avHost) - 1 To 1 Step - 1
            If StringInStr($avHost[$i], "#") Then
                _ArrayDelete($avHost, $i)
            EndIf
        Next
        FileCopy($sPath, $sPath & "1")
        FileDelete($sPath)
        For $i = 1 To UBound($avHost) - 1
            FileWrite($sPath, StringStripWS($avHost[$i], 4) & @CRLF)
        Next
    EndIf
EndFunc   ;==>_CleanupHostFile

It doesn't seem to filter out the whitespace in the HOSTS file.

This is how my host file looks after this:

127.0.0.1         localhost

This filters out the default comments fine, but it doesn't remove the Whitespace.

Can you help?

Link to comment
Share on other sites

This is totally off the top of my head, but this should reduce the whitespace to just 1 space:

While StringInStr($line, "  ")
    StringReplace($line, "  ", " ")
Wend

If that doesn't compile/work, here's the thought process for it:

On each line you read, while the line contains two spaces side by side, replace every double space it finds with a single space.

The reason for the loop, I'm not sure how StringReplace researches an area it already replaced once, so I do it in a loop to make sure it rechecks any double space characters it itself may have created. There's probably an easier way to do this with Regular Expressions, but like I said at the top, this is totally off the top of my head.

Link to comment
Share on other sites

Oh my god i am seriously about to rip my hair out.

I've tried EVERYTHING I CAN THINK OF!

Let me just vent for a minute

[venting]MY GOD THIS IS SO ANNOYING SOMEONE PUNCH ME IN THE FACE SO THIS WILL WORK I NEED TO FIND A STAPLER AND STAPLE MY FINGERS TO THE EFFING KEYBOARD[/venting]

Ok. I'm all better.

Heres what i have now, but it doesn't work.

Func _CleanupHostFile($sPath = "C:\WINDOWS\system32\drivers\etc\hosts")
    Local $avHost
    If $sPath = "" Then
        Return -1
    EndIf
    _FileReadToArray($sPath, $avHost)
    If IsArray($avHost) Then
        For $i = UBound($avHost) - 1 To 1 Step - 1
            If StringInStr($avHost[$i], "#") Then
                _ArrayDelete($avHost, $i)
            EndIf
        Next
        FileCopy($sPath, $sPath & "1")
        FileDelete($sPath)
        For $i = 0 To UBound($avHost) - 1
            If StringInStr($avHost[$i], "  ") Then
                Do
                    $line = StringReplace($avHost[$i], "  ", " ", 0)
                Until Not StringInStr($avHost[$i], "  ")
            EndIf
            
            FileWrite($sPath, $line & @CRLF)
        Next
    EndIf
EndFunc   ;==>_CleanupHostFile

So much for this being a simple function.

Link to comment
Share on other sites

Found where is the error :) took me 15 minutes but here it is :

$line = StringReplace($avHost[$i], " ", " ", 0)

this line won't modify the content of $avHost[$i] making the function to cycle endlessly.

This is the working code :P enjoy

_CleanupHostFile()

Func _CleanupHostFile($sPath = "C:\WINDOWS\system32\drivers\etc\hosts")
    Local $line
    Local $avHost
    If $sPath = "" Then
        Return -1
    EndIf
    _FileReadToArray($sPath, $avHost)
    If IsArray($avHost) Then
        $fhandle = FileOpen($sPath, 2)
        For $i = 1 to Ubound($avHost)-1 
            If Not StringInStr($avHost[$i], "#") and $avHost[$i]<> "" Then
                MsgBox(0, "line", $avHost[$i])
                If StringInStr($avHost[$i], "  ") Then
                    Do
                        $avHost[$i] = StringReplace($avHost[$i], "  ", " ")
                    Until Not StringInStr($avHost[$i], "  ")
                EndIf
                FileWriteLine($sPath, $avHost[$i])
            EndIf
        Next
       FileClose($fhandle)
    EndIf
EndFunc

Sorry because I changed the format but I've used my previous example.

You can really modify yours to reflect the changes.

SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script

wannabe "Unbeatable" Tic-Tac-Toe

Paper-Scissor-Rock ... try to beat it anyway :)

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