Is there a more efficient way to do this?

Previous topic - Next topic

Hatonastick

Basically I run through a string one character at a time and copy only the characters 0-9, a-z, A-Z to the new string.  Everything else is removed/ignored.  Generally flag strings will be quite short (probably < 10 characters), but I still can't help thinking there's a better way to do this.

Code (glbasic) Select
// Make sure given flag string contains only letters and numbers.
// Wish I could think of a faster, more efficient way to do this.  One that
// didn't rely on going through the string one character at a time.
FUNCTION FlagMakeAlpha: BYREF flag$
  LOCAL l, i, temp$, c$
 
  // Get the length of the given string.
  l = LEN(flag$)
  // Make sure the string isn't zero in length and process it.
  IF l > 0
    // Run through the string one character at a time.
    FOR i = 0 TO (l - 1)
      c$ = MID$(flag$, i, 1)
      // Remove anything that doesn't fall in the range of 0-9, a-z, A-Z.
      IF (ASC(c$) >= 48 AND ASC(c$) <= 57) OR (ASC(c$) >= 65 AND ASC(c$) <= 90) OR (ASC(c$) >= 97 AND ASC(c$) <= 122)
        temp$ = temp$ + c$
      ENDIF
    NEXT
    flag$ = temp$
  ENDIF
ENDFUNCTION
Mat. 5: 14 - 16

Android: Toshiba Thrive Tablet (3.2), Samsung Galaxy Tab 2 (4.1.2).
Netbook: Samsung N150+ Netbook (Win 7 32-bit + Ubuntu 11.10).
Desktop: Intel i5 Desktop with NVIDIA GeForce GTX 460 (Win 8.1 64-bit).

Falstaff

While your approach may not seem incredibly elegant.. I don't see any other way around it inside GLB currently. What you're asking for would be incredibly easy in any language that had Regular Expressions, but AFAIK GLB currently does not. In something like perl, that could be done in a single line pretty handily.

Hatonastick

#2
Yeah I really miss regex...

Hmm wonder if I can access that using inline.

Edit: I'm going senile, standard C doesn't have regex (as far as I can see).  I must have written my own some time back, going to see if I can find it.

Edit: Ah ok, I would have used the POSIX version while programming under UNIX.
Mat. 5: 14 - 16

Android: Toshiba Thrive Tablet (3.2), Samsung Galaxy Tab 2 (4.1.2).
Netbook: Samsung N150+ Netbook (Win 7 32-bit + Ubuntu 11.10).
Desktop: Intel i5 Desktop with NVIDIA GeForce GTX 460 (Win 8.1 64-bit).

Slydog

Ha, I don't know any fancy way to do this either, but here's a crack at a slightly different approach.
I don't think you need your length check, as an empty string will just not enter the FOR loop.

Code (glbasic) Select
FUNCTION FlagMakeAlpha: BYREF flag$
    LOCAL allowed$ = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
    LOCAL i%, temp$="", c$

    // Run through the string one character at a time.
    FOR i = 0 TO LEN(flag$) - 1
        c$ = MID$(flag$, i, 1)
        IF INSTR(allowed$, c$) >= 0 THEN INC temp$, c$
    NEXT
    flag$ = temp$
ENDFUNCTION
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

spacefractal

#4
I do a similar way when I print text (from the lastest post). But I do use a static 255 char dim to hold a either 1 or 0 (which run once from the allowed$ string). When its 1, its allowered, and when its 0 its disallowred. When using with a type, you could include positions where they are when you draw them with POLYVECTOR.

Something like this (which need to been modiced), which run once in the function (can been checked by a static variable):
Code (glbasic) Select

FOR i=0 TO LEN(font$)
LOCAL b=ASC(MID$(font$, i, 1))  //<- font$=allowered$
aceii[b].l=1
NEXT
Genius.Greedy Mouse - Karma Miwa - Spot Race - CatchOut - PowerUp Elevation - The beagle Jam - Cave Heroes 2023 - https://spacefractal.itch.io/

Kitty Hello

Would it be cool to have an ASC command that can take an optional 2nd arg for the index of the character?

Hatonastick

Quote from: Slydog on 2011-Nov-09
Ha, I don't know any fancy way to do this either, but here's a crack at a slightly different approach.
I don't think you need your length check, as an empty string will just not enter the FOR loop.

Code (glbasic) Select
FUNCTION FlagMakeAlpha: BYREF flag$
    LOCAL allowed$ = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
    LOCAL i%, temp$="", c$

    // Run through the string one character at a time.
    FOR i = 0 TO LEN(flag$) - 1
        c$ = MID$(flag$, i, 1)
        IF INSTR(allowed$, c$) >= 0 THEN INC temp$, c$
    NEXT
    flag$ = temp$
ENDFUNCTION

Actually I ended up making your routine into a 'check the flag string for illegal characters' routine instead, and failing if the string contained any as it fits my flag system better.  I should have thought of having a string of legal characters myself.  I must have been having a slow day.  ;/
Mat. 5: 14 - 16

Android: Toshiba Thrive Tablet (3.2), Samsung Galaxy Tab 2 (4.1.2).
Netbook: Samsung N150+ Netbook (Win 7 32-bit + Ubuntu 11.10).
Desktop: Intel i5 Desktop with NVIDIA GeForce GTX 460 (Win 8.1 64-bit).

Hatonastick

Quote from: Kitty Hello on 2011-Nov-10
Would it be cool to have an ASC command that can take an optional 2nd arg for the index of the character?
Nah, don't think it's needed.  Easy enough to use MID$() etc. if you have to.  Can't speak for anyone else, but I like ASC() as it is.
Mat. 5: 14 - 16

Android: Toshiba Thrive Tablet (3.2), Samsung Galaxy Tab 2 (4.1.2).
Netbook: Samsung N150+ Netbook (Win 7 32-bit + Ubuntu 11.10).
Desktop: Intel i5 Desktop with NVIDIA GeForce GTX 460 (Win 8.1 64-bit).

Kitty Hello

Next update has an ASC command with optional 2nd parameter. The benefit is, that it's muuuch quicker to do this instead of MID$(a$, i, 1) for a long string, when you just want to find the first non-ascii character or so...

Hatonastick

Mat. 5: 14 - 16

Android: Toshiba Thrive Tablet (3.2), Samsung Galaxy Tab 2 (4.1.2).
Netbook: Samsung N150+ Netbook (Win 7 32-bit + Ubuntu 11.10).
Desktop: Intel i5 Desktop with NVIDIA GeForce GTX 460 (Win 8.1 64-bit).