从Common Lisp中的标准输入中获取一组数字

时间:2016-06-22 03:24:11

标签: arrays common-lisp

我意识到这是一个非常基本的问题,但我刚刚开始使用CL,我想知道如何从标准输入中获取输入,如:

1 2 3 4 5

并将其存储在数组中。

我试过了:

(setq array (read-line))

然后检查类型给出了缺点。

我也尝试过像这样构建一个数组:

(setf array (make-array n :element-type 'number))

其中n是我输入的值的数量,但在此之后我就丢失了。我是否需要使用循环或有没有办法在没有循环的情况下执行此操作?

感谢。

4 个答案:

答案 0 :(得分:3)

您需要执行以下步骤:

  • 阅读
  • 分成数字
  • 解析数字

看起来像这样:

(defun read-array (stream)
  (let* ((line (read-line stream))
         (items (split-sequence #\Space line))
         (numbers (map 'vector #'parse-integer items)))
    numbers))

Split-sequence来自同名的图书馆。)

这只是基本的实现,您可能希望清理输入,并在任何空格上进行拆分。

我建议不要以任何方式使用read来阅读用户输入,因为读者可以做更多事情而且你需要非常小心用户输入。

答案 1 :(得分:1)

预定义函数read-line返回一个字符串(请参阅manual)。

从该字符串中获取数组(假设数字在一行上)的一种简单方法是通过添加必要的语法来操作返回的字符串,以便通过函数{{1将其作为文字数组读取}}。这是一个简单的功能,改编自Paul Graham撰写的优秀On Lisp书中的列表:

read-from-string

当然,如果数字在多行上,则需要进行某种迭代。

答案 2 :(得分:1)

可以通过使用流来读取字符串。然后,只要有数字,就会调用read,将其收集到列表中并将列表转换为矢量。

CL-USER 36 > (coerce (with-input-from-string (stream "1 2 3 4 5")
                       (loop for n = (read stream nil nil)
                             while (numberp n)
                             collect n))
                     'vector)
#(1 2 3 4 5)

或:one创建一个可以增长的向量 - 在Common Lisp中,向量应该是可调整的(当大小未知时)并且有一个填充指针。然后从字符串流中读取并将数字推送到矢量上。

CL-USER 40 > (let ((vector (make-array 0 :adjustable t :fill-pointer t)))
               (with-input-from-string (stream "1 2 3 4 5")
                 (loop for n = (read stream nil nil)
                       while (numberp n)
                       do (vector-push-extend n vector)))
               vector)
#(1 2 3 4 5)

答案 3 :(得分:1)

您正在描述的Common Lisp中的文字数组的语法是#(1 2 3 4 5)。您只需键入{而不是1 2 3 4 5,然后读取

CL-USER> (read)  
; type "#(1 2 3 4 5)" (no quotes)
#(1 2 3 4 5)     ; return value

CL-USER> (let ((array (read)))
           (type-of array))
; type "#(1 2 3)" (no quotes)
(SIMPLE-VECTOR 3)