Lisp 使用read line从.txt读取,并读取其他符号。记事本的人工制品?

Lisp 使用read line从.txt读取,并读取其他符号。记事本的人工制品?,lisp,common-lisp,Lisp,Common Lisp,以下是家庭作业/考试准备的一部分:我正在尝试编写一些clisp代码来读取文本文件中的行。应包括空行。以下是我提出的代码: (defun read-file (filename) (do* ((streamin (open filename)) ;open the file content (line (read-line streamin nil 'eof) ;read from file in loop

以下是家庭作业/考试准备的一部分:我正在尝试编写一些clisp代码来读取文本文件中的行。应包括空行。以下是我提出的代码:

(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
在sublime texteditor(或记事本)中创建的文本文件的预期输出,如下所示:

this is

a

test
file
这是:

("this is" "" "a" "" "test" "file")
然而,我收到以下信息:

("this is^M" "^M" "a^M" "^M" "test^M" "file^M")
“^M”来自哪里?它们是用记事本插入的吗?还是因为我的代码?他们到底是什么?我猜它们表明了一条新的路线

如果它们是由sublime插入的,那么我需要哪些替代方案来创建预期的输出?记事本也是如此。本练习的下一步是使用filter函数从输出中删除空行,我想这是通过比较等于空行的行来实现的。但是,当插入这些^M时,这是不可能的,因为例如

(equal "^M" (read-line test_file_with_empty_lines))
返回零。当

(equal "^M" "^M")

返回T显然…

您正在读取一个带有DOS行结束约定的文件,而系统需要Unix行结束约定

DOS使用回车/换行对结束行。回车的ASCII码是#x0d/13,它是控件M,换行是#x0a/10,它是控件J

这些字符的CL名称(我应该在上面使用)分别是
#\Return
#\Newline

因此,具有DOS行结束约定的文件将包含类似(十六进制)
0d0a
的序列,以标记行结束。读取它时,如果希望使用Unix行结束约定(只有一个
0a
),则会将其作为最后一个字符为
\Return
的行来读取

处理这一问题的方法有三种:

  • 假设您在Unixy机器上运行,请使用使用Unixy行结束约定的编辑器(OSX上的升华文本仍然如此)
  • 如果您在Windows计算机上,那么Lisp可能默认为假定平台的本机行结束约定,并为您进行翻译
  • 如果上述一项或两项都不起作用,或者文件已在计算机之间移动,则需要阅读
    open
    的实现文档,了解如何教它使用适当的外部格式来读取DOS约定文件

似乎您正在使用CLISP。如果是这样,并且我正确阅读了它的手册,那么您可能希望使用类似于
(open…:external format':dos)



另外要注意的是,虽然您的代码可以工作,但它不是非常惯用的CL,而且也不安全(如果在读取文件时出现错误会发生什么情况?):您可能希望查看规范的第21.2节(我故意不给您答案,因为您一直很诚实&说这是家庭作业,谢谢!).

您正在读取一个文件,该文件具有DOS行结束约定,并且系统需要Unix行结束约定

DOS使用回车/换行对结束行。回车的ASCII码是#x0d/13,它是控件M,换行是#x0a/10,它是控件J

这些字符的CL名称(我应该在上面使用)分别是
#\Return
#\Newline

因此,具有DOS行结束约定的文件将包含(十六进制)
0d0a
等序列来标记行结束。读取它时,如果希望使用Unix行结束约定(只有一个
0a
),则会将其作为最后一个字符为
\Return
的行来读取

处理这一问题的方法有三种:

  • 假设您在Unixy机器上运行,请使用使用Unixy行结束约定的编辑器(OSX上的升华文本仍然如此)
  • 如果您在Windows计算机上,那么Lisp可能默认为假定平台的本机行结束约定,并为您进行翻译
  • 如果上述一项或两项都不起作用,或者文件已在计算机之间移动,则需要阅读
    open
    的实现文档,了解如何教它使用适当的外部格式来读取DOS约定文件

似乎您正在使用CLISP。如果是这样,并且我正确阅读了它的手册,那么您可能希望使用类似于
(open…:external format':dos)



另外要注意的是,尽管您的代码可以正常工作,但它不是非常惯用的CL,而且也不安全(如果在读取文件时出现错误,会发生什么情况?):您可能希望查看规范的第21.2节(我故意不给您答案,因为您诚实地说这是家庭作业,谢谢!)。

“^m”可能是Windows上的文本编辑器经常插入的。在Linux中,我们只使用换行。@ymonad是的,这也是我的猜测。知道我如何在输出中消除它们吗?也许你可以在阅读每一行后调用
string right trim
:另请参阅@coredump谢谢你加入讨论。是的,我正在使用Windows 10。对于CLISP,我使用了一个名为“portacle”的IDE,其中包含用于LISP的SLIME。以下是我的测试文件中hextump的输出:
000000746869732069730d0a0d0a610d0a0d0a0a0a
0000107465730d0a66696c65
“^M”可能经常被Windows上的文本编辑器插入。在Linux中,我们只使用换行。@ymonad是的,这也是我的猜测。知道我如何在输出中消除它们吗?也许你可以在阅读每一行后调用
string right trim
:另请参阅@coredump谢谢你加入讨论。是的,我正在使用Windows 10。对于CLISP,我使用了一个名为“portacle”的IDE,其中包含用于LISP的SLIME。这是我测试文件中hextump的输出:
000000746869732069730d0a0d0a610d0a0d0a0a0a
0000107465730d0a66696c65
谢谢你,这是我得到的答案/解释