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

时间:2015-10-27 15:17:22

标签: common-lisp

以下是我在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进行简单的清除/重置,即,不能连接更多吗?或者我是否只需要重做正在设置fstr的顶级表达式?

2 个答案:

答案 0 :(得分: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)
""

答案 1 :(得分:6)

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

  

填充指针 n。 (向量)与向量相关的整数   表示没有元素处于活动状态的索引。 (填写   指针是一个非负整数,不大于总数   向量中的元素。并非所有向量都有填充指针。)

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

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

  

with-output-to-string 创建一个字符输出流,执行一系列操作,可以将结果发送到此流,然后   关闭流。

因此,您可以使用(setf fill-pointer)“重置”字符串,并且可以使用 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"

  )