如何用填充指针清除字符串?

How to clear string with fill pointer?

这是我在 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 问:如果您想重新开始并放入一些新东西,您如何在 fstr 上做一个简单的 clear/reset它,也就是说,不连接更多吗?还是我只需要重做正在设置 fstr 的顶部表达式?

设置填充指针:

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)
""

这里有两个正交的概念在相互作用。第一个是向量(字符串、一维数组等)可以有一个 fill pointer:

fill pointer n. (of a vector) an integer associated with a vector that represents the index above which no elements are active. (A fill pointer is a non-negative integer no larger than the total number of elements in the vector. Not all vectors have fill pointers.)

当您查看字符串时,填充指针本质上是字符串的长度,但允许底层数组实际包含更多数据(其中 仍然可以访问;这可能很重要,具体取决于应用程序)。

然后,有很多方法可以使用填充指针来操作向量的内容。对于 stringswith-output-to-string 提供了一个有用的方法,它创建一个字符流,将字符输出发送到字符串。

with-output-to-string creates a character output stream, performs a series of operations that may send results to this stream, and then closes the stream.

因此,您可以使用 (setf fill-pointer) "reset" 您的字符串,您可以使用 with-output-to-string 添加内容,以及其他方式:

(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"

  )