Comparison of characters and strings is not ASCII based
Description
Liberty BASIC offers alphabetic comparison of characters and strings which can confuse folks expecting ASCII comparison. It is quite unusual to find this feature, established programmers expect ASCII comparison. This issue needs much better coverage in the help file. Also the fact that comparison used is locale-dependent should be mentioned (it doesn't depend on locale for ASCII comparison).
Often programmers never realize alphabetic comparison is taking place as the majority of the comparisons they make work as expected. However there is a difference between the methods.
A programmer used to ASCII comparison would expect this character order:
! " # $ % & ' ( ) * + , - . /
0 1 2 3 4 5 6 7 8 9 : ; < = > ?
@ A B C D E F G H I J K L M N O
P Q R S T U V W X Y Z [ \ ] ^ _
` a b c d e f g h i j k l m n o
p q r s t u v w x y z { | } ~
Alphabetic comparison actually uses this character order:
' - ! " # $ % & ( ) * , . /
: ; ? @ [ \ ] ^ _ ` { | } ~ + <
= > 0 1 2 3 4 5 6 7 8 9 A a B b
C c D d E e F f G g H h I i J j
K k L l M m N n O o P p Q q R r
S s T t U u V v W w X x Y y Z z
This is "Dictionary" or alphabetic order, numerals followed by uppercase and then lower case alpha characters. If you are used to ASCII comparison you will probably be forcing upper case or lower case prior to comparing alphanumeric data. In which case you will notice little difference.
Example code to demonstrate the difference.
Here Liberty tells us that "R" is not less than "q" alphabetically despite the fact that asc("R") is less than asc("q"). Alphabetic comparison is quite happy to deal with case.
print "R"<"q"
print asc("R")<asc("q")
print "Abc"<"aBc" print "Abc"<"abC" print "Abc"<"abc"
Forcing case allows ASCII alphanumeric comparison.
print upper$("Abc") = upper$("aBc")
print lower$("Abc") = lower$("abC")
Example code to work around the bug.
If you need ASCII string compare, you can use this function.
'Ascii string compare
'returns -1 if s1$<s2$, 0 if s1$=s2$, 1 if s1$>s2$
function AsciiCompare(s1$,s2$)
if s1$=s2$ then AsciiCompare=0: exit function
minLen=len(s1$)
if minLen>len(s2$) then minLen=len(s2$)
for i=1 to minLen
c1$=mid$(s1$,i,1)
c2$=mid$(s2$,i,1)
if c1$<>c2$ then 'sign of asc(c1$)-asc(c2$)
AsciiCompare = (asc(c1$)>asc(c2$))*2-1
exit function
end if
next
'if we are here then one string ended, and we already checked for equal - so
AsciiCompare=(len(s1$)>len(s2$))*2-1
end function
Proposed fix
- Document this behavior in the help file.
- Make the method of string comparison optional, controlled by an operator or compiler directive.