2015-10-27 3 views
3

Вот пример, который я видел в Hyperspec:Как очистить строку с помощью указателя заполнения?

(setq fstr (make-array '(0) :element-type 'base-char 
          :fill-pointer 0 :adjustable t)) 
(with-output-to-string (s fstr) 
    (format s "here's some output")) 

Итак fstr держит here's some output Q: Как вы могли бы сделать простой прозрачный/сброс на fstr в случае, если вы хотите, чтобы начать все сначала и положить что-то новое в нем , то есть не конкатенировать на нем больше? Или мне просто нужно переделать верхнее выражение, где устанавливается fstr?

+1

просто уточнить, нет никаких * ввод * поток здесь. Существует массив (который также является строкой из-за своего типа элемента), который имеет указатель заполнения. ** with-output-to-string ** создает поток символов * output *, который отправляет свой вывод в строку. –

ответ

8

Установите указатель заливки:

CL-USER 3 > (setq fstr (make-array '(0) :element-type 'base-char 
            :fill-pointer 0 :adjustable t)) 
"" 

CL-USER 4 > (with-output-to-string (s fstr) 
       (format s "here's some output")) 
NIL 

CL-USER 5 > fstr 
"here's some output" 

CL-USER 6 > (setf (fill-pointer fstr) 0) 
0 

CL-USER 7 > fstr 
"" 

CL-USER 8 > (with-output-to-string (s fstr) 
       (format s "here's some more output")) 
NIL 

CL-USER 9 > fstr 
"here's some more output" 

Вы также можете позвонить adjust-array на самом деле изменить размер массива.

CL-USER 16 > (setf (fill-pointer fstr) 0) 
0 

CL-USER 17 > (adjust-array fstr 0) 
"" 
6

Здесь взаимодействуют две ортогональные концепции. Во-первых, что векторы (строки, одномерные массивы и т.д.) могут иметь fill pointer:

указатель заполнения п. (вектора) целое число, ассоциированное с вектором, которое представляет собой индекс, над которым нет активных элементов. (Указатель заполнения не является неотрицательным целым числом не больше, чем общее число элементов в векторе. Не все векторы имеют заполнять указатели.)

Когда вы смотрите на строку, указатель заполнения по существу длина строки, но позволяет основному массиву фактически содержать больше данных (, который равен, все еще доступен; это может быть важно в зависимости от приложения).

Затем существует множество способов управления содержимым вектора с помощью указателя заполнения. Для строк есть полезный, предоставляемый with-output-to-string, который создает пар символов, который отправляет вывод символов в строку.

с-вывода в строку создает выходной поток символов, выполняет ряд операций, которые могут посылать результаты к этому потоку, и затем закрывает поток.

Таким образом, вы можете «сбросить» вашу строку с (setf fill-pointer), и вы можете добавить контент с с-вывода в строку, среди прочего:

(let ((str (make-array '(0) 
         :element-type 'base-char 
         :adjustable t 
         :fill-pointer 0))) 

    ;; Temporarily create a character output stream that directs its 
    ;; output to the underlying string that we created, and write "hello 
    ;; world!" to it. 
    (with-output-to-string (s str) 
    (format s "hello world!")) 

    ;; prints "hello world", sets the FILL-POINTER back to 0, and then 
    ;; prints "". 
    (print str) 
    (setf (fill-pointer str) 0) 
    (print str) 

    ;; But note that the underlying array 
    ;; and the content that you put into 
    ;; it are still available. While LENGTH 
    ;; returns 0, ARRAY-TOTAL-SIZE reports 
    ;; 12, and you can still just AREF to 
    ;; get the old content. 
    (print (length str))     ;=> 0 
    (print (array-total-size str))  ;=> 12 
    (print (aref str 6))     ;=> #\w 

    ;; update content using vector push extend, and print "abcde". 
    (vector-push-extend #\a str) 
    (vector-push-extend #\b str) 
    (vector-push-extend #\c str) 
    (vector-push-extend #\d str) 
    (vector-push-extend #\e str) 
    (print str)       ;=> "abcde" 

    ;; Or set the fill pointer manually, possibly setting content in the 
    ;; array before or after. Note that you can (SETF AREF) elements in 
    ;; the vector that aren't in the active portion. First, we confirm 
    ;; that the fill pointer is at 5, then set an element at 8 (past the 
    ;; fill pointer), then set the fill pointer to 10, and set an 
    ;; element at 6 (before the fill pointer). All these changes affect 
    ;; the vector contents. 
    (print (fill-pointer str))   ;=> 5 
    (setf (aref str 8) #\X) 
    (setf (fill-pointer str) 10) 
    (setf (aref str 6) #\Y) 
    (print str)       ;=> "abcde YoXl" 

) 
Смежные вопросы