Check if user input through DCL is real number

Check if user input through DCL is real number

betsy.kirtland
Enthusiast Enthusiast
1,474 Views
11 Replies
Message 1 of 12

Check if user input through DCL is real number

betsy.kirtland
Enthusiast
Enthusiast

Hi all,

 

I am trying to incorporate some error checking into my code to ensure that the user inputs a real number.  Here's a snippet of what I have:

(defun checkval ()

 (if
   (not
     (and
       (numberp (atof (get_tile "left_offset")))
       (numberp (atof (get_tile "left_overhang")))
       (numberp (atof (get_tile "right_offset")))
       (numberp (atof (get_tile "right_overhang")))
       ) ;end and
     ) ; end not
     (set_tile "error" "Offset and overhang inputs must be numbers!")
 )
)

 

However, when I test it out by putting a letter into any of those edit boxes, the routine crashes and displays the following message in the command bar:

; error: bad argument type: stringp nil

 

Any help or thoughts would be greatly appreciated!

0 Likes
Accepted solutions (1)
1,475 Views
11 Replies
Replies (11)
Message 2 of 12

hak_vz
Advisor
Advisor

Break this to segments

(numberp (atof (get_tile "left_offset")))

If anything meaningful is received from DCL tile, even an empty string atof will  convert it to real number.

First test if received value exist, and than test use atof and numberp. Check if names of a dcl tiles are ok.

 

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
0 Likes
Message 3 of 12

john.uhden
Mentor
Mentor

That makes no sense.

As @hak_vz pointed out, (atof  "anystring") will return 0.0.

Might one of the tiles be missing in the DCL?

 

Anyway, that could be shortened as well...

(defun checkval ()
 (or
   (and
     (numberp (atof (get_tile "left_offset")))
     (numberp (atof (get_tile "left_overhang")))
     (numberp (atof (get_tile "right_offset")))
     (numberp (atof (get_tile "right_overhang")))
   ) ;end and
   (set_tile "error" "Offset and overhang inputs must be numbers!")
 ) ;end or
)
;; or even...
(vl-every (mapcar '(lambda (x)(numberp (atof (get_tile x))))'("left_offset" "left_overhang" "right_offset" "right_overhang")))

Check your code to see how checkval is being used as it will always return T.

Actually your version will return nil if all the get_tiles are okay, and will return the error string if not.

John F. Uhden

0 Likes
Message 4 of 12

john.uhden
Mentor
Mentor

@betsy.kirtland 

Two other thoughts:

1.  Instead of using (numberp (atof (get_tile ...))) try using (numberp (read (get_tile ...)))

2.  If it's not against your style, you could use (alert <error message>) instead of (set_tile "error" ...)

     alert always returns nil and it can be called while a dialog is active.

 

John F. Uhden

0 Likes
Message 5 of 12

_gile
Consultant
Consultant

Hi,

Instead of using (numberp (read ...)) you can simply use (distof ...).

distof returns nil if the string does not represent a valid number or fraction.

_$ (distof "25.4")
25.4
_$ (distof "12")
12.0
_$ (distof "3/8")
0.375
_$ (distof "foo")
nil


Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 6 of 12

john.uhden
Mentor
Mentor
@_gile
A definite improvement!
Even (distof "") returns nil

John F. Uhden

0 Likes
Message 7 of 12

betsy.kirtland
Enthusiast
Enthusiast

Thank you @_gile and @john.uhden.  Changing my (numberp (atof ... )) to just (distof ..) made the error go away!

0 Likes
Message 8 of 12

john.uhden
Mentor
Mentor
That's good news, but we would like to know why.
I suspect that the (numberp (atof ...)) wasn't the problem but how you
were using checkval because of what it returns.
Please let us know, and accept @_gile 's response as the solution.

John F. Uhden

0 Likes
Message 9 of 12

betsy.kirtland
Enthusiast
Enthusiast

@john.uhden @_gile I may have spoken too soon.  I'm still getting that error, now even when I input numbers into the edit boxes.  John, here's where I'm using checkval:

 

 

