以下是家庭作业/考试准备的一部分:我正在尝试编写一些简明的代码来从文本文件中读取行。空行应包括在内。以下是我想出的代码:
(defun read-file (filename)
(do* ((streamin (open filename)) ;open the file
content
(line (read-line streamin nil 'eof) ;read from file in loop
(read-line streamin nil 'eof)))
((equal line 'eof) (close streamin) ;close the stream if eof is reached
(reverse content))
(setq content (cons line content)))) ;add a read line to the returned symbol
Run Code Online (Sandbox Code Playgroud)
在Sublime Texteditor(或记事本)中创建的文本文件的预期输出,如下所示:
this is
a
test
file
Run Code Online (Sandbox Code Playgroud)
这是:
("this is" "" "a" "" "test" "file")
Run Code Online (Sandbox Code Playgroud)
但是,我收到以下信息:
("this is^M" "^M" "a^M" "^M" "test^M" "file^M")
Run Code Online (Sandbox Code Playgroud)
“ ^ M”来自哪里?它们是通过记事本插入的吗?还是因为我的代码而在那里?他们到底是什么?我猜他们表明一个新的线。
如果将它们插入到高处,我必须用什么替代方法来产生预期的输出?记事本也一样。练习的下一步是使用过滤器功能从输出中删除空行,我想这可以通过将等于空行的行进行比较来实现。但是,当插入这些^ M时,这是不可能的,因为例如
(equal "^M" (read-line test_file_with_empty_lines))
Run Code Online (Sandbox Code Playgroud)
返回NIL。而
(equal "^M" "^M")
Run Code Online (Sandbox Code Playgroud)
显然返回T ...
您正在使用DOS的行尾约定的系统读取文件,该系统需要Unix的行尾约定。
DOS以回车/换行对结束行。回车的ASCII码是#x0d / 13,它是控件M,换行是#x0a / 10,它是控件J。
这些字符的CL名称(我应该在上面使用过)分别是#\Return&#\Newline。
因此,具有DOS行尾约定的文件将包含序列(如(十六进制))0d0a以标记行尾。期待Unix的行尾约定(只是一个0a)的读者可能会将其读为最后一个字符为的行#\Return。
解决此问题的方法是三件事之一:
open以了解如何教它使用适当的外部格式来读取DOS约定文件。看来您正在使用CLISP。如果是这样,并且如果我正确阅读了其手册,则可能要使用(open ... :external-format ':dos)。
另外要注意的是,尽管您的代码可以工作,但它不是非常惯用的CL,也不安全(读取文件时出现错误怎么办?):您可能希望查看规范的21.2节。(我故意不给您答案,因为您很诚实并说这是家庭作业,谢谢!)。
| 归档时间: |
|
| 查看次数: |
61 次 |
| 最近记录: |