Jump to content

Weird Problem with a Switch Block


Zohar
 Share

Recommended Posts

Hi

 

I have used Switch Blocks so many times, and all went OK,

but this time I have something unexplainable :)

 

See this function

Func    TestFunc($Char)
    Local   $Result

    Switch $Char
        Case "-",".","0" To "9","A" To "Z","_","a" To "z","~"
            $Result =$Char
        Case Else
            $Result ="#"
    EndSwitch
    
    Return $Result
EndFunc

Should be quite simple..

Certain chars will go thru,

and all the rest will be converted to "#".

 

Try it on "A", "g", "5", all will be OK and the output will be identical to the input.

Try it on "%", "?", "(", they will be converted to "#", as they should.

But...

try it on "™", and you get an output "™".

Why?

Link to comment
Share on other sites

Try it this way:

ConsoleWrite(TestFunc("A") & @CRLF)
ConsoleWrite(TestFunc("%") & @CRLF)
ConsoleWrite(TestFunc("g") & @CRLF)
ConsoleWrite(TestFunc("™") & @CRLF)
ConsoleWrite(TestFunc("5") & @CRLF)
ConsoleWrite(TestFunc("?") & @CRLF)

Func TestFunc($Char)
    Switch Asc($Char)
        Case 45 To 46, 48 to 57, 65 To 90, 95, 97 To 122, 126
            Return $Char
        Case Else
            Return "#"
    EndSwitch
EndFunc

Br,

UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

Looks like a bug in Switch over strings. Anyway, try this as well:

Func _TestFunc($Char)
    Return(StringRegExpReplace($Char, "(?i)[^-.\d\w~]", "#"))
EndFunc

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

really a bug?

I thought I was missing something in the code :)

 

BTW I managed to narrow it:

Func    TestFunc($Char)
    Local   $Result
    
    Switch $Char
        Case "T" To "U"
            $Result =$Char
        Case Else
            $Result ="#"
    EndSwitch
    
    Return $Result
EndFunc

It seems that the problem happens between "T" and "U"..

 

Edited by Zohar
Link to comment
Share on other sites

This deserves a ticket in Trac.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

@jchd: I personally don't think it is a bug. The OP came from the world with not only has char type but also castable to integer so it's easy to explain why he complain with a problem like this. AutoIt doesn't have a char datatype but string-type-variable. "Get distance from 2 string" is not sense at all.

Edited by binhnx

99 little bugs in the code

99 little bugs!

Take one down, patch it around

117 little bugs in the code!

Link to comment
Share on other sites

binhnx,

I've no idea which language the OP "comes from" but your remark about strings not being sortable doesn't make sense to me. In a Switch condition, "X To Y" clause isn't about distance (a completely distinct beast) but string comparison, which is said to be "case insensitive" in the help file under Switch.

So, yes, it's definitely a bug.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

@jchd: I chose word carefully, and I said "distance from 2 string" but you translate it to "not being sortable".

String can be sorted, but you cannot calculate the distance from them.

Say, we have two string "Hello" and "World", it is easy to sort them alphabetical, but can you say how far from "Hello" to "World"? It's definitely impossible. 

The document state that "Switch statements are case-insensitive" is for the regular Case, not for the distance/range case. Using distance with any value other than number / char does not make sense. Note that AutoIt does not have a value type of char, but string only.

But the dev may provide a "sweet feature" that handle the case when using switch statement with char range ('x' to 'y'). Then it should be a feature request. Beside that, I doubt that implement that feature is far from trivial.

Edit: And I see that you rely soooooo much on the RegEx. It's a nice feature but IMO, it is not only slow but also looks weird in some cases. And even it doesn't looks weird this case, I think it is better to suggest a more standard/ flexible solution

Edited by binhnx

99 little bugs in the code

99 little bugs!

Take one down, patch it around

117 little bugs in the code!

Link to comment
Share on other sites

