Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
IsAlpha etc
#1
Do we have the equivalents of the IsAlpha, IsUpper, IsLower, and IsNum in QBPE? I have searched but could only find them in C++.
If not, could they be easily implemented? It seems to me that it would be fairly simple, and would be quite useful.
Of all the places on Earth, and all the planets in the Universe, I'd rather live here (Perth, Western Australia.) Big Grin
Please visit my Website at: http://oldendayskids.blogspot.com/
Reply
#2
Here's IsNum

Code: (Select All)

Function IsNum% (PassedText As String)
dim text$, temp$
dim special$
dim r$
dim r2$
dim r3$
dim check$
dim I as integer

    text$ = PassedText
    special$ = UCase$(Left$(text$, 2))
    Select Case special$
        Case "&H", "&B", "&O"
            'check for symbols on right side of value
            r3$ = Right$(text$, 3)
            Select Case r3$
                Case "~&&", "~%%", "~%&" 'unsigned int64, unsigned byte, unsigned offset
                    text$ = Left$(text$, Len(text$) - 3)
                Case Else
                    r2$ = Right$(text$, 2)
                    Select Case r2$
                        Case "~&", "##", "%&", "%%", "~%", "&&" 'unsigned long, float, offset, byte, unsigned integer, int64
                            text$ = Left$(text$, Len(text$) - 2)
                        Case Else
                            r$ = Right$(text$, 1)
                            Select Case r$
                                Case "&", "#", "%", "!" 'long, double, integer, single
                                    text$ = Left$(text$, Len(text$) - 1)
                            End Select
                    End Select
            End Select
            check$ = "0123456789ABCDEF"
            If special$ = "&O" Then check$ = "01234567"
            If special$ = "&B" Then check$ = "01"
            temp$ = Mid$(UCase$(text$), 2)
            For I = 1 To Len(temp$)
                If InStr(check$, Mid$(temp$, I, 1)) = 0 Then Exit For
            Next
            If I <= Len(temp$) Then IsNum = -1
        Case Else
            If _Trim$(Str$(Val(text$))) = text$ Then IsNum = -1
    End Select
End Function
Reply
#3
IsAlpha is easy.

Code: (Select All)

FUNCTION IsLetter(L as String)
   IsLetter = ( ASC(L) >= ASC("A") and ASC(L) <= ASC("Z")) or ( ASC(L) >= ASC("a") and ASC(L) <= ASC("z") ) 
END FUNCTION

FUNCTION IsWhiteSpace(L as String)
DIM C AS INTEGER
     C = ASC(L)
     IsWhiteSpace = C=32 or C=9 or C=8 or C=13 or C=10 or C=7
END FUNCTION

FUNCTION IsAlpha(S as String)
  DIM TMP AS INTEGER
  DIM I AS LONG
  TMP = _True

  FOR I = 1 to Len(S)
       If IsLetter(MID$(S,I,1)) or IsWhiteSpace(MID$(S,I,1)) THEN
          _Continue
       Else
          TMP = _False
           Exit For
       End If
  Next
  IsAlpha = TMP
End FUNCTION

Reply
#4
You should be able to suss out an IsUpper and IsLower by dissecting IsAlpha

or 

Code: (Select All)

FUNCTION IsUpperLetter(L as String)
  IsUpperLetter = ( ASC(L) >= ASC("A") and ASC(L) <= ASC("Z"))
END FUNCTION

FUNCTION IsLowerLetter(L as String)
   IsLowerLetter =  ( ASC(L) >= ASC("a") and ASC(L) <= ASC("z") )
END FUNCTION

FUNCTION IsLetter (L as String)
  IsLetter = IsLowerLetter(L) or IsUpperLetter(L)
END FUNCTION

FUNCTION IsWhiteSpace(L as String)
DIM C AS INTEGER
    C = ASC(L)
    IsWhiteSpace = C=32 or C=9 or C=8 or C=13 or C=10 or C=7
END FUNCTION


FUNCTION IsAlpha(S as String)
  DIM TMP AS INTEGER
  DIM I AS LONG
  TMP = _True

  FOR I = 1 to Len(S)
      If IsLetter(MID$(S,I,1)) or IsWhiteSpace(MID$(S,I,1)) THEN
          _Continue
      Else
          TMP = _False
          Exit For
      End If
  Next
  IsAlpha = TMP
End FUNCTION