;When the user clicks "OK", check all the values of their inputs
  (action_tile "accept" ;when the user clicks OK, do the following
     "(progn
      	(checkval) (setq num_gird (atof (get_tile \"gird_list\")))
        (setq num_gird (fix num_gird))
        (setq num_gird (nth num_gird NumGirdList))
        )" 
   );end action tile

 

 

And the full code of checkval:

(defun checkval ()

 (if
   (not
     (and
       (distof (get_tile "left_offset"))
       (distof (get_tile "left_overhang"))
       (distof (get_tile "right_offset"))
       (distof (get_tile "right_overhang"))
       ) ;end and
     ) ; end not
     (set_tile "error" "Offset and overhang inputs must be numbers!")

   ;Else Ifs:
  	(if (= (get_tile "left_offset") "")
	  (progn
	     (set_tile "error" "You must enter a value for the Left Edge of Deck Offset.")
	     (mode_tile "left_offset" 3)
	   );end progn

	(if (= (get_tile "left_overhang") "")
	  (progn
	     (set_tile "error" "You must enter a value for the Left Edge of Deck Overhang.")
	     (mode_tile "left_overhang" 3)
	  );end progn
	      
	(if (= (get_tile "right_offset") "")
	  (progn
	     (set_tile "error" "You must enter a value for the Right Edge of Deck Offset.")
	     (mode_tile "right_offset" 3)
	  );end progn

	(if (= (get_tile "right_overhang") "")
	  (progn
	     (set_tile "error" "You must enter a value for the Right Edge of Deck Overhang.")
	     (mode_tile "right_overhang" 3)
	  );end progn
	  
	(done_dialog)  ;if none of those things happen, close the dialog box.

	); end 4th else if
        ); end 3rd else if
        ); end 2nd else if
        ); end 1st else if
   );end Main If
);end function

 

 

Full code attached if more context would be useful.

 

0 Likes
Message 10 of 12

hak_vz
Advisor
Advisor
Accepted solution
;Program to help come up with preliminary bridge framing plans.

;All angles, radii, offsets, etc. should be manually checked by the user in model space.

(defun C:FRAMING (/ alignment left_offset left_overhang right_offset right_overhang num_gird)

  (FramingInput)
  ;(setq alignment (entsel "\nSelect Alignment:"))
  ;(command "._offset" left_offset alignment)

  (alert (strcat "You have input " left_offset "ft \nfor the left offset and"
		 right_overhang "ft for the right overhang."))

  (princ)
  
  );end function


;-------------------------Run the dialog box---------------------------

(defun FramingInput (/ dcl_id NumGirdList num_gird)
  (setq dcl_id (load_dialog "D:\\FramingInput.dcl"));load dialog box and set a reference to it

  (if (not (new_dialog "FramingInput" dcl_id));if the dialog definition is not found, exit the program.
    (progn
      (alert "The DCL file for user input could not be found.")
      (exit)
      );end progn
  );end if

;Define the list that the user can choose from for Number of Girders
  ;(setq num_gird 2)
  (setq NumGirdList '("2" "3" "4" "5" "6" "7" "8" "9" "10" "11" "12" "13" "14"))
  (start_list "gird_list")
  (mapcar 'add_list NumGirdList)
  (end_list)
  

;Define variables used in the above main code from the user inputs from the dialog box
  (action_tile "left_offset" "(setq left_offset $value)")
  (action_tile "left_overhang" "(setq left_overhang $value)")
  (action_tile "right_offset" "(setq right_offset $value)")
  (action_tile "right_overhang" "(setq right_overhang $value)")
  ;note to self: need to add a line for checking if girder spacing is set to variable or constant

;If the user presses cancel, close the dialog box.
  (action_tile "cancel" "(done_dialog) (setq userclick nil)") ;close dialog, set flag


;When the user clicks "OK", check all the values of their inputs
  (action_tile "accept" ;when the user clicks OK, do the following
     "(progn
      	(checkval)
        )" 
   );end action tile

  
  (start_dialog)
  (unload_dialog dcl_id)

  (princ)

);end function



;------------------Check Dialog Box Inputs-------------------------
(defun checkval ()

 (if
   (not
     (or
       (distof (get_tile "left_offset"))
       (distof (get_tile "left_overhang"))
       (distof (get_tile "right_offset"))
       (distof (get_tile "right_overhang"))
       ) ;end and
     ) ; end not
     (set_tile "error" "Offset and overhang inputs must be numbers!")
 
   ;Else Ifs:
  	(cond 
		((= (get_tile "left_offset") "")
			 (set_tile "error" "You must enter a value for the Left Edge of Deck Offset.")
			 (mode_tile "left_offset" 3)
		)
		((= (get_tile "left_overhang") "")

		 (set_tile "error" "You must enter a value for the Left Edge of Deck Overhang.")
		 (mode_tile "left_overhang" 3)
		)
		((= (get_tile "right_offset") "")
			 (set_tile "error" "You must enter a value for the Right Edge of Deck Offset.")
			 (mode_tile "right_offset" 3)
		)
		((= (get_tile "right_overhang") "")
			(set_tile "error" "You must enter a value for the Right Edge of Deck Overhang.")
			(mode_tile "right_overhang" 3)
		)
		
	   (T(done_dialog))  ;if none of those things happen, close the dialog box.

	)
   )


  );end function

 

To many IF statements wrongly written, and error in actiontile ACCEPT.

Autolisp doesn't have IF THEN ELSE ELSEIF form as other programming languages.

It's only (IF (true block)(false block)). Better use COND instead.

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
0 Likes
Message 11 of 12

betsy.kirtland
Enthusiast
Enthusiast

Thank you, @hak_vz .  I didn't know that autolisp wouldn't like my nested IFs.

 

I copy-pasted your (cond...) format into my code and now the error checking works - although, I don't think think we need the ElseIf block at all.  (distof (get_tile... )) reports nil if the input into the dialog box is a non-number or if it is blank. 

 

Regardless of if the ElseIf block is included or not, I am still getting the ; error: bad argument type: stringp nil if the user only inputs numbers into the dialog box (which is what we want!). I've included a screen recording of the the error checking working but getting the error after putting in numbers.

 

 

0 Likes
Message 12 of 12

betsy.kirtland
Enthusiast
Enthusiast

Actually... there was another issue in a different part of my code.  All set now!!