Формат полинома к нормальной форме> (Как сделать так, чтобы конечный результат стал строкой в ​​lisp? (Все функции включены)) - PullRequest
0 голосов
/ 25 февраля 2019

В настоящее время я пишу функцию о входе 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

Ответы [ 2 ]

0 голосов
/ 25 февраля 2019

Функции типа 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 (как ясно, читая две строки после вызова print-pexpr), и этопричина ошибки.

Как можно изменить программу, чтобы она возвращала напечатанную строку?В основном есть две возможности.Первое - это то, что было предложено в ответе Райнера Джосвинга с использованием двух вещей: функции 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))))

Альтернативный способ состоит в том, чтобы вместо вывода результата в какой-либо поток преобразовать егов строке, используя format с первым параметром NIL вместо print (как, например, (format () "~a" expression)), а затем concatenate все эти строки водин при объединении различных частей (используя снова format или concatenate).Это требует больше изменений в вашей программе.

0 голосов
/ 25 февраля 2019
CL-USER 6 > (with-output-to-string (*standard-output*)
              (princ 'foobar))
"FOOBAR"
...