GLBasic forum

Main forum => GLBasic - en => Topic started by: Hatonastick on 2011-Nov-09

Title: Is there a more efficient way to do this?
Post by: Hatonastick on 2011-Nov-09
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
Title: Re: Is there a more efficient way to do this?
Post by: Falstaff on 2011-Nov-09
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 (http://en.wikipedia.org/wiki/Regular_expression), but AFAIK GLB currently does not. In something like perl, that could be done in a single line pretty handily.
Title: Re: Is there a more efficient way to do this?
Post by: Hatonastick on 2011-Nov-09
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.
Title: Re: Is there a more efficient way to do this?
Post by: 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
Title: Re: Is there a more efficient way to do this?
Post by: spacefractal on 2011-Nov-09
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
Title: Re: Is there a more efficient way to do this?
Post by: 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?
Title: Re: Is there a more efficient way to do this?
Post by: Hatonastick on 2011-Nov-14
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.  ;/
Title: Re: Is there a more efficient way to do this?
Post by: Hatonastick on 2011-Nov-14
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.
Title: Re: Is there a more efficient way to do this?
Post by: Kitty Hello on 2011-Nov-14
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...
Title: Re: Is there a more efficient way to do this?
Post by: Hatonastick on 2011-Nov-14
Sounds good. :)