Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
DAY 036: _STRCMP
#1
Ever want to compare strings, without being called a racist? Well now you can with _STRCMP...

SYNTAX compare% = _STRCMP(string1$, string2$)

What does it do? _STRCMP reads each string from left to right, and compares each ASCII character value. At the first instance where one value is not equal to the other, the function exits and returns:

-1 If the string character being compared in the first string is smaller than the string character being compared in the second string.
 0 If the strings are equal.
 1 If the string character being compared in the first string is larger than the string character being compared in the second string.

Also, remember that: Upper case letters are valued less than lower case letters in the ASCII evaluation. (Wiki).

So here is a quick function using our Keyword of the Day to see how it "functions."

Code: (Select All)
DO
    LINE INPUT "String 1: "; a$
    LINE INPUT "String 2: "; b$: PRINT
    IF a$ = "" AND b$ = "" THEN END
    PRINT scompare(a$, b$)
    PRINT
LOOP

FUNCTION scompare$ (string1$, string2$)
    a% = _STRCMP(string1$, string2$)
    SELECT CASE a%
        CASE -1
            scompare$ = "The first string is smaller than the second string."
        CASE 0
            scompare$ = "The first string is equal to the second string."
        CASE 1
            scompare$ = "The first string is larger than the second string."
    END SELECT
END FUNCTION

Well hold on a minute there, Sparky...

What if I input a$ = 99.9 and b$ = 1024?

Well, _STRCMP would correctly return "The first string is larger than the second string." because with left to right evaluation, "9" of a$ is larger than "1" of b$.

To get a method to tell you if the value of a string representing a numeric value like we use in String Math routines, requires a bit of work...

Code: (Select All)
DO
    LINE INPUT "Number 1: "; s1$
    LINE INPUT "Number 2: "; s2$
    IF s1$ = "" OR s2$ = "" THEN EXIT DO
    gl% = 0: sm_greater_lesser s1$, s2$, gl%
    SELECT CASE gl%
        CASE -1: PRINT s1$; " < "; s2$
        CASE 0: PRINT s1$; " = "; s2$
        CASE 1: PRINT s1$; " > "; s2$
    END SELECT
    PRINT
LOOP

SUB sm_greater_lesser (stringmatha$, stringmathb$, gl%)
    compa$ = stringmatha$: compb$ = stringmathb$ ' So original variables do not get changed.
    DO
        WHILE -1 ' Falx loop.
            IF gl% = 2 THEN EXIT WHILE ' For bypassing sign and decimal adjustments when only positive non-decimal numbers are being evaluated.
            ' Remove trailing zeros after a decimal point.
            IF INSTR(compa$, ".") THEN
                DO UNTIL RIGHT$(compa$, 1) <> "0" AND RIGHT$(compa$, 1) <> "." AND RIGHT$(compa$, 1) <> "-"
                    compa$ = MID$(compa$, 1, LEN(compa$) - 1)
                LOOP
            END IF
            IF INSTR(compb$, ".") THEN
                DO UNTIL RIGHT$(compb$, 1) <> "0" AND RIGHT$(compb$, 1) <> "." AND RIGHT$(compb$, 1) <> "-"
                    compb$ = MID$(compb$, 1, LEN(compb$) - 1)
                LOOP
            END IF

            IF MID$(compa$, 1, 2) = "-0" OR compa$ = "" OR compa$ = "-" THEN compa$ = "0"
            IF MID$(compb$, 1, 2) = "-0" OR compb$ = "" OR compb$ = "-" THEN compb$ = "0"

            ' A - and +
            j% = 0: k% = 0
            IF LEFT$(compa$, 1) = "-" THEN j% = -1
            IF LEFT$(compb$, 1) = "-" THEN k% = -1
            IF k% = 0 AND j% THEN gl% = -1: EXIT DO
            IF j% = 0 AND k% THEN gl% = 1: EXIT DO

            j&& = INSTR(compa$, ".")
            k&& = INSTR(compb$, ".")

            ' A starting decimal and non-decimal.
            IF j&& = 0 AND k&& = 1 THEN
                IF compa$ = "0" THEN gl% = -1 ELSE gl% = 1
                EXIT DO
            END IF
            IF k&& = 0 AND j&& = 1 THEN
                IF compb$ = "0" THEN gl% = 1 ELSE gl% = -1
                EXIT DO
            END IF

            ' remove decimals and align.
            j2&& = 0: k2&& = 0
            IF j&& <> 0 OR k&& <> 0 THEN
                IF j&& THEN compa$ = MID$(compa$, 1, INSTR(compa$, ".") - 1) + MID$(compa$, INSTR(compa$, ".") + 1): j2&& = LEN(compa$) - j&& + 1
                IF k&& THEN compb$ = MID$(compb$, 1, INSTR(compb$, ".") - 1) + MID$(compb$, INSTR(compb$, ".") + 1): k2&& = LEN(compb$) - k&& + 1
                compa$ = compa$ + STRING$(k2&& - j2&&, "0")
                compb$ = compb$ + STRING$(j2&& - k2&&, "0")
            END IF
            EXIT WHILE
        WEND

        ' Remove leading zeros if any.
        DO UNTIL LEFT$(compa$, 1) <> "0"
            compa$ = MID$(compa$, 2)
        LOOP
        IF compa$ = "" THEN compa$ = "0"
        DO UNTIL LEFT$(compb$, 1) <> "0"
            compb$ = MID$(compb$, 2)
        LOOP
        IF compb$ = "" THEN compb$ = "0"

        ' Both positive or both negative whole numbers.

        SELECT CASE LEN(compa$)
            CASE IS < LEN(compb$)
                gl% = -1
            CASE IS = LEN(compb$)
                IF compa$ = compb$ THEN
                    gl% = 0
                ELSEIF compa$ > compb$ THEN gl% = 1
                ELSEIF compa$ < compb$ THEN gl% = -1
                END IF
            CASE IS > LEN(compb$)
                gl% = 1
        END SELECT
        EXIT DO
    LOOP
END SUB

So sure, doing a simple numeric comparison like...

Code: (Select All)
PRINT 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999997 = 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999997.1
 Output 0 for False, which is correct.

...works, but below, using a strings to represent these values, the  VAL() function converts our string numbers to S.N. with some loss of accuracy along the way.

Code: (Select All)
PRINT VAL("99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999997") > VAL("99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999997.1")
Output -1 for True, which is incorrect; as VAL() of both is: 1D+224

So since String Math is designed for enormous numbers, a string comparison function for val() had to be created. If you have an alternative, please post, but otherwise please just keep in mind the difference between _STRCMP, which compares the ASCII character values from left to right, and the function I posted, which compares the numeric value of the strings.

Pete
Reply


Messages In This Thread
DAY 036: _STRCMP - by Pete - 12-16-2022, 07:09 PM
RE: DAY 036: _STRCMP - by SMcNeill - 12-16-2022, 08:00 PM
RE: DAY 036: _STRCMP - by Pete - 12-16-2022, 08:28 PM
RE: DAY 036: _STRCMP - by Pete - 12-17-2022, 06:37 AM



Users browsing this thread: 1 Guest(s)