首页 > 解决方案 > 将多项式格式化为范式>(如何让最终结果变成lisp中的字符串?(包括所有函数))

问题描述

我目前正在写一个关于输入 P 的函数是正常形式的 PExpr 。以以下“常识”格式输出表示 P 的字符串

这是我现在得到的:</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中的方法

标签: stringloopsprintinglispcommon-lisp

解决方案


princ, print, ecc等函数。执行两个不同的任务:

  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(通过阅读 call 之后的两行可以清楚地看出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))))

另一种方法是,不是将结果打印到某个流,而是通过使用formatwith first parameterNIL而不是 print 将其转换为字符串(例如(format () "~a" expression)),然后concatenate在组合不同的字符串时将所有这些字符串转换为一个部分(再次使用formatconcatenate)。这需要对您的程序进行更多更改。


推荐阅读