右对齐文本 Lisp

Right Justified Text Lisp

我正在尝试让我的 lisp 代码输出右对齐的内容。我查阅了格式 (doc link) 的文档并尝试了以下

(format t "~10:<*~>")

问题是运行这段代码给了我这个:

     *         *
     *

而不是给我这样的东西:

   **
    *

下面是整个函数,但我不认为它是导致任何问题的函数:

(defun triangle-print-neg (rows numStar)
   (cond
      ((= rows 0) (return-from triangle-print-neg nil)) ;If rows = 0, force exit
      ((< numStar (abs rows)) (progn
           (format t "~10:<*~>")
           (triangle-print-neg rows (+ numStar 1)) ;Call function again but with numStar + 1
      )); numStar < abs(rows) print("*")
      (t (progn
             (format t "~%")
             (triangle-print-neg (+ rows 1) 0)
       )) ; Else call triangle print neg with row+1, 0
   )
)

谢谢

鉴于您的潜在问题,即打印三角形,大概是学习 Lisp 练习的一部分,并且您(我猜)对 Common Lisp 不是很熟悉,我建议 not 试图理解 format 字符串语言的细节,这很复杂并且与 Lisp 完全无关,除非它恰好嵌入在 CL 中,而是简单地编写一个函数来做使用简单的打印操作即可实现。

您需要的两个简单的打印操作是:

  • princ 打印没有任何修饰的东西,如换行符或引号;
  • terpri 打印换行符。

鉴于这两个操作,您可以编写一个过程 princ-n-padded,它打印 n 个字符的副本,填充到给定的宽度,然后是换行符。您可以使用使宽度为负的肮脏技巧来指示右侧的填充。

下面是这样一个程序:

(defun print-n-padded (c n width &optional (to *standard-output*))
  "Print a line with N copies of C in width |WIDTH|.
If WIDTH >= 0 then print left justified, if it is < 0 print right justified.
The optional TO argument is the stream to which to print."
  (if (>= width 0)
      (dotimes (i width)
        (princ (if (< i n) c #\Space) to))
     (dotimes (i (- width))
       (princ (if (< i (- (- width) n)) #\Space c) to)))
  (terpri to))

现在

> (dotimes (i 10)
    (print-n-padded #\* (+ i 1) -10))
         *
        **
       ***
      ****
     *****
    ******
   *******
  ********
 *********
**********
nil

如您所见,这是简单的代码,没有繁琐难懂的 format 字符串。在现实生活中,您可能最终想以 non-trivial 的方式开始使用 format,但通常更容易编写执行您想要的代码,其中您想要的东西相对简单,而不是而不是编写充满 line-noise 个字符串的代码。


如果您需要递归执行此操作,那么您也可以这样做:

(defun print-n-padded (c n width &optional (to *standard-output*))
  "Print a line with N copies of C in width |WIDTH|.
If WIDTH >= 0 then print left justified, if it is < 0 print right justified.
The optional TO argument is the stream to which to print."
  (if (>= width 0)
      (princ-ab c #\Space width (- width n) to)
    (princ-ab #\Space c (- width) n to))
  (terpri to))

(defun princ-ab (a b n m to)
  "print (with PRINC) a total of N copies of A or B, printing N-M of A
followed by M of B, to TO.  Do not print a newline"
  (cond  ((> n 0)
          (princ (if (<= n m) b a) to)
          (princ-ab a b (- n 1) m to))
         ((= n 0)
          nil)
         ((< n 0)
          (error "negative-creep"))))
(defun my-triangle (k)
   (format t "~10@a~&" (make-string k :initial-element #\a))
   (unless (zerop k)
     (my-triangle (decf k))))
MY-TRIANGLE

CL-USER> (MY-TRIANGLE 5)
     aaaaa
      aaaa
       aaa
        aa
         a
          
NIL

我使用 ~a 填充 10 和 left-align @ 修饰符:https://lispcookbook.github.io/cl-cookbook/strings.html#justifying-on-the-left-