an equal '=' test string not case sensitive

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
said
Enthusiast
Enthusiast
Posts: 342
Joined: Thu Apr 14, 2011 6:07 pm

an equal '=' test string not case sensitive

Post by said »

would be really nice to be able to test 2 strings regardless of their case.

An idea, this could be achieved via a new directive such as

EnableTextCompare

then all s1$ = s2$ will compare the two strings with no case and then we dont need a new operator for that

For now i have to convert both strings into lower/upper casing and compare!

Hope you find this useful
User avatar
TI-994A
Addict
Addict
Posts: 2704
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: an equal '=' test string not case sensitive

Post by TI-994A »

said wrote:...all s1$ = s2$ will compare the two strings with no case and then we dont need a new operator for that

For now i have to convert both strings into lower/upper casing and compare!
Hello said. For now, instead of converting the strings to match their cases, perhaps you could make use of PureBasic's FindString() function with the #PB_String_NoCase flag, like this:

Code: Select all

s1$ = "hello said!"
s2$ = "HELLO Said!"
If FindString(s1$, s2$, 1, #PB_String_NoCase)
  result$ = "The two strings match!"
Else
  result$ = "The two strings don't match."
EndIf
MessageRequester("Case Insensitive String Compare", result$)
Just a suggestion. :)
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
User avatar
Demivec
Addict
Addict
Posts: 4260
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: an equal '=' test string not case sensitive

Post by Demivec »

Or using CompareMemoryString():

Code: Select all

