написать функцию сравнения строк - PullRequest
2 голосов
/ 10 июня 2011

Я полностью понимаю использование списка в lisp, но у меня проблема с использованием строки.Я пытаюсь написать свой собственный код функций, таких как string> или string <из общего lisp, чтобы понять, как lisp работает со строкой.Например, abcde больше, чем abbb и возвращает 1. </p>

Я думаю, что я буду использовать функцию char или вы думаете, что я должен использовать subseq?или функция, которая имеет дело с кодом ASCII?

Вот случаи, которые я обнаружил: - Символ 0 каждой строки равен, мы продолжаем, со следующим символом.-характеры 0 отличаются, один меньше другого, мы останавливаемся.

Мне нужна помощь по поводу «перейти к следующему символу».

Большое спасибо !!

Ответы [ 4 ]

2 голосов
/ 10 июня 2011

Это версия Common Lisp. Вы можете просто использовать ELT, потому что

(type-of "a") => (SIMPLE-ARRAY CHARACTER (1))

(defun my-string< (a b &key (start 0))
  (cond
    ((= start (length a) (length b))
     nil)
    ((>= start (min (length a) (length b)))
     (error "Undefined"))
    ((char= (elt a start) (elt b start))
     (my-string< a b :start (1+ start)))
    ((char< (elt a start) (elt b start))
     t)))
1 голос
/ 01 июля 2011

Ваша проблема уже решена, но если вы столкнетесь с другими, может пригодиться следующий метод:

Я установил SBCL из источника и держу источник вокруг. Это позволяет мне запускать M-. на имя функции, как строка < и он перейдет к определению в вашей реализации lisp.

В моем случае я оказался в этом макросе:

;;; LESSP is true if the desired expansion is for STRING<* or STRING<=*.
;;; EQUALP is true if the desired expansion is for STRING<=* or STRING>=*.
(sb!xc:defmacro string<>=*-body (lessp equalp)
  (let ((offset1 (gensym)))
    `(with-two-strings string1 string2 start1 end1 ,offset1 start2 end2
       (let ((index (%sp-string-compare string1 start1 end1
                                        string2 start2 end2)))
         (if index
             (cond ((= (the fixnum index) (the fixnum end1))
                    ,(if lessp
                         `(- (the fixnum index) ,offset1)
                       `nil))
                   ((= (+ (the fixnum index) (- start2 start1))
                       (the fixnum end2))
                    ,(if lessp
                         `nil
                       `(- (the fixnum index) ,offset1)))
                   ((,(if lessp 'char< 'char>)
                     (schar string1 index)
                     (schar string2 (+ (the fixnum index) (- start2 start1))))
                    (- (the fixnum index) ,offset1))
                   (t nil))
             ,(if equalp `(- (the fixnum end1) ,offset1) nil))))))
) ; EVAL-WHEN
1 голос
/ 13 июня 2011

Это реализация функции, которая при наличии двух строк будет возвращать либо -1, 0, либо +1, в зависимости от того, будет ли первое меньше, равно или больше второго.Если одна строка является начальной частью другой, то более короткая строка считается «меньше», чем длиннее.

Алгоритм очень прост ... зацикливается на каждом символе, пока индекс не пройдет одинстрок или, если обнаружен другой символ.

(defun strcmp (a b)
  (do ((i 0 (1+ i))
       (na (length a))
       (nb (length b)))
      ((or (= i na) (= i nb) (char/= (elt a i) (elt b i)))
         (cond
           ((= i na nb) 0)                  ;; Strings are identical
           ((= i na) -1)                    ;; a finished first
           ((= i nb) 1)                     ;; b finished first
           ((char< (elt a i) (elt b i)) -1) ;; Different char a < b
           (t 1)))))                        ;; Only remaining case

(defun test (a b)
  (format t "(strcmp ~s ~s) -> ~s~%"
          a b (strcmp a b)))

(test "abc" "abc")
(test "ab"  "abc")
(test "abc" "ab")
(test "abd" "abc")
(test "abc" "abd")

Вывод

(strcmp "abc" "abc") -> 0
(strcmp "ab" "abc") -> -1
(strcmp "abc" "ab") -> 1
(strcmp "abd" "abc") -> 1
(strcmp "abc" "abd") -> -1
0 голосов
/ 10 июня 2011

В Схеме нет прямого понятия итерации («следующая») со строками. Это относится только к спискам. Так что вместо этого вы должны перебирать индексы:

(define (string<? lhs rhs)
  (let* ((lhslen (string-length lhs))
         (rhslen (string-length rhs))
         (minlen (min lhslen rhslen)))
    (let loop ((i 0))
      (if (= i minlen) (< lhslen rhslen)
          (let ((lhschar (string-ref lhs i))
                (rhschar (string-ref rhs i)))
            (cond ((char<? lhschar rhschar) #t)
                  ((char<? rhschar lhschar) #f)
                  (else (loop (+ i 1)))))))))
...