所以我试图将标准输入的2D数组解析为Common Lisp(SBCL)中的数据结构。 我希望输入的格式为
1 2 3
4 5 6
7 8 9
如果它有3行。
到目前为止,我已经得到了这个:
(defun read-2d-array (rows &rest args)
(values (read-from-string
(concatenate 'string "#2A("
(dotimes (i rows)
(concatenate 'string "("
(apply #'read-line args)
")"))
")"))))
这个问题是,虽然外部连接似乎有效,但我在尝试连接循环迭代并获取表单时遇到了麻烦:
#2A((1 2 3)(4 5 6)(7 8 9))
任何帮助将不胜感激。谢谢!
答案 0 :(得分:2)
最好用PARSE-INTEGER
解析不变数字并将它们自己放入数组中,而不是制作一个字符串并从中读取一个文字数组。
(defun read-2d-array (rows &rest args)
;; I'm assuming that the array is a square matrix. Otherwise you'd
;; need the number of columns too.
(let ((arr (make-array (list rows rows)
:element-type 'integer
:initial-element 0)))
(dotimes (i rows)
(let ((line (apply #'read-line args))
(start 0))
(dotimes (j rows)
(multiple-value-bind (number end)
(parse-integer line :start start
:junk-allowed t)
(setf start end
(aref arr i j) number)))))
arr))
(with-input-from-string (str "1 2 3
4 50 6
7 8 9")
(read-2d-array 3 str))
;=> #2A((1 2 3) (4 50 6) (7 8 9))
修改强>
为了安全起见,这是一个通过查看第一行输入来计算列数的版本。
(defun read-2d-array (rows &rest args)
(let* ((first-line (apply #'read-line args))
(cols (1+ (count #\space first-line)))
(arr (make-array (list rows cols)
:element-type 'integer
:initial-element 0)))
(loop for i below rows
for line = first-line then (apply #'read-line args)
for start = 0
do (dotimes (j cols)
(multiple-value-bind (number end)
(parse-integer line :start start
:junk-allowed t)
(setf start end
(aref arr i j) number))))
arr))
或者使用CL-PPCRE从行中提取整数:
(defun read-2d-array (rows &rest args)
(labels ((numbers (string)
(mapcar #'parse-integer
(cl-ppcre:all-matches-as-strings "\\d+" string))))
(let* ((first-line (numbers (apply #'read-line args)))
(cols (length first-line))
(arr (make-array (list rows cols)
:element-type 'integer
:initial-element 0)))
(loop for i below rows
for line = first-line then (numbers (apply #'read-line args))
do (dotimes (j cols)
(setf (aref arr i j) (pop line))))
arr)))
答案 1 :(得分:1)
所有这些连接并不是最好的方法。
Common Lisp可以使用字符串进行读取和打印。
只需打印到由WITH-OUTPUT-TO-STRING
创建的字符串输出流:
(defun convert-text-to-array-string (stream)
(with-output-to-string (out-stream)
(write-string "#2A(" out-stream)
(loop for line = (read-line stream nil nil)
while line
do
(write-string "(" out-stream)
(write-string line out-stream)
(write-string ")" out-stream))
(write-string ")" out-stream)))
从WITH-OUTPUT-TO-STRING
返回时,表单返回完成输出到输出结果的字符串。
答案 2 :(得分:0)
您的dotimes
表单会返回nil
。
您需要连接您阅读的行:
(defun read-2d-array (rows &rest args)
(values (read-from-string
(concatenate 'string "#2A("
(apply #'concatenate 'string
(loop :repeat rows
:collect (apply #'read-line args)))
")"))))