Lisp 如何从流中读取以空格分隔的单词?

Lisp 如何从流中读取以空格分隔的单词?,lisp,common-lisp,Lisp,Common Lisp,在CommonLisp中,有没有一种简单的方法可以从输入流中读取单个以空格分隔的单词?本质上,我在寻找与C的scanf(“%s”,somevar)等价的东西 我确实得出了以下结论: (defun read-word-from-stream (in) (peek-char t in) ; skip initial whitespace (do ((str (make-array 16 :fill-pointer 0 :element-type 'standard-char :adjusta

在CommonLisp中,有没有一种简单的方法可以从输入流中读取单个以空格分隔的单词?本质上,我在寻找与C的scanf(“%s”,somevar)等价的东西

我确实得出了以下结论:

(defun read-word-from-stream (in)
  (peek-char t in) ; skip initial whitespace
  (do ((str (make-array 16 :fill-pointer 0 :element-type 'standard-char :adjustable t) 
            (progn (vector-push-extend (read-char in) str) str)))
      ((let ((c (peek-char nil in))) 
            (or (char= c #\Newline) (char= c #\Space))) str)))
…虽然功能上满足了我有限的需求,但对于这么简单的操作来说,感觉有点笨拙。理想情况下,我会有一个方法为我做这件事,但是使用任何可用的公共Lisp库(最好是使用flexi streams的库)做这件事的最干净和最短的正确方法是什么?

使用peek char检测空白 虽然我在文章中写道,没有标准的方法来实现这一点,部分原因是没有通用的空白概念。(您的版本包括空格和换行符,但是关于制表符、垂直制表符、回车符等呢?)也就是说,您使用peek char提醒我,peek char采用可选的peek类型参数,指示是否应跳过空白。如果您同时使用这两种类型的窥视,那么当它们不一致时,您必须使用空格字符。这意味着您可以使用如下函数读取空白字符(其中空白字符的确切含义由实现决定):

(defun read-string (&optional (stream *standard-input*))
  (loop
     for c = (peek-char nil stream nil nil)              ; include whitespace
     while (and c (eql c (peek-char t stream nil nil)))  ; skip whitespace
     collect (read-char stream) into letters
     finally (return (coerce letters 'string))))

我使用了(强制字母字符串)在这里获取字符串,但您也可以使用和输出到字符串:

(defun read-string (&optional (stream *standard-input*))
  (with-output-to-string (out)
    (loop
       for c = (peek-char nil stream nil nil)
       while (and c (eql c (peek-char t stream nil nil)))
       do (write-char (read-char stream) out))))

将术语表条目用于空格 空白的术语表条目表示:

n1。图形中的一个或多个字符 字符#\空格或其他非图形字符,如#\换行符 这只会移动打印位置。2。A.Na的语法类型 作为标记分隔符的字符。有关详细信息,请参见第2.1.4.7节 (空白字符)。B形容词。(指角色)具有 空格[2a]语法类型[2]。CN空格[2b]字符

根据第一个定义,很容易定义一个粗略的近似值(这不会检查打印位置;我不确定是否有一种便携式方法来检查它):

这样做很容易:

(defun read-until (test &optional (stream *standard-input*))
  (with-output-to-string (out)
    (loop for c = (peek-char nil stream nil nil)
       while (and c (not (funcall test c)))
       do (write-char (read-char stream) out))))


您始终可以使用
循环执行某些操作。请看一个没有标准函数的例子,可能至少部分是因为对什么算空白没有标准限制。例如,您只计算了换行符和空格,但通常也应包括制表符和回车符。有垂直标签吗?但实际上,这只是一个阅读字符的问题,直到你找到一个算作终止字符。但是,您可以通过强制收集的字符列表来创建字符串,或者将输出与字符串一起使用,这两种方法都可以简化代码。
CL-USER> (read-string)
some more input
"some"
(defun whitespace-char-p (x)
  (or (char= #\space x)
      (not (graphic-char-p x))))
(defun read-until (test &optional (stream *standard-input*))
  (with-output-to-string (out)
    (loop for c = (peek-char nil stream nil nil)
       while (and c (not (funcall test c)))
       do (write-char (read-char stream) out))))
CL-USER> (read-until 'whitespace-char-p)
this is some input
"this"