将多项式格式化为正常形式>(如何让最终结果在 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格式多项式中复制了该方法

princprint、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(通过读取调用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))))

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

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

最新更新