Author Topic: Testing a string for a number  (Read 3814 times)

0 Members and 1 Guest are viewing this topic.

whdjr

  • Guest
Testing a string for a number
« on: April 24, 2006, 11:56:31 AM »
What would be a good and easy/quick way to test a string to see if it is a number?

(atoi "aaa")   ==> 0
(atoi "0")      ==> 0
(atoi "111")  ==> 111

Any ideas?

CAB

  • Global Moderator
  • Seagull
  • Posts: 10376
Re: Testing a string for a number
« Reply #1 on: April 24, 2006, 12:09:20 PM »
How about
Code: [Select]
(numberp (read (substr str 1 1)))or
Code: [Select]
(numberp (read str))
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

Alexander Rivilis

  • Bull Frog
  • Posts: 212
  • Programmer from Kyiv (Ukraine)
Re: Testing a string for a number
« Reply #2 on: April 24, 2006, 12:11:18 PM »
(distof "aaa")  ==> nil
(distof "0") ==> 0.0
(distof "111") ==> 111.0

T.Willey

  • Needs a day job
  • Posts: 5218
Re: Testing a string for a number
« Reply #3 on: April 24, 2006, 12:13:26 PM »
I think this might work.  Written on the fly.

Code: [Select]
(defun IsStrNums (String)

(and
 (mapcar
  '(lambda (x) (>= 48 x 57))
  (vl-string->list String)
 )
)
)

I think that is the right function to use (vl-string->list), but not sure.

Edit:  Change the test to greater than or equal, not less than or equal.
« Last Edit: April 24, 2006, 12:25:46 PM by T.Willey »
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

CAB

  • Global Moderator
  • Seagull
  • Posts: 10376
Re: Testing a string for a number
« Reply #4 on: April 24, 2006, 12:16:57 PM »
That's a nice one Rivilis. :-)
Code: [Select]
(distof "2'-3 1/2\"")
27.5
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.

John Kaul (Se7en)

  • Administrator
  • Needs a day job
  • Posts: 9300
Re: Testing a string for a number
« Reply #5 on: April 24, 2006, 12:21:48 PM »
Oho, potential fun: I think if i remeber correctly numbers take up codes 48 and up in ascii codes. ... 0 = 48 1 = 49...

“Common sense is not so common.” ~Voltaire

--> Donate to TheSwamp.org <--

Alexander Rivilis

  • Bull Frog
  • Posts: 212
  • Programmer from Kyiv (Ukraine)
Re: Testing a string for a number
« Reply #6 on: April 24, 2006, 12:33:34 PM »
That's a nice one Rivilis. :-)
Code: [Select]
(distof "2'-3 1/2\"")
27.5
On my AutoCAD: (distof "2'-3 1/2\"") ==> nil because LUNITS is setting to 2
This function is dependent on LUNITS variable. If you need test only decimal number (not architectural, nor engineering)
you must use (distof val 2)  - val is a testing string.

MP

  • Seagull
  • Posts: 17529
Re: Testing a string for a number
« Reply #7 on: April 24, 2006, 01:23:11 PM »
On my AutoCAD: (distof "2'-3 1/2\"") ==> nil because LUNITS is setting to 2
This function is dependent on LUNITS variable. If you need test only decimal number (not architectural, nor engineering)
you must use (distof val 2)  - val is a testing string.

Perhaps this may be useful --

Code: [Select]
(defun MyDistOf ( string / result )
    (vl-some
       '(lambda (mode)
            (setq result
                (distof
                    string
                    mode
                )
            )
        )
       '(2 3 5 4 1)
    )
    result
)

From here.
\|// Set goal. Experiment tirelessly until
|Oo| practice has become expertise.  Loop.
|- | LinkedIn | Dropbox

whdjr

  • Guest
Re: Testing a string for a number
« Reply #8 on: April 24, 2006, 01:24:07 PM »
Thanks for the reply guys those are some great examples but I think for simplicity sake I will use the method suggested by CAB.

How about
...
Code: [Select]
(numberp (read str))

Thanks again guys,

MP

  • Seagull
  • Posts: 17529
Re: Testing a string for a number
« Reply #9 on: April 24, 2006, 01:33:12 PM »
I don't know the context you're going to use it Will but do be careful --

    Command: (numberp (read "123 abc")) => T

    Command: (numberp (mydistof "123 abc")) => nil


Should your host application consider "123 abc" a number?

\|// Set goal. Experiment tirelessly until
|Oo| practice has become expertise.  Loop.
|- | LinkedIn | Dropbox

