April 20, 2024, 12:41:15 AM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Checking a string is all uppercase

Started by Andy, November 11, 2019, 04:30:57 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Andy

Hi all,

Just looking at my convert keywords program - I will release it soon as it his all 1,661 IWB keywords in now, and works 100% and much faster...

But, I was wondering is there a very quick way to detect if a string is all uppercase or not?
(maybe scanf in "C" might be quick - if so can you send an expample please?).

The simple logic for my program is this...

Don't try to convert a word that is already all uppercase.

Thanks,
Andy.
 :)



 
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

fasecero

I think you would need to go letter by letter and see if each one of them falls within the ASCII range of the capital letters (A = 65, B = 66 ...) but this will probably be slower than simply convert to uppercase no matter what format is comming inside the string. I don't know any built-in function to do this...

The c-runtime function for uppercase is _strupr. And _strlwr for lowercase.

I made an example where I call UCASE$ and _strupr 100,000 times. In my notebook _strupr takes up about 60 milliseconds to complete and UCASE$ about 90. The speed of UCASE$ is impressive, anyway.

$INCLUDE "windowssdk.inc"

OPENCONSOLE
PRINT

string text = " HeLlO hOw Are YoU "
_strupr(text) : PRINT text ' uppercase
_strlwr(text) : PRINT text ' lowercase

PRINT

int j
string buffer = ""

' UCASE SPEED
PRINT "UCASE test (100 000 calls)"
DWORD time1 = GetTickCount()
FOR j = 1 TO 100000
buffer = " HeLlO hOw Are YoU " + STR$(j)
buffer = UCASE$(buffer)
NEXT j
DWORD time2 = GetTickCount()
PRINT "UCASE milliseconds: " + STR$(time2 - time1)
PRINT

' _strupr SPEED
PRINT "_strupr test (100 000 calls)"
time1 = GetTickCount()
FOR j = 1 TO 100000
buffer = " HeLlO hOw Are YoU " + STR$(j)
_strupr(buffer)
NEXT j
time2 = GetTickCount()
PRINT "_strupr milliseconds: " + STR$(time2 - time1)
PRINT

PRINT "Press any key to exit"
DO:UNTIL INKEY$ <> ""
CLOSECONSOLE


Andy

Thanks as always fasecero,

Brian found this code:

autodefine "off"

$include "windowssdk.inc"

STRING text1="abcde"
STRING text2="ABCDE"

openconsole
print

INT result=lstrcmpA(&text1,&text2)

IF result=0
PRINT "Strings are the same"
ELSE
PRINT "Strings are different"
ENDIF

do:until inkey$<>""
closeconsole
end

Thanks Brian! it doesn't seems to slow down my program too much.

Andy.
 :)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.

fasecero

November 12, 2019, 06:12:28 AM #3 Last Edit: November 12, 2019, 06:14:21 AM by fasecero
That's ok, but in the long run it will slow down the performance a bit. Did a second test to confirm my theory with and without lstrcmp...

IF lstrcmp(text, cap) <> 0 THEN _strupr(text) ' convert to uppercase only when necessaryVs
_strupr(text) ' convert to uppercase always, even if 'text' is capitalized already

$INCLUDE "windowssdk.inc"

OPENCONSOLE
PRINT
DoSomething()

PRINT
PRINT "Press any key to exit"
DO:UNTIL INKEY$ <> ""
CLOSECONSOLE

SUB DoSomething()
SeedRandomNumbers()

string text = ""
string cap = "HELLO HOW ARE YOU"
string mix = "HeLlO hOw Are YoU"
string low = "hello how are you"

INT j
INT value
DWORD time1 = GetTickCount()
PRINT "_strupr test with lstrcmp (1,000,000 calls)"
FOR j = 1 TO 1000000
value = GetRandomNumber(1, 3)

SELECT value
case 1 : text = cap
case 2 : text = mix
case 3 : text = low
ENDSELECT

IF lstrcmp(text, cap) <> 0 THEN _strupr(text) ' USING lstrcmp
NEXT j
DWORD time2 = GetTickCount()
PRINT "milliseconds: " + STR$(time2 - time1)
PRINT

time1 = GetTickCount()
PRINT "_strupr test without lstrcmp (1,000,000 calls)"
FOR j = 1 TO 1000000
value = GetRandomNumber(1, 3)

SELECT value
case 1 : text = cap
case 2 : text = mix
case 3 : text = low
ENDSELECT

_strupr(text) ' NOT USING lstrcmp
NEXT j
time2 = GetTickCount()
PRINT "milliseconds: " + STR$(time2 - time1)
PRINT
ENDSUB

SUB SeedRandomNumbers() ' seeding for the first time only!
srand(GetTickCount())
ENDSUB

SUB GetRandomNumber(INT min, INT max), INT ' range : [min, max]
   RETURN min + _rand() % (max + 1 - min)
ENDSUB

After ONE MILLION calls, the second route takes around 60 miliseconds to complete and lstrcmp takes around 500, which is like 10x more time! So, the second approach, even though it is redundant when 'text' is already capitalized, is much faster.

Happy coding!

Brian

Just tried Fasecero's code - I got 297 and 63 milliseconds respectively, for the two tests

Impressive!

Brian

Andy

Thanks guys!

I will give a try just as I have solved a pointer problem which is holding me up at the moment.

Thanks!
Andy.
 :)
Day after day, day after day, we struck nor breath nor motion, as idle as a painted ship upon a painted ocean.