Jump to content

_ArrayyDelete removes arrays


Recommended Posts

I just switched to the new version of AutoIt (from v3.2.10.0 to v3.2.12.1). Besides that I had to change a lot of code to get it working with the new version I still have one problem left.

When I use _ArrayDelete on an 1-dim array only consisting of one last Element it removes the array completely form memory instead of doing what it did in the old version -> setting the remaining line to "" ("" = empty) According to the remark in the help it still should do so but even if I check the array with IsArray() it tells me that the array is gone.

Is this intentional or just a bug due to the changes in Array.au3?

Link to comment
Share on other sites

It's perfectly intentional, and behaving exactly as the remark says. When you remove the last item in the array, the array gets set to an empty string (to indicate that it's empty). There is no such thing as an empty array in AutoIt -- arrays must have at least one element. The way it used to behave, AutoIt would simply not remove the last item, which is rather silly, especially considering the fact that when one asks to remove the last item, they should well-expect that it will remove the last item.

The only problem here is that you can't really use the variable again and expect it behave as an array immediately -- you'd have to first check to make sure it is an array before using _ArrayAdd() on the cleared "array," for example. Either way, though, it's a better alternative than guessing when an array was meant to have been empty (where _ArrayDelete() failed on the last item) or if it actually had exactly one element left.

Edited by -Ultima-

[ WinINet.au3 | Array.au3 (Optimized) | _UnixTimeParse() ]

Link to comment
Share on other sites

well then why doesn't it work SINCE the update. before the update I could apply _ArrayDelete() as often as I wanted on an "empty" array but now the array is gone (don't know how to call it else) when _ArrayDelete removes the last line, which it should just overwrite with "". here's an example:

#include <Array.au3>

Global $test[1]
_ArrayAdd($test,11)
_ArrayAdd($test,12)
_ArrayAdd($test,13)
_ArrayDelete($test,0)
;now the array has 3 elements and no empty lines (this is what i need)
_ArrayDisplay($test)
MsgBox(0,"",IsArray($test))
While _ArrayMax($test)<>"";delete until only empty line is left
    _ArrayDelete($test,UBound($test)-1)
    _ArrayDisplay($test)
    MsgBox(0,UBound($test),IsArray($test))
WEnd
;from hiere on Ubound is 0 and i can't write elements to the array
_ArrayInsert($test,0,44);doesn't work
_ArrayAdd($test,21);does't work
_ArrayDisplay($test);doesn't work
MsgBox(0,UBound($test),IsArray($test));
Edited by magnifier512
Link to comment
Share on other sites

It's becasue the behaviour was changed ! Now you have to change your Scripts, too :)

e.g. make a Function like this:

Func _ArrayAddCreate(ByRef $avArray, $vValue)
    If Not IsArray($avArray) Then
        Dim $avArray[1] = [$vValue]
    Else
        Return _ArrayAdd(ByRef $avArray, $vValue)
    EndIf