whdjr

  • Guest
Re: Testing a string for a number
« Reply #10 on: April 24, 2006, 01:41:36 PM »
Thanks Michael, 

The list will either be a number or a string not both so I think the numberp will work fine.  Thanks for your code though it definitely covers all the bases.  :-)

whdjr

  • Guest
Re: Testing a string for a number
« Reply #11 on: April 24, 2006, 01:51:12 PM »
Michael,

Upon further trials:

    Command: (numberp (read "123 abc")) => T -> In the VLIDE it strips everything off after the space.

    Command: (numberp (read "123abc")) => Nil  If you remove the space then it nil's out.

Just FYI.
 :-)

MP

  • Seagull
  • Posts: 17529
Re: Testing a string for a number
« Reply #12 on: April 24, 2006, 01:58:25 PM »
Precisely why I posted that example Will.

An aside, here's another variant I wrote that is relatively bomb proof --

Code: [Select]
(defun distanceof ( x  / result )
   (vl-catch-all-apply
      '(lambda ()
           (vl-some
              '(lambda (units) (setq result (distof x units)))
               (list (getvar "lunits") 4 5 2 1)
           )
       )
   )   
   result
)

From here.

:)
\|// Set goal. Experiment tirelessly until
|Oo| practice has become expertise.  Loop.
|- | LinkedIn | Dropbox

whdjr

  • Guest
Re: Testing a string for a number
« Reply #13 on: April 24, 2006, 02:04:39 PM »
Thanks Michael,

I like that one a little better because once it catches a T it stops processing.  Very COOL.

Thanks,
 :-)

CAB

  • Global Moderator
  • Seagull
  • Posts: 10376
Re: Testing a string for a number
« Reply #14 on: April 24, 2006, 02:33:39 PM »
Thanks Michael..

Here is something to consider, although may not be relevant to Will.

Code: [Select]
Command: test1                             Command: test2                         
                                                                                   
*--> 3.5        gives number: 3.5          *--> 3.5        gives number: 3.5       
" type: " 2                                                                       
*--> 3 1/2      gives number: 3.5          *--> 3 1/2      gives number: 3.5       
" type: " 2                                                                       
*--> 3 1/2"     gives number: 3.5          *--> 3 1/2"     gives number: 3.5       
" type: " 3                                                                       
*--> 3 1/2'     gives number: 42.0         *--> 3 1/2'     gives number: 42.0     
" type: " 3                                                                       
*--> 3-1/2'     gives number: 42.0         *--> 3-1/2'     gives number: 42.0     
" type: " 3                                                                       
*--> 3'-1"      gives number: 37.0         *--> 3'-1"      gives number: 37.0     
" type: " 3                                                                       
*--> 3' -1"      gives number: 3             **  Invalid Number  **  3' -1"       
" type: " 6                                                                       
*--> 3'- 1"      gives number: 3             **  Invalid Number  **  3'- 1"       
" type: " 6                                                                       
*--> 3'-1       gives number: 37.0         *--> 3'-1       gives number: 37.0     
" type: " 3                                                                       
*--> 3' 1       gives number: 37.0         *--> 3' 1       gives number: 37.0     
" type: " 3                                                                       
*--> 3' 1"      gives number: 37.0         *--> 3' 1"      gives number: 37.0     
" type: " 3                                                                       
*--> 3' 1 1/2   gives number: 37.5         *--> 3' 1 1/2   gives number: 37.5     
" type: " 3                                                                       
*--> 3'-1-1/2   gives number: 37.5         *--> 3'-1-1/2   gives number: 37.5     
" type: " 3                                                                       
*--> 3' 1 1/2"  gives number: 37.5         *--> 3' 1 1/2"  gives number: 37.5     
" type: " 3                                                                       
*--> 3' 1.5     gives number: 37.5         *--> 3' 1.5     gives number: 37.5     
" type: " 3                                                                       
*--> 3' .5      gives number: 36.5         *--> 3' .5      gives number: 36.5     
" type: " 3                                                                       
*--> 3'.5      gives number: 36.5          *--> 3'.5      gives number: 36.5       
" type: " 3                                                                       
  **  Invalid Number  **  10-1               **  Invalid Number  **  10-1         
                                                                                   
*--> -10        gives number: -10.0        *--> -10        gives number: -10.0     
" type: " 2                                                                       
  **  Invalid Number  **  -10-1              **  Invalid Number  **  -10-1         
                                                                                   