FUNCTION IsUpper(S as String)
  DIM TMP AS INTEGER
  DIM I AS LONG
  TMP = _True

  FOR I = 1 to Len(S)
      If IsUpperLetter(MID$(S,I,1)) or IsWhiteSpace(MID$(S,I,1)) THEN
          _Continue
      Else
          TMP = _False
          Exit For
      End If
  Next
  IsAlpha = TMP
End FUNCTION

FUNCTION IsLower(S as String)
  DIM TMP AS INTEGER
  DIM I AS LONG
  TMP = _True

  FOR I = 1 to Len(S)
      If IsLowerLetter(MID$(S,I,1)) or IsWhiteSpace(MID$(S,I,1)) THEN
          _Continue
      Else
          TMP = _False
          Exit For
      End If
  Next
  IsAlpha = TMP
End FUNCTION




You do know you can force to Upper or Lower with UCASE$ & LCASE$ . 

   If I need to do case insensitive or case sensitive comparisons I use these.
Reply
#5
Probably stuff I don't need... unless you want to throw in 40 virgins, then I'd be happy to convert to IsNum. If this offended anybody, IsTooBad.

Pete Big Grin 

@ahenry3068

I do like the IsNum one. Val by itself is insufficient, so the function must check each character of the string. It is cool that val() can detect some, like &H75, which returns 117 if I remember correctly.

Pete
Reply
#6
(01-22-2026, 12:09 AM)Pete Wrote: Probably stuff I don't need... unless you want to throw in 40 virgins, then I'd be happy to convert to IsNum. If this offended anybody, IsTooBad.

Pete Big Grin 

@ahenry3068

I do like the IsNum one. Val by itself is insufficient, so the function must check each character of the string. It is cool that val() can detect some, like &H75, which returns 117 if I remember correctly.

Pete

   The IsNum one is well optimized and one I use quite a bit,  It's handy !    The other one's I just threw together on the Spot to show Phil how it could be done.
I knew right away they aren't well optimized. !     I typically don't care much about Is Upper or Is Lower.    If I'm doing a comparison that needs to account for case
I usually force the case with UCASE before doing a comparison !

I could optimize it a little by using _orelse instead of or in few of those functions.
Reply
#7
(01-22-2026, 12:23 AM)ahenry3068 Wrote:
(01-22-2026, 12:09 AM)Pete Wrote: Probably stuff I don't need... unless you want to throw in 40 virgins, then I'd be happy to convert to IsNum. If this offended anybody, IsTooBad.

Pete Big Grin 

@ahenry3068

I do like the IsNum one. Val by itself is insufficient, so the function must check each character of the string. It is cool that val() can detect some, like &H75, which returns 117 if I remember correctly.

Pete

   The IsNum one is well optimized and one I use quite a bit,  It's handy !    The other one's I just threw together on the Spot to show Phil how it could be done.
I knew right away they aren't well optimized. !     I typically don't care much about Is Upper or Is Lower.    If I'm doing a comparison that needs to account for case
I usually force the case with UCASE before doing a comparison !

  I could optimize it a little by using _orelse instead of or in few of those functions.

Thanks both for that, but I already use similar constructs when I need them - and yes, I am aware of UCase$ and LCase$, and use these regularly.
What I meant was, could those functions be implemented as a keyword. I know, that's lazy, but if it speeds up or simplifies coding I think it would be worthwhile.
Of all the places on Earth, and all the planets in the Universe, I'd rather live here (Perth, Western Australia.) Big Grin
Please visit my Website at: http://oldendayskids.blogspot.com/
Reply
#8
Code: (Select All)
Screen _NewImage(550, 600, 32)
For i = 0 To 255
    i$ = Chr$(i)
    o$ = i$ + "="
    If IsUpper(i$) Then Print o$ + "Upper",
    If IsLower(i$) Then Print o$ + "lower",
    If IsAlpha(i$) Then Print o$ + "alpha",
Next

Sleep
Cls

Const limit = 16

Dim test(limit) As String

Data "123a.3","-123.456","--234","1.23E15","123","dogfood","678.965","54678","-987134","1E15"
Data "&HFF","&B1001111","&O17","&HFF&&","&B12000222","1.E-12"

For i = 1 To limit
    Read test(i)
Next


