我目前正在写有关输入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中复制了该方法
答案 0 :(得分:3)
诸如princ
,print
等功能。执行两个不同的任务:
*standard-output*
是反弹,则可以有所不同; 例如:
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"