(Edit: @jchd: Ahh, I wrong, but its not a bug and work as expected, AutoIt's dev is great!!!)
 
@Zohar: After some quick tests, it may be like this (I cannot guarantee my assumption is true but it seems logic)
To handle a range switch like x to y, the value first must be translate to number. In language which support char datatype, like VB, the character is translated to corresponding int/byte.
With AutoIt, we have not a char datatype, but string only. The string is converted to int by internal conversion, then "9abc" is converted to 9 but "abc" is translated to 0
 
Then your statement can be written as 
 
Func    TestFunc($Char)
    Local   $Result
    Switch $Char
        Case "-", ".", 0 To 9, 0 To 0, "_", 0 To 0, "~"
            $Result =$Char
        Case Else
            $Result ="#"
    EndSwitch
   
    Return $Result
EndFunc


 

Edit: My naive assumption is wrong, but it is still valuable. All range-switch must be translate to number
But for one-character-string, AutoIt normalize it to a ansi character. Then ™ becomes t (and ℣ becomes v, ℤ becomes z, but Ω cannot be normalized to ansi.)

 
Now, in your case: 
First, all one-character-string is converted to lower character, then converted to ascii number
™ is converted to t, then converted to ascii number, so it match ascii number range a To z, and also match t To u
The t To t is a bit tricky, I think the dev wrote a test that, with x To y, if x equals to y, check if x equals to sample. In this case, since t is not equals with ™, the condition is not match, in your case it return "#".
same as ℣, with range v To w.
With the ℤ, there're no alphabetical character after it. And the z To z is not match due to the previous trick, so in your test it will return "#"
Ω cannot be normalized, will return "#".

Interesting enough, since Ω cannot be normalized, it remains Ω. And due to its large character code, a case like this:

Case "b" To "Ω"

will match all chracters from "b" to "z"
 
This explain anything "weird" with your script :)

Edited by binhnx

99 little bugs in the code

99 little bugs!

Take one down, patch it around

117 little bugs in the code!

Link to comment
Share on other sites

binhnx,

 

Say, we have two string "Hello" and "World", it is easy to sort them alphabetical, but can you say how far from "Hello" to "World"? It's definitely impossible. 

The document state that "Switch statements are case-insensitive" is for the regular Case, not for the distance/range case. Using distance with any value other than number / char does not make sense. Note that AutoIt does not have a value type of char, but string only.

Only you are talking about distance between strings.

In a Switch condition, "X To Y" means "X ≤ $SwitchExpression ≤ Y" and that doesn't anyhow imply any concept of distance between strings, only the Unicode case-insensitive lexicographic comparison.

Now can you precisely define how and why use of a simple regexp can be said "weird"?

Finally your attempt at an explanation falls short on its nose.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

binhnx: It is definitely a bug if the language enables people to define a range, and then that range suddenly contains chars it doesn't.

AutoIt may not have datatypes, but when you use do If $A="C" then it knows how to compare it, so it should when doing a switch.. whether or not there is a char type..

 

I hope this can be fixed..

Link to comment
Share on other sites

  • Moderators

If what you two are saying is right, then you're suggesting that all the range switches/loops/etc are bugs?

e.g.

For $i = "A" To "Z"

 

Edit:

I know most of the other languages I dabble in, use the quotes to distinguish... I'm curious on how it would be suggested to handle that here.

Edited by SmOke_N

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

comparing single chars could be managed by the <value> To <value> construct maybe using the AscW() value of that chars for example,
but how could be managed an entire word? (at first glance it make no sense to me)
which cases would you expect to match in the following construct?

Local $sMsg = "orange"

Switch $sMsg
    Case "apple" To "banana"
        $sMsgx = "It's a fruit"
    Case "table" To "bed"
        $sMsgx = "It's a furniture"
    Case "Tricycle" To "Car"
        $sMsg = "It's a vehicle"
    Case Else
        $sMsgx = "What's that?"
EndSwitch

MsgBox(0, $sMsg, $sMsgx)

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

  • Moderators

 

comparing single chars could be managed by the <value> To <value> construct maybe using the AscW() value of that chars for example,

but how could be managed an entire word? (at first glance it make no sense to me)

which cases would you expect to match in the following construct?

Local $sMsg = "orange"

Switch $sMsg
    Case "apple" To "banana"
        $sMsgx = "It's a fruit"
    Case "table" To "bed"
        $sMsgx = "It's a furniture"
    Case "Tricycle" To "Car"
        $sMsg = "It's a vehicle"
    Case Else
        $sMsgx = "What's that?"
EndSwitch

MsgBox(0, $sMsg, $sMsgx)

