当达到eof时,读取线如何在Lisp中工作?

Jon*_*h P 2 lisp file-io common-lisp

上下文:我有一个文本文件,fr.txt其中包含3列文本:

65  A   #\A
97  a   #\a
192     À   #\latin_capital_letter_a_with_grave
224     à   #\latin_small_letter_a_with_grave
etc...
Run Code Online (Sandbox Code Playgroud)

我想创建一个函数来读取第一个(也最终是第三个)列并将其写入另一个名为的文本文件中alphabet_code.txt.

到目前为止,我有这个功能:

(defun alphabets()
   (setq source (open "fr.txt" :direction :input :if-does-not-exist :error))
   (setq code (open "alphabet_code.txt" :direction :output :if-does-not-exist :create :if-exists :supersede))
   (loop
      (setq ligne (read-line source nil nil))
      (cond
         ((equal ligne nil) (return))
         (t (print (read-from-string ligne) code))
      )
   )
   (close code)
   (close source)
)
Run Code Online (Sandbox Code Playgroud)

我的问题:

  1. 我真的不明白读取线功能的参数如何.我已阅读此文档,但对我来说仍然很模糊.如果有人会有非常简单的例子,那会有所帮助.

  2. 使用当前代码,我收到此错误:*** - read: input stream #<input string-input-stream> has reached its end 即使我将nil nilin 更改(read-line source nil nil)为其他值.

谢谢你的时间!

sds*_*sds 7

你的问题

read-line 可选参数

read-line 接受3个可选参数:

  1. eof-error-p:在EOF上做什么(默认:错误)
  2. eof-value:当您看到EOF时,返回什么而不是错误
  3. recursive-p:你从你的print-object方法中调用它(暂时忘掉这个)

例如,当streamEOF时,

  • (read-line stream)将发出end-of-file错误信号
  • (read-line stream nil) 将返回 nil
  • (read-line stream nil 42)会回来的42.

请注意,它们(read-line stream nil)是相同的,(read-line stream nil nil)但人们通常仍会显式传递第二个可选参数. eof-valuenil是罚款read-line,因为nil不是一个字符串,并read-line只返回一个字符串.

还要注意,在read第二个可选参数的情况下,传统上是stream自身:(read stream nil stream).这很方便.

错误

您收到的错误read-from-string不是read-line,因为显然您的文件中有一个空行.

我知道,因为错误提到string-input-stream,而不是file-stream.

你的代码

您的代码在功能上是正确的,但在风格上非常错误.

  1. 你应该with-open-file尽可能使用.
  2. 你不应该print在代码中使用它,这是一个奇怪的遗留功能,主要用于交互式使用.
  3. 您不能使用setq- 使用let或其他等效形式创建局部变量(在这种情况下,您永远不需要let!:-)

以下是我将如何重写您的函数:

(defun alphabets (input-file output-file)
  (with-open-stream (source input-file)
    (with-open-stream (code output-file :direction :output :if-exists :supersede)
      (loop for line = (read-line source nil nil)
          as num = (parse-integer line :junk-allowed t)
        while line do
          (when num
            (write num :stream code)
            (write-char #\Newline code))))))
(alphabets "fr.txt" "alphabet_code.txt")
Run Code Online (Sandbox Code Playgroud)

查看文档:

  1. loop:for/as,while,do
  2. write, write-char
  3. parse-integer

或者,而不是(when num ...)我可以使用相应的loop条件.

而且,而不是write+ write-char我可以写(format code "~D~%" num).

请注意,我没有传递与with-open-stream默认值相同的参数.默认设置是一成不变的,您必须编写的代码越少,用户必须阅读的内容越少,出错的可能性就越小.