Как поменять эту функцию, у «машины» появились проблемы - PullRequest
1 голос
/ 02 февраля 2020

Я хочу написать функцию, которая преобразует из «нормальной» записи, например: «1 + 4 * 2-8», в эту предварительную запись: «+ 1- * 428».

Я надеюсь, вы поняли это здесь. Важно: оно должно быть в строках.

Что я получаю до сих пор:

(define (converter lst )
     (let ((operand1 (car lst))
           (operator (car (cdr lst)))
           (operand2 (caddr lst)))
       (list operator
             (converter operand1)
             (converter operand2)))
  )
(infixLst->prefixLst '(1 + 2 * 3))

У меня здесь две проблемы.

1) Это для списков, мне нужно, чтобы оно работало для строк типа "1 + 3" и не '(1 + 3)

2) Это не работать до сих пор (даже не для списков), потому что это дает мне некоторые ошибки в отношении "автомобиля", например: машина: ожидает пару, учитывая 1

Так, начиная с списка - > Строковое изменение: (Я знаю, что (список здесь неуместен. Как и другие методы списка, но у меня пока не было лучшей идеи.

(define (infix->prefix str)
  (let ((operand1 (car str))
           (operator (cadr str)) 
           (operand2 (caddr str)))
       (list operator
             (infix->prefix operand1)
             (infix->prefix operand2)))
  )

(infix->prefix "1 + 2")

1 Ответ

1 голос
/ 21 февраля 2020

Нормальная нотация 1+4*2-8 называется инфиксной нотацией.

  • Если вам просто нужно использовать эту нотацию, Racket имеет готовый модуль: (require infix), вот ссылка на документацию .

  • Если вы хотите попрактиковаться в написании собственного инфиксного парсера, алгоритм 1011 * shunting-yard может это сделать. Он использует стек для отслеживания операторов в математическом выражении.

Если вы хотите проанализировать математику из строки, вам нужно сначала разбить строку на список токенов ( номера и операторы). Начните с процедуры math->tokens, которая просто возвращает список токенов, не заботясь об их значении. Есть много способов написать это. Вот один из них:

(define (math->tokens s)
  (let collect-tokens ((i 0) (tokens '()))
    (if (= i (string-length s))
        (reverse tokens)
        (let ((char (string-ref s i)))
          (if (not (char-numeric? char))
              (let ((operator (string->symbol (string char))))
                (collect-tokens (+ i 1) (cons operator tokens)))
              (let collect-number ((j (+ i 1)))
                (if (and (< j (string-length s))
                         (char-numeric? (string-ref s j)))
                    (collect-number (+ j 1))
                    (let ((number (string->number (substring s i j))))
                      (collect-tokens j (cons number tokens))))))))))

Например, (math->tokens "+1-*428") возвращает список токенов (+ 1 - * 428). Теперь вы можете применить алгоритм маневрового двора к этому списку.

...