*--> .5         gives number: 0.5          *--> .5         gives number: 0.5       
" type: " 2                                                                       
*--> 0.5        gives number: 0.5          *--> 0.5        gives number: 0.5       
" type: " 2                                                                       
*--> 5 -2       gives number: 5              **  Invalid Number  **  5 -2         
" type: " 6                                                                       
*--> 1/2        gives number: 0.5          *--> 1/2        gives number: 0.5       
" type: " 2                                                                       
*--> 1/2"       gives number: 0.5          *--> 1/2"       gives number: 0.5       
" type: " 3                                                                       
*--> 9 1/2      gives number: 9.5          *--> 9 1/2      gives number: 9.5       
" type: " 2                                                                       
*--> 1.55E+01   gives number: 15.5         *--> 1.55E+01   gives number: 15.5     
" type: " 2                                                                       
  **  Invalid Number  **  5A                 **  Invalid Number  **  5A           
                                                                                   
*--> 5 A        gives number: 5              **  Invalid Number  **  5 A           
" type: " 6




Code: [Select]
(defun c:test1 (/ txt txtlst num)
  (setq txtlst
         (list  "3.5       "   ; type:  2
                "3 1/2     "   ; type:  2 ?5
                "3 1/2\"    "  ; type:  4
                "3 1/2'    "   ; type:  4
                "3-1/2'    "   ; type:  4
                "3'-1\"     "  ; type:  4
                "3' -1\"     " ; Invalid Number
                "3'- 1\"     " ; Invalid Number
                "3'-1      "   ; type:  4
                "3' 1      "   ; type:  4
                "3' 1\"     "  ; type:  4
                "3' 1 1/2  "   ; type:  4
                "3'-1-1/2  "   ; type:  4
                "3' 1 1/2\" "  ; type:  4
                "3' 1.5    "   ; type:  4
                "3' .5     "   ; Invalid Number
                "3'.5     "    ; type   3
                "10-1      "   ; Invalid Number
                "-10       "   ; type:  2
                "-10-1     "   ; Invalid Number
                ".5        "   ; type:  2
                "0.5       "   ; type:  2
                "5 -2      "   ; type:  6
                "1/2       "   ; type:  2 ?5
                "1/2\"      "  ; type:  4
                "9 1/2     "   ; type:  2 ?5
                "1.55E+01  "   ; type:  2
                "5A        "   ; Invalid Number
                "5 A       "   ; type:  6
         )
  )
  (setq idx -1)

  ;;  distof will tollerate trailing spaces but not any other character
  ;;  therefore READ can be used to extract numbers followed by characters IF
  ;;  there is a space behing the number (read "12 A") = 12 (read "12a") = "12a"


  (while (< (setq idx (1+ idx)) (length txtlst))
    (setq txt (nth idx txtlst))
    ;;  must be tested in this order (2 1 5 4 3)
    ;; if you use (1 2 3 4 5) you will not get any 2 4 or 5 results
    ;;  further test result in inconsistancies with 3&4 and 5 types
    (cond ((setq num (distof txt 2))
           (setq typ 2)
          )
          ((setq num (distof txt 1))
           (setq typ 1)
          )
          ((setq num (distof txt 5))
           (setq typ 5)
          )
          ((setq num (distof txt 3))
           (setq typ 3)
          )
          ((setq num (distof txt 4))
           (setq typ 4)
          )
          ((setq num (read txt))
           (setq typ 6)
          ); get number if followed by a space "10 a" = 10
           ;; (read "10a") = "10a" so you must test result with
           ;;   (numberp "10a") results in 'not a number'
    )
    (if (numberp num) ;  Got a valid number
      (progn
        (prompt (strcat "\n*--> " txt " gives number: "))
        (princ num)
        (print " type: ")
        (princ typ)
      )
      (prompt (strcat "\n  **  Invalid Number  **  " txt))
    )
  )
  (princ)

)

test2
Code: [Select]
  (while (< (setq idx (1+ idx)) (length txtlst))
    (setq txt (nth idx txtlst))
   
    (setq num (distanceof txt))
    (if (numberp num) ;  Got a valid number
      (progn
        (prompt (strcat "\n*--> " txt " gives number: "))
        (princ num)
        (print)
      )
      (prompt (strcat "\n  **  Invalid Number  **  " txt))
    )
  )
I've reached the age where the happy hour is a nap. (°¿°)
Windows 10 core i7 4790k 4Ghz 32GB GTX 970
Please support this web site.