将多项式格式设置为标准格式>(如何使最终结果变成Lisp中的字符串?(包括所有函数))

时间:2019-02-25 00:30:23

标签: string loops printing lisp common-lisp

我目前正在写有关输入P的函数,它是标准形式的PExpr。以以下“常识”格式输出表示P的字符串

这是我现在得到的:

(defun writepoly (a b start)
  (cond
    ((and (minusp a) start) 
      (princ "-"))
    ((not start)
      (princ (if (plusp a) " + " " - "))))

  (cond
    ((not (equal (abs a) 1))
    (princ (abs a))))

  (cond
    ((equal (abs b) 1)
      (princ "x"))
    ((> (abs b) 1)
      (princ "x")
      (princ "^")
      (princ b))))


(defun print-pexpr (P)
(loop for (a . b) in P
  for start = t then nil

    do (write-to-string (writepoly a b start))

我确实得到了正确的结果,例如

(print-pexpr '((-1 . 10) (-23 . 0)))

-x^10 - 23
NIL

但是当我做测试用例时

(defun test-case (ID Test Result)
    (if (equal Test Result)
        (format nil "Test ~S OK" ID)
        (format nil "FAIL: Test ~S expected ~S got ~S" ID Result Test)
    )
   )

(test-case 6.4
    (print-pexpr '((-1 . 10) (-23 . 0)))
    "-x^10 - 23"
)

输出为:

"FAIL: Test 6.4 expected \"-x^10 - 23\" got NIL

如何更改我的函数,以便可以获取字符串...?我不应该使用princ命令吗?希望有人能回答我的问题...谢谢

PS:我在Lisp Formatting Polynomial中复制了该方法

2 个答案:

答案 0 :(得分:3)

诸如princprint等功能。执行两个不同的任务:

  1. 它们在标准输出(通常是终端)上打印其参数,但是如果特殊变量*standard-output*是反弹,则可以有所不同;
  2. 它们返回打印为语言值的参数。

例如:

CL-USER> (+ (print 1) (print 2))

1   ; <- printed by (print 1), which returns also 1
2   ; <- printed by (print 2), which returns also 2
3   ; <- the sum of 1+2, printed by the REPL, not by the program!

因此,如果尝试使用实例(writepoly -1 10 t),则会得到:

CL-USER> (writepoly -1 10 t)
-x^10   ; <- printed by writepoly
10      ; <- returned by writepoly

换句话说,您的程序将输出某些内容并返回其他内容,例如最后一个函数,在该函数中您将打印多项式但返回NIL(通过在调用print-pexpr之后读取两行即可清楚看到),是导致错误的原因。

如何修改程序以返回打印出的字符串?基本上有两种可能性。第一种是Rainer Joswing的答案所建议的,它使用两件事:函数with-output-to-string,该函数创建一个新的输出流,其中“打印”的所有内容作为单个字符串最后返回,即第二个方法是指定该流*standard-output*的名称,实际上,它“指示”所有打印命令(没有显式的流参数)在该字符串上进行打印(否则,应通过显式添加该流来更改所有打印调用)在上面打印)。

因此您可以使用以下命令更改最后一个功能:

(defun print-pexpr (P)
  (with-output-to-string (*standard-output*)
    (loop for (a . b) in P
      for start = t then nil
      do (writepoly a b start))))

另一种方法是,不将结果打印到某个流中,而是通过将第一个参数为NIL的{​​{3}}而不是print来将其转换为字符串(例如{{ 1}}),然后在组合不同部分时将所有这些字符串format合并为一个(再次使用(format () "~a" expression)format)。这需要对程序进行更多更改。

答案 1 :(得分:2)

CL-USER 6 > (with-output-to-string (*standard-output*)
              (princ 'foobar))
"FOOBAR"