Lisp:如何提示阅读浮点数?
Lisp: How to prompt-read a float?
我有一个函数,我同时使用解析整数和提示阅读。但是,我需要这些整数之一是浮点数。当我将 parse-integer 更改为 parse-float 时,它不再有效。
这是函数:
(defun prompt-for-cat ()
(add-record
(make-cat
(prompt-read "Name")
(prompt-read "Coloring")
(or (parse-integer (prompt-read "Weight") :junk-allowed t) 0)
(or (parse-integer (prompt-read "Experience") :junk-allowed t) 0)
(or (parse-integer (prompt-read "Length") :junk-allowed t) 0))))
这按原样工作,但我需要第一个整数,"Weight" 是一个浮点数。 parse-float 不起作用,我找不到正确的方法来做到这一点。
(let ((weight (progn
(format t "Weight: ")
(read t))))
(if (floatp weight) weight 0))
有两种方法可以做到这一点。一种是以某种形式使用 read
,另一种是使用浮点解析库。
使用read
委婉地说,使用 read
充满了危险。特别是,除非您小心,否则您很容易受到代码注入攻击。 切勿在您不完全信任输入的代码中使用 read
,除非您至少对其采取了一些安全预防措施。
就是说,这里有一个函数尝试以最低限度安全的方式使用 read
来读取带提示的浮点数。
(defun prompt-for-float (prompt &optional (default 0.0))
;; Use READ to read a float, in a way which should be at least
;; minimally safe.
(with-standard-io-syntax
(let ((*read-eval* nil))
(format *query-io* "~A: " prompt)
(finish-output *query-io*)
(let ((result (read *query-io*)))
(typecase result
(float result)
(real (coerce result 'float))
(t default))))))
这至少 尝试 通过标准化语法和关闭读取时评估来提高安全性,代码注入攻击就是这样发生的。
然而,这可能仍然不是完全安全的。除了可能不安全之外,在允许在系统上执行不受控制的代码的意义上,使用 read
没有严格约束的可读表也不是没有副作用的(例如,它可以实习符号) ,并且可以允许各种可能的拒绝服务攻击,例如通过导致大量内存分配。要处理这些问题,您要么需要做大量工作,将可读表减少到安全的范围,要么使用只读取您关心的类型的库。
使用浮点解析库
有一个名为 parse-float which solves this problem for you. This library is available via Quicklisp 的图书馆。假设你安装了 Quicklisp(你应该安装:如果没有,那么你的第一个问题是安排它是真的),那么使用它就像说 (ql:quickload "parse-float")
一样简单,然后解析浮点数,对于实例:
> (parse-float:parse-float "12.2")
12.2
4
我有一个函数,我同时使用解析整数和提示阅读。但是,我需要这些整数之一是浮点数。当我将 parse-integer 更改为 parse-float 时,它不再有效。 这是函数:
(defun prompt-for-cat ()
(add-record
(make-cat
(prompt-read "Name")
(prompt-read "Coloring")
(or (parse-integer (prompt-read "Weight") :junk-allowed t) 0)
(or (parse-integer (prompt-read "Experience") :junk-allowed t) 0)
(or (parse-integer (prompt-read "Length") :junk-allowed t) 0))))
这按原样工作,但我需要第一个整数,"Weight" 是一个浮点数。 parse-float 不起作用,我找不到正确的方法来做到这一点。
(let ((weight (progn
(format t "Weight: ")
(read t))))
(if (floatp weight) weight 0))
有两种方法可以做到这一点。一种是以某种形式使用 read
,另一种是使用浮点解析库。
使用read
委婉地说,使用 read
充满了危险。特别是,除非您小心,否则您很容易受到代码注入攻击。 切勿在您不完全信任输入的代码中使用 read
,除非您至少对其采取了一些安全预防措施。
就是说,这里有一个函数尝试以最低限度安全的方式使用 read
来读取带提示的浮点数。
(defun prompt-for-float (prompt &optional (default 0.0))
;; Use READ to read a float, in a way which should be at least
;; minimally safe.
(with-standard-io-syntax
(let ((*read-eval* nil))
(format *query-io* "~A: " prompt)
(finish-output *query-io*)
(let ((result (read *query-io*)))
(typecase result
(float result)
(real (coerce result 'float))
(t default))))))
这至少 尝试 通过标准化语法和关闭读取时评估来提高安全性,代码注入攻击就是这样发生的。
然而,这可能仍然不是完全安全的。除了可能不安全之外,在允许在系统上执行不受控制的代码的意义上,使用 read
没有严格约束的可读表也不是没有副作用的(例如,它可以实习符号) ,并且可以允许各种可能的拒绝服务攻击,例如通过导致大量内存分配。要处理这些问题,您要么需要做大量工作,将可读表减少到安全的范围,要么使用只读取您关心的类型的库。
使用浮点解析库
有一个名为 parse-float which solves this problem for you. This library is available via Quicklisp 的图书馆。假设你安装了 Quicklisp(你应该安装:如果没有,那么你的第一个问题是安排它是真的),那么使用它就像说 (ql:quickload "parse-float")
一样简单,然后解析浮点数,对于实例:
> (parse-float:parse-float "12.2")
12.2
4