s1$ = "hello said!"
s2$ = "HELLO Said!"
If CompareMemoryString(@s1$, @s2$, #PB_String_NoCase) = #PB_String_Equal
  result$ = "The two strings match!"
Else
  result$ = "The two strings don't match."
EndIf
MessageRequester("Case Insensitive String Compare", result$)
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: an equal '=' test string not case sensitive

Post by skywalk »

Code: Select all

Macro StrCmp(str1, str2, UseCase=#PB_String_NoCase)
  Bool(CompareMemoryString(@str1, @str2, UseCase) = #PB_String_Equal) ; = 0 means same memory
EndMacro
s1$ = "hello said!"
s2$ = "HELLO Said!"
If StrCmp(s1$,s2$)  ; ,#PB_String_CaseSensitive)
  MessageRequester("String Compare", "Match")
Else
  MessageRequester("String Compare", "No Match")
EndIf
EDIT: Demivec beat me :oops:
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: an equal '=' test string not case sensitive

Post by Michael Vogel »

Or keep the simple If LCase(a$)=LCase(b$), if speed is not the primary target...
said
Enthusiast
Enthusiast
Posts: 342
Joined: Thu Apr 14, 2011 6:07 pm

Re: an equal '=' test string not case sensitive

Post by said »

thank you all for your suggestions, nice ones (honestly, never thought of using a FindString for that :shock: TI-994A :!: )

My thought, this is a basic test that we are likely to use everyday and in almost any program!
Last edited by said on Thu Aug 15, 2013 9:55 pm, edited 2 times in total.
said
Enthusiast
Enthusiast
Posts: 342
Joined: Thu Apr 14, 2011 6:07 pm

Re: an equal '=' test string not case sensitive

Post by said »

After doing some tests:

using CompareMemoryString() as suggested by Demivec, skywalk ... this cannot be used when one param is a constant string ( #txt$ = "hello SaiD" ) even after converting the macro into a procedure and using a local variable to receive the param! Looks like PB treats very differently constant-strings and variable-strings!

using FindString() as suggested by TI-994A is on avg 6-7 times slower than UCase() /LCase() ...

for me this feature request still makes sense!
Little John
Addict
Addict
Posts: 4779
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: an equal '=' test string not case sensitive

Post by Little John »

said wrote:using FindString() as suggested by TI-994A is on avg 6-7 times slower than UCase() /LCase() ...
Then just use UCase() /LCase(). :-)
said
Enthusiast
Enthusiast
Posts: 342
Joined: Thu Apr 14, 2011 6:07 pm

Re: an equal '=' test string not case sensitive

Post by said »

Little John wrote: Then just use UCase() /LCase(). :-)

am using it right now :D (see first post) however i believe if implemented native in PB the test would be much faster
User avatar
Demivec
Addict
Addict
Posts: 4260
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: an equal '=' test string not case sensitive

Post by Demivec »

said wrote:After doing some tests:

using CompareMemoryString() as suggested by Demivec, skywalk ... this cannot be used when one param is a constant string ( #txt$ = "hello SaiD" ) even after converting the macro into a procedure and using a local variable to receive the param! Looks like PB treats very differently constant-strings and variable-strings!

using FindString() as suggested by TI-994A is on avg 6-7 times slower than UCase() /LCase() ...

for me this feature request still makes sense!
There's other ways of doing it, that may or not be feasible for your particular needs. Just for the sake of comparison, here's a way that requires you to define constants differently:

Code: Select all

#txt$ = "hello SaiD!"
DataSection
  c_txt$: Data.s #txt$ ;constant
EndDataSection

Macro StrCmp(str1, str2, UseCase=#PB_String_NoCase)
  Bool(CompareMemoryString(@str1, @str2, UseCase) = #PB_String_Equal) 
EndMacro

Macro StrCmp_c(str1, str2, UseCase=#PB_String_NoCase)
  Bool(CompareMemoryString(@str1, ?str2, UseCase) = #PB_String_Equal) 
EndMacro

s1$ = "hello said!"
s2$ = "HELLO Said!"

Debug StrCmp_c(s1$, c_txt$)
Debug StrCmp_c(s2$, c_txt$)
Debug StrCmp(s1$, s2$)
Debug StrCmp(s1$, s2$, #PB_String_CaseSensitive) 
You'll notice that you have to use a different macro to specifically handle when you are using the constants that have been declared this way.

I get a 10x speedup over using UCase()/LCase() when doing it this way.

Not being able to retrieve the address of a literal string or a string constant definitely throws curves into the process. I agree that the easiest thing to do is probably just to continue on with UCase/LCase() until a native solution is reached. :)
User avatar
skywalk
Addict
Addict
Posts: 4211
Joined: Wed Dec 23, 2009 10:14 pm
Location: Boston, MA

Re: an equal '=' test string not case sensitive

Post by skywalk »

If you really want to speed up the comparison, just drop the String Constant since they cannot be addressed using @.
In these cases I use a global string variable instead.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
said
Enthusiast
Enthusiast
Posts: 342
Joined: Thu Apr 14, 2011 6:07 pm

Re: an equal '=' test string not case sensitive

Post by said »

Demivec wrote: .... just to continue on with UCase/LCase() until a native solution is reached. :)
I think i will continue that way ... Thanks for trying to find workarounds :!: still quite cumbersome and requires knowing before hand that we are to deal with literal string ...

However we are in the Feature Requests section and this is just one of them ... Hopefully the PB team will think this is an important one and decide to implement it :!:
User avatar
TI-994A
Addict
Addict
Posts: 2704
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: an equal '=' test string not case sensitive

Post by TI-994A »

said wrote:using CompareMemoryString() ... cannot be used when one param is a constant string ( #txt$ = "hello SaiD" ) even after converting the macro into a procedure and using a local variable to receive the param! ...

using FindString() ... is on avg 6-7 times slower than UCase() /LCase()
Hello again said. You're right; of all the methods, the FindString() function is the slowest, with the CompareMemoryString() function being the fastest. Although string constants can be passed to procedures to be evaluated by the CompareMemoryString() function, the speed compromise is huge.

However, as you can see in this example, a simple re-assignment of the string constant to a regular string would solve this problem quite easily, without any loss of speed. And since comparisons against string constants should be known beforehand, such an approach shouldn't be much of an issue:

Code: Select all

s$ = "hello said!"
#s = "HELLO Said!"

Procedure StrComp(a.s, b.s)
  ProcedureReturn CompareMemoryString(@a, @b, #PB_String_NoCase)  
EndProcedure

a$ = #s : t = ElapsedMilliseconds()
For L = 1 To 1000000
  CompareMemoryString(@s$, @a$, #PB_String_NoCase)
Next
Debug "Constant re-assignment: " + 
      Str(ElapsedMilliseconds() - t) + " milliseconds"

t = ElapsedMilliseconds()
For L = 1 To 1000000
  StrComp(s$, #s)
Next
Debug "Procedure conversion: " +
      Str(ElapsedMilliseconds() - t) + " milliseconds"
A very good alternative until your wish is granted. :wink:
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
davido
Addict
Addict
Posts: 1890
Joined: Fri Nov 09, 2012 11:04 pm
Location: Uttoxeter, UK

Re: an equal '=' test string not case sensitive

Post by davido »

Hi TI-994A,

To give a fairer test, shouldn't the procedure call in the second example be eliminated, thus increasing the speed by a factor of 3 to 4?
DE AA EB
User avatar
TI-994A
Addict
Addict
Posts: 2704
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: an equal '=' test string not case sensitive

Post by TI-994A »

davido wrote:To give a fairer test, shouldn't the procedure call in the second example be eliminated, thus increasing the speed by a factor of 3 to 4?
Hello davido. You're right, excluding the procedure call would increase the speed, but that wouldn't be a fair evaluation as the function has to be called recursively.

Code: Select all

#s = "ABC"

Procedure StrComp(a.s, b.s)
  ProcedureReturn CompareMemoryString(@a, @b, #PB_String_NoCase)  
EndProcedure

a$ = #s
s$= "abc"
Debug CompareMemoryString(@s$, @a$, #PB_String_NoCase)
s$= "aBc"
Debug CompareMemoryString(@s$, @a$, #PB_String_NoCase)
s$= "abC"
Debug CompareMemoryString(@s$, @a$, #PB_String_NoCase)

s$= "abc"
Debug StrComp(s$, #s)
s$= "aBc"
Debug StrComp(s$, #s)
s$= "abC"
Debug StrComp(s$, #s)
The loops were used only for benchmarking, but in actual implementation the strings to be evaluated would change outside the procedure. :)
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
Post Reply