EndFuncoÝ÷ ØêÚºÚ"µÍ[ÈÐ^Q[]SX]JTY ÌÍØ]^K   ÌÍÚQ[[Y[
BSØØ[ ÌÍÝØØ^HHÐ^J   ÌÍØ]^JBSØØ[    ÌÍÜHÐ^Q[]JTY    ÌÍØ]^K   ÌÍÚQ[[Y[
BSØØ[ ÌÍÙÜHÜSØØ[   ÌÍÙ^[YH^[YRY ÌÍÝØØ^H[ÝÐ^J ÌÍØ]^JH[[H   ÌÍØ]^VÌWBT]Ù]Ü    ÌÍÙÜ    ÌÍÙ^[Y   ÌÍÜB[[

*GERMAN* [note: you are not allowed to remove author / modified info from my UDFs]My UDFs:[_SetImageBinaryToCtrl] [_TaskDialog] [AutoItObject] [Animated GIF (GDI+)] [ClipPut for Image] [FreeImage] [GDI32 UDFs] [GDIPlus Progressbar] [Hotkey-Selector] [Multiline Inputbox] [MySQL without ODBC] [RichEdit UDFs] [SpeechAPI Example] [WinHTTP]UDFs included in AutoIt: FTP_Ex (as FTPEx), _WinAPI_SetLayeredWindowAttributes

Link to comment
Share on other sites

It's becasue the behaviour was changed

Thx, guess that would work, but I tried to avoid stuff like that.

Why did they change it anyway? It worked just fine the way it was and now I have to use these ugly workarounds. I guess I just include the old Array.au3 (or at least the old _ArrayDelete). There is no sence in using UDF's that force me to write even more of them to be usable.

Link to comment
Share on other sites

I already said this before: _ArrayDelete() used to simply fail when you tried to remove the last item. It didn't remove anything. It didn't set anything to "". It simply failed and set @error to 2.

If you're working on an array, and you're expecting the possibility that it might become empty, then you better keep track of the array size. Doing otherwise is silly (borderline dumb), and bad programming practice. You're practically inviting undefined/unexpected behavior by not checking edge cases.

Why the change? Well, why not? If you're deleting and deleting until you reach the last item, then attempt to delete, and then add, then with the old _ArrayDelete(), you're left with the undeleted element as the first item in the array anyhow, which is equally bad -- I would have wanted a one-element array, not a two element array with the first element being a remenant of the previously-cleared array. If I said to delete it, and I wanted to delete it, then AutoIt better delete it. In the end, you're going to have to check *something* if you want the array to behave correctly. Checking for "" is much easier and simpler than looking at the last item in the array and guessing whether it's supposed to be empty, or if it was intended to be there. Setting the last item to "" is not a solution either -- what if the array was meant to be an array with a single element containing ""? Would you consider it to be a one-element array, or an array that should be interpreted as being empty?

This might all be "solved" if empty arrays were allowed in AutoIt, but this simple edge-case probably isn't much of an incentive, especially when all you'd have to do is fix one line in your test script:

#include <Array.au3>

Global $test[1]
_ArrayAdd($test,11)
_ArrayAdd($test,12)
_ArrayAdd($test,13)
_ArrayDelete($test,0)
;now the array has 3 elements and no empty lines (this is what i need)
_ArrayDisplay($test)
MsgBox(0,"",IsArray($test))
While _ArrayMax($test)<>"";delete until only empty line is left
    _ArrayDelete($test,UBound($test)-1)
    _ArrayDisplay($test)
    MsgBox(0,UBound($test),IsArray($test))
WEnd
if not isarray($test) then Global $test[1] = [44]; FIX
_ArrayAdd($test,21);does work
_ArrayDisplay($test);does work
MsgBox(0,UBound($test),IsArray($test));

BTW, if _ArrayDelete() were to be implemented as you envisioned (the last item being set to ""), your script would probably not work as you might've wanted/expected anyway -- the final array would end have ended up as [44, "", 21] instead of [44, 21]. And if former result was what you wanted, then simply doing something like

if not isarray($test) then global $test[1]

;from hiere on Ubound is 0 and i can't write elements to the array
_ArrayInsert($test,0,44);doesn't work
_ArrayAdd($test,21);does't work
_ArrayDisplay($test);doesn't work
MsgBox(0,UBound($test),IsArray($test));

would have done exactly as you wanted -- one line, and not even an ugly "workaround."

Now imagine trying to get the second result ([44, 21]) in your test script if things behaved the way you described.

Edited by -Ultima-

[ WinINet.au3 | Array.au3 (Optimized) | _UnixTimeParse() ]

Link to comment
Share on other sites

I get your point and thx for the fix, but it is not aplicalbe for what i need. My programm needs some way to handle empty arrays, because it adds entries from many different functions. so th eonly fix for me will be to write something like

Func _ArrayAdd2(array,value)
      check if valid array, recreate if needed
     _ArrayAdd(array,value)
EndFunc

let's say this problem is fixed

But this i still have to say: The old _ArrayDelete never failed to set the last element to "". If it had not done so my programm wouldn't have worked the way it did and ... right ... iI needed a workaround to fix the problem with the first added entry. I agree that this was a bad solution for an "empty" array but then _ArrayAdd() should be reworked to handle arrays which have been striped down to not recognizable objects by _ArrayDelete(). Not even _ArrayInsert() could work with whatever is left of the former array. If I start with an array I don't want to end up with something even IsArray() cannot recognize as an array or can only be handled be reinitializing it as an array.

Link to comment
Share on other sites

But this i still have to say: The old _ArrayDelete never failed to set the last element to "".

The old code indicates otherwise:

Func _ArrayDelete(ByRef $avArray, $iElement)
    Local $iCntr = 0, $iUpper = 0

    If (Not IsArray($avArray)) Then
        SetError(1)
        Return ""
    EndIf

    ; We have to define this here so that we're sure that $avArray is an array
    ; before we get it's size.
    $iUpper = UBound($avArray)    ; Size of original array

; LOOK HERE
    ; If the array is only 1 element in size then we can't delete the 1 element.
    If $iUpper = 1 Then
        SetError(2)
        Return ""
    EndIf
; LOOK HERE

    Local $avNewArray[$iUpper - 1]
    If $iElement < 0 Then
        $iElement = 0
    EndIf
    If $iElement > ($iUpper - 1) Then
        $iElement = ($iUpper - 1)
    EndIf
    If $iElement > 0 Then
        For $iCntr = 0 To $iElement - 1
            $avNewArray[$iCntr] = $avArray[$iCntr]
        Next
    EndIf
    If $iElement < ($iUpper - 1) Then
        For $iCntr = ($iElement + 1) To ($iUpper - 1)
            $avNewArray[$iCntr - 1] = $avArray[$iCntr]
        Next
    EndIf
    $avArray = $avNewArray
    SetError(0)
    Return 1
EndFunc   ;==>_ArrayDelete
Edited by -Ultima-

[ WinINet.au3 | Array.au3 (Optimized) | _UnixTimeParse() ]

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