Or even worse, a real life AutoIt scenario:

Global $gszMsg = 65
Switch $gszMsg
    Case 65
        MsgBox(64, "Info", "There are " & $gszMsg & " things I want to do today.")
    Case "A" ; if "A" To "Z" worked even, I just wanted a single char example
        MsgBox(64, "Info", "My name has an " & $gszMsg & " in it.")
EndSwitch

I could see a "fix" causing issues with scripts that had this type of logic.  If "A" was passed as the $gszMsg, then the conversion would cause an issue, I'd get stopped at Case 65 when I was really looking for Case "A".

I see the "dynamic" ability being an issue.

Edited by SmOke_N

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

SmOke_N,

From the specification of For found in the help file:

For $i = "A" To "Z"

is equivalent to:

For $i = 0 To 0

Why? Because <start>, <stop> and <step> are defined to be numeric values. Passing string datatype(s) will force conversion to numeric by means of an implied Number() call. Switch and Select don't have such a limitation, as Switch is defined (remember the help file plays the role of a loose specification document) to be case-insensitive (i.e. will handle strings in conditions) and Select example shows a string condition tested.

 

Chimp,

 

comparing single chars could be managed by the <value> To <value> construct maybe using the AscW() value of that chars for example,
but how could be managed an entire word? (at first glance it make no sense to me)
which cases would you expect to match in the following construct?

You and SmOke_N seem to regard Switch as something magical or esoterical but it's not so, even if it is currently buggy in some Case(s) [pun intended].

Your example is no different than:

Local $sMsg = "orange"

Switch $sMsg
    Case "apple" To "banana"
        $sMsgx = "It's a fruit"
    Case "table" To "bed"
        $sMsgx = "It's a furniture"
    Case "Tricycle" To "Car"
        $sMsg = "It's a vehicle"
    Case Else
        $sMsgx = "What's that?"
EndSwitch
MsgBox(0, $sMsg, $sMsgx)

If "apple" <= $sMsg And $sMsg <= "banana" Then
        $sMsgx = "It's a fruit"
ElseIf "table" <= $sMsg And $sMsg <= "bed" Then
        $sMsgx = "It's a furniture"
ElseIf "Tricycle" <= $sMsg And $sMsg <= "Car" Then
        $sMsg = "It's a vehicle"
Else
        $sMsgx = "What's that?"
EndIf
MsgBox(0, $sMsg, $sMsgx)

Strings are compared lexicographically over case-insensitive UTF-2 character set. How is that difficult to understand?

Conditions where <begin> is greater than <end> in a range are simply ignored, irrelevant of datatype(s).

Only the implementation --possibly using a buggy jump table or something fancy but wrong-- differs from a sequence of tests.

Change "banana" into "zebra" and see by yourself that is works fine, neglecting the fact that a zebra is not a fruit.

 

SmOke_N,

Thanks for providing an example which demonstrates that Switch unsurprisingly behaves exactly as common sense would expect:

_Test(65)
_Test("A")

Func _Test($v)
    Switch $v
        Case 65
            MsgBox(64, "Info", "There are " & $v & " things I want to do today.")
        Case "A" ; if "A" To "Z" worked even, I just wanted a single char example
            MsgBox(64, "Info", "My name has an " & $v & " in it.")
    EndSwitch
EndFunc
Edited by jchd

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

Yes, almost all language distinguish between char and string using single and double quote. The problems with AutoIt is it treats all quotes as string.

Indeed, statement like $a = 'A' is not only different from switch but also totally different from $a = 'A' to 'Z' switch.

@Smoke: In my previous comment, I did think that AutoIt dont handle the one-character-string case, but I wrong. It did, yes, the wonderful AutoIt. It did so well so we don't see any problem with simple switch case 'A' To 'Z'. Indeed, it already fixed. My comment (#13) attempt to give a explaination about how it is handled.

@jchd: Now I realize that I was totally misunderstood what you've said. But the example you gave clear me. 

Your implemention is totally different from what currently be used by AutoIt.

But what I think now is both implementation has both advantages and drawbacks, so I don't think its a bug myself. And I prefer the more-standard-way one which is currently be used.

Edited by binhnx

99 little bugs in the code

99 little bugs!

Take one down, patch it around

117 little bugs in the code!

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