For i = 1 To limit
    Print "TEST #"; i; ": "; test(i) + " "
    result = NumType(test(i))
    If result = 0 Then Print "INVALID: "; NumErr$ Else Print "IS A NUMBER: ";
    If result And 1 Then Print "Valid Unsigned Bit.  ";
    If result And 2 Then Print "Valid Unsigned Byte.  ";
    If result And 4 Then Print "Valid Unsigned Integer.  ";
    If result And 8 Then Print "Valid Unsigned Long.  ";
    If result And 16 Then Print "Valid Unsigned Integer64.  ";
    If result And 32 Then Print "Valid Unsigned Bit.  ";
    If result And 64 Then Print "Valid Signed Byte.  ";
    If result And 128 Then Print "Valid Signed Integer.  ";
    If result And 256 Then Print "Valid Signed Long.  ";
    If result And 512 Then Print "Valid Signed Integer64.  ";
    If result And 1024 Then Print "Valid Single.  ";
    If result And 2048 Then Print "Valid Double.  ";
    If result And 4096 Then Print "Valid Float.  ";
    If result And 8192 Then Print "Valid Unsigned Offset.  ";
    If result And 16384 Then Print "Valid Signed Offset.  ";
    Print
    Sleep
Next

Function IsUpper (s As String * 1)
    If Asc(s) = _Clamp(Asc(s), 65, 90) Then IsUpper = _TRUE
End Function

Function IsLower (s As String * 1)
    If Asc(s) = _Clamp(Asc(s), 97, 122) Then IsLower = _TRUE
End Function

Function IsAlpha (s As String * 1)
    If (Asc(s) Or 32) = _Clamp(Asc(s) Or 32, 97, 122) Then IsAlpha = _TRUE
End Function

Function NumType~% (text$)
    Shared NumErr$
    Dim TempNum As Integer
    temp$ = UCase$(_Trim$(text$))
    NumErr$ = "": TempNum = 0

    'First look for manually assigned types
    r1$ = Right$(temp$, 1): r = 1
    r2$ = Left$(Right$(temp$, 2), 1)
    Select Case r1$
        Case "`"
            TestFor = 1 'bit
        Case "%"
            If r2$ = "%" Then
                r = 2
                TestFor = 2 'byte
            Else
                TestFor = 3 'integer
            End If
        Case "&" 'long, int64, offset
            If r2$ = "&" Then
                r = 2
                TestFor = 5 'int64
            ElseIf r2$ = "%" Then
                r = 2
                TestFor = 9 'offset
            Else
                TestFor = 4 'long
            End If
        Case "!" 'single
            TestFor = 6
        Case "#" 'double, float
            If r2$ = "#" Then
                r = 2
                TestFor = 8 'float
            Else
                TestFor = 7 'double
            End If
        Case Else 'there's no set type
            TestFor = 0
            r = 0
    End Select


    temp$ = Left$(temp$, Len(temp$) - r) 'strip off the type symbol
    Select Case TestFor
        Case 1 To 5, 9
            r$ = Right$(temp$, 1)
            If r$ = "~" Then Unsigned = -1: temp$ = Left$(temp$, Len(temp$) - 1)
    End Select

    'check for valid prefixes

    l$ = Left$(temp$, 2)
    Select Case l$
        Case "&H"
            temp$ = Mid$(temp$, 3)
            For i = 1 To Len(temp$)
                t$ = Mid$(temp$, i, 1)
                Select Case t$
                    Case "0" To "9", "A" To "F" 'valid
                    Case Else
                        NumErr$ = NumErr$ + "Invalid Character (" + t$ + ") encountered.  "
                End Select
            Next
            If NumErr$ <> "" Then Exit Function
            GoTo evaluateintegers
        Case "&B"
            temp$ = Mid$(temp$, 3)
            For i = 1 To Len(temp$)
                t$ = Mid$(temp$, i, 1)
                Select Case t$
                    Case "0", "1" 'only valid bit characters
                    Case Else
                        NumErr$ = NumErr$ + "Invalid Character (" + t$ + ") encountered.  "
                End Select
            Next
            If NumErr$ <> "" Then Exit Function
            GoTo evaluateintegers
        Case "&O"
            temp$ = Mid$(temp$, 3)
            For i = 1 To Len(temp$)
                t$ = Mid$(temp$, i, 1)
                Select Case t$
                    Case "0" To "7" 'only valid oct characters
                    Case Else
                        NumErr$ = NumErr$ + "Invalid Character (" + t$ + ") encountered.  "
                End Select
            Next
            If NumErr$ <> "" Then Exit Function
            GoTo evaluateintegers
    End Select


    'Test for easy integers
    'First check for positive/negative values; flag for invalid cases of multiple negation.
    If Mid$(temp$, 1, 1) = "-" Then
        negative = -1: temp$ = Mid$(temp$, 2) 'strip off the initial negative
    ElseIf Mid$(temp$, 1, 1) = "+" Then
        temp$ = Mid$(temp$, 2) 'strip off the initial positive
    End If

    For i = 1 To Len(temp$)
        If Mid$(temp$, i, 1) = "-" Then minus = minus + 1
        If Mid$(temp$, i, 1) = "+" Then plus = plus + 1
        If Mid$(temp$, i, 1) = "." Then period = period + 1 'Go ahead and check for multiple periods while we're at it.
        If Mid$(temp$, i, 1) = "E" Or Mid$(temp$, i, 1) = "D" Then
            Exponent = Exponent + 1
            If Mid$(temp$, i + 1, 1) = "-" Or Mid$(temp$, i + 1, 1) = "+1" Then ExponentSign = -1
        End If
    Next

    If period = 0 And Exponent = 0 Then 'we should only have integers to process
        For i = 1 To Len(temp$)
            t$ = Mid$(temp$, i, 1)
            If t$ < "0" Or t$ > "9" Then NumErr$ = NumErr$ + "Invalid Character (" + t$ + ") encountered.  ": Exit Function
        Next
        GoTo evaluateintegers
    End If

    'At this point forward, we should only have REAL numbers to process

    If Exponent > 1 Then NumErr$ = NumErr$ + "Multiple E/D exponent characters in string.  ": Exit Function

    If ExponentSign = 0 Then
        If minus Then NumErr$ = NumErr$ + "Multiple negative signs (-) encountered.  ": Exit Function
        If plus Then NumErr$ = NumErr$ + "Multiple negative signs (-) encountered.  ": Exit Function
    Else
        If minus > 1 Then NumErr$ = NumErr$ + "Multiple negative signs (-) encountered.  ": Exit Function
        If plus > 1 Then NumErr$ = NumErr$ + "Multiple negative signs (-) encountered.  ": Exit Function
    End If

    If period > 1 Then NumErr$ = NumErr$ + "Multiple decimal points (.) encountered.  ": Exit Function

    If Exponent And period Then
        e = InStr(temp$, "E")
        If e = 0 Then e = InStr(temp$, "D")
        p = InStr(temp$, ".")
        If p > e Then NumErr$ = NumErr$ + "Decimal points (.) AFTER E/D exponent encountered.  ": Exit Function
    End If


    For i = 1 To Len(temp$)
        t$ = Mid$(temp$, i, 1)
        Select Case t$
            Case "0" To "9", "-", "+", ".", "D", "E" 'we should have validated all these characters earlier
            Case Else 'so anything else is invalid
                NumErr$ = NumErr$ + "Invalid Character (" + t$ + ") encountered.  ": Exit Function
        End Select
    Next

    If NumErr$ <> "" Then Exit Function


    'We should've passed all the error checking by this point -- I think...


    evaluateintegers:
    t## = Val(text$)

    'first compare for all types
    If Int(t##) = t## Then
        If t## = -1 Or t## = 0 Then TempNum = TempNum Or 32 'signed bit
        If t## >= -128 And t## <= 127 Then TempNum = TempNum Or 64 'signed byte
        If t## >= -32768 And t## <= 32767 Then TempNum = TempNum Or 128 'signed integer
        If t## >= -2147483648 And t## <= 2147483647 Then TempNum = TempNum Or 256 'signed long
        If t## >= -9223372036854775808 And t## <= 9223372036854775807 Then
            TempNum = TempNum Or 512 'signed integer64
            TempNum = TempNum Or 16384 'signed offset
        End If
        If t## = 1 Or t## = 0 Then TempNum = TempNum Or 1 'unsigned bit
        If t## >= 0 And t## <= 255 Then TempNum = TempNum Or 2 'unsigned byte
        If t## >= 0 And t## <= 65535 Then TempNum = TempNum Or 4 'unsigned integer
        If t## >= 0 And t## <= 4294967295 Then TempNum = TempNum Or 8 'unsigned long
        If t## >= 0 And t## <= 18446744073709551615 Then
            TempNum = TempNum Or 16 'unsigned integer64
            TempNum = TempNum Or 8192 'unsigned offset
        End If
    End If

    If t## >= -2.802597D45 And t## <= 3.402823D+38 Then
        TempNum = TempNum Or 1024 'single
    End If
    If t## >= -4.490656458412465E324 And t## <= 1.797693134862310E+308 Then TempNum = TempNum Or 2048 'double
    If t## >= -1.18E4932 And t## <= 1.18E+4932 Then TempNum = TempNum Or 4096 'float

    If r Then 'we have specific suffix; only decide if the value is valid for it
        TempNum = 0
        If Not Unsigned Then 'unsigned
            Select Case TestFor
                Case 1
                    If t## = -1 Or t## = 0 Then TempNum = 32 'signed bit
                Case 2
                    If t## >= -128 And t## <= 127 Then TempNum = 64 'signed byte
                Case 3
                    If t## >= -32768 And t## <= 32767 Then TempNum = 128 'signed integer
                Case 4
                    If t## >= -2147483648 And t## <= 2147483647 Then TempNum = 256 'signed long
                Case 5, 9
                    If t## >= -9223372036854775808 And t## <= 9223372036854775807 Then
                        If TestFor = 5 Then
                            TempNum = 512 'signed integer64
                        Else
                            TempNum = 16384 'signed offset
                        End If
                    End If
                Case 6
                    If t## >= -2.802597E-45 And t## <= 3.402823E+38 Then TempNum = 1024 'single
                Case 7
                    If t## >= -4.490656458412465E-324 And t## <= 1.797693134862310E+308 Then TempNum = 2048 'double
                Case 9
                    If t## >= -1.18E-4932 And t## <= 1.18E+4932 Then TempNum = 4096 'float
            End Select
        Else
            Select Case TestFor
                Case 1
                    If t## = 0 Or t## = 1 Then TempNum = 1 'unsigned bit
                Case 2
                    If t## >= 0 And t## <= 255 Then TempNum = 2 'unsigned byte
                Case 3
                    If t## >= 0 And t## <= 65535 Then TempNum = 4 'unsigned integer
                Case 4
                    If t## >= 0 And t## <= 4294967295 Then TempNum = 8 'unsigned long
                Case 5, 9
                    If t## >= 0 And t## <= 18446744073709551615 Then
                        If TestFor = 5 Then
                            TempNum = 16 'unsigned integer64
                        Else
                            TempNum = 8192 'unsigned offset
                        End If
                    End If
            End Select
        End If
        If TempNum = 0 Then NumErr$ = "Invalid Suffix.  "
    End If
    NumType = TempNum
End Function

The above makes these functions work for you.  It also tells you what numeric TYPE a number is, if you're interested in that bit of information as well, so you can not only determine if it's a valid number, but if it's a valid _BYTE or whatnot.  Wink
Reply
#9
(01-21-2026, 10:45 PM)ahenry3068 Wrote: Here's IsNum

Code: (Select All)

Function IsNum% (PassedText As String)
dim text$, temp$
dim special$
dim r$
dim r2$
dim r3$
dim check$
dim I as integer

    text$ = PassedText
    special$ = UCase$(Left$(text$, 2))
    Select Case special$
        Case "&H", "&B", "&O"
            'check for symbols on right side of value
            r3$ = Right$(text$, 3)
            Select Case r3$
                Case "~&&", "~%%", "~%&" 'unsigned int64, unsigned byte, unsigned offset
                    text$ = Left$(text$, Len(text$) - 3)
                Case Else
                    r2$ = Right$(text$, 2)
                    Select Case r2$
                        Case "~&", "##", "%&", "%%", "~%", "&&" 'unsigned long, float, offset, byte, unsigned integer, int64
                            text$ = Left$(text$, Len(text$) - 2)
                        Case Else
                            r$ = Right$(text$, 1)
                            Select Case r$
                                Case "&", "#", "%", "!" 'long, double, integer, single
                                    text$ = Left$(text$, Len(text$) - 1)
                            End Select
                    End Select
            End Select
            check$ = "0123456789ABCDEF"
            If special$ = "&O" Then check$ = "01234567"
            If special$ = "&B" Then check$ = "01"
            temp$ = Mid$(UCase$(text$), 2)
            For I = 1 To Len(temp$)
                If InStr(check$, Mid$(temp$, I, 1)) = 0 Then Exit For
            Next
            If I <= Len(temp$) Then IsNum = -1
        Case Else
            If _Trim$(Str$(Val(text$))) = text$ Then IsNum = -1
    End Select
End Function

Note that this can fail with scientific notation values.
Reply
#10
If you want lean, mean and short-circuited.


Attached Files
.bi   String.bi (Size: 4.27 KB / Downloads: 7)
.bm   String.bm (Size: 8.68 KB / Downloads: 8)
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)