最新消息:

Scheme学习笔记2: 输入和输出

未分类 admin 2867浏览 0评论

本文包括以下内容:

作为一门语言,它需要提供与外设交互的方式,在各种语言中都提供了输入输出,Scheme语言也不例外。Scheme语言的输入输出功能,是在C基础上的一种封装。

read和write

输入输出中我们常用是读和写,对应读与写,在Scheme中有read和write。
read是读操作,它将 Scheme 对象的外部表示转换为对象本身。
read的标准格式为:(read port)
其中port参数可以省略,此时它使用的默认是current-input-port的返回值。

write是写操作,它的标准格式为:(read obj port)
write过程的作用是向给定端口port输出obj的内容。其中输出内容的反斜线、双引号等会被反斜线转义。write的参数中port参数可以省略,默认情况下使用current-output-port的返回值。

这里的默认值我们可以对应到标准输入和输出。从ZOJ的第一题我们看下read的使用。
如下代码:

ZOJ第一题(zoj1001):

<span style="color: #66cc66;">(</span>define <span style="color: #66cc66;">(</span>main<span style="color: #66cc66;">)</span>

<span style="color: #66cc66;">(</span><span style="color: #b1b100;">let</span> <span style="color: #66cc66;">(</span><span style="color: #66cc66;">(</span>a <span style="color: #66cc66;">(</span>read<span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span> <span style="color: #66cc66;">(</span>b <span style="color: #66cc66;">(</span>read<span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span>

<span style="color: #66cc66;">(</span><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">(</span><span style="color: #b1b100;">not</span><span style="color: #66cc66;">(</span>eof-object? a<span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span>begin
<span style="color: #66cc66;">(</span>display <span style="color: #66cc66;">(</span>+ a b<span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span>newline<span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span>main<span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">)</span>

<span style="color: #66cc66;">)</span>

<span style="color: #66cc66;">(</span>main<span style="color: #66cc66;">)</span>

题目很简单,就是输入两个数,输出和。这里的难点是对于输入结束的判断,在C语言中scanf函数有一个EOF的判断,而在Scheme语言中,我们通过判断输入的输入的值是否为eof来判断,其对应的判断过程为eof-object?(嗯,问号也是调用过程的组成部分,个人非常喜欢这种表达方式),在判断不为结束时继续递归调用,实现C语言中的while循环。

字符操作

对于字符的读写操作,我们常用的三个过程如下:

read-char
标准格式: (read-char port)
读取一个字符,并将port指针指向下一个字符。
read-char的参数中port可以省略,默认情况下使用current-input-port的返回值。

write-char
标准格式: (write-char port)
write-char过程的作用是向给定端口port输出的内容。
write-char的参数中port可以省略,默认情况下使用current-output-port的返回值。

peek-char
标准格式: (peek-char port)
获取一个字符,但并不将port指针指向下一个字符
peek-char的参数中port可以省略,默认情况下使用current-input-port的返回值。

以一个示例说明这三个过程的调用,示例实现从指定文件中按字符读取内容,并放到一个列表中。

<span style="color: #66cc66;">(</span>define input_port <span style="color: #66cc66;">(</span>open-input-file <span style="color: #ff0000;">"temp"</span><span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span>

<span style="color: #66cc66;">(</span>define read-char-with-file <span style="color: #66cc66;">(</span><span style="color: #b1b100;">lambda</span> <span style="color: #66cc66;">(</span>port<span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">(</span>eof-object? <span style="color: #66cc66;">(</span>peek-char port<span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span>
'<span style="color: #66cc66;">(</span><span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span><span style="color: #b1b100;">cons</span> <span style="color: #66cc66;">(</span>read-char port<span style="color: #66cc66;">)</span> <span style="color: #66cc66;">(</span>read-char-with-file port<span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">)</span>

<span style="color: #66cc66;">(</span><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">(</span>input-port? input_port<span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span>begin
<span style="color: #66cc66;">(</span>display <span style="color: #66cc66;">(</span>read-char-with-file input_port<span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span>close-input-port input_port<span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">)</span>

<span style="color: #66cc66;">(</span>begin
<span style="color: #66cc66;">(</span>display <span style="color: #ff0000;">"read file form temp failed"</span><span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span>newline<span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">)</span>

这段代码写得有些复杂,我们可以通过let关键字和call-with-input-file过程来简化这段代码,如下:

<span style="color: #66cc66;">(</span>define output-chars
<span style="color: #66cc66;">(</span>call-with-input-file <span style="color: #ff0000;">"temp"</span>
<span style="color: #66cc66;">(</span><span style="color: #b1b100;">lambda</span> <span style="color: #66cc66;">(</span>p<span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span><span style="color: #b1b100;">let</span> f <span style="color: #66cc66;">(</span><span style="color: #66cc66;">(</span>x <span style="color: #66cc66;">(</span>read-char p<span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span><span style="color: #b1b100;">if</span> <span style="color: #66cc66;">(</span>eof-object? x<span style="color: #66cc66;">)</span>
'<span style="color: #66cc66;">(</span><span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span><span style="color: #b1b100;">cons</span> x <span style="color: #66cc66;">(</span>f <span style="color: #66cc66;">(</span>read-char p<span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span><span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">)</span>

<span style="color: #66cc66;">(</span>display output-chars<span style="color: #66cc66;">)</span>
<span style="color: #66cc66;">(</span>newline<span style="color: #66cc66;">)</span>

call-with-input-file的标准调用格式为:

procedure: (call-with-input-file path procedure)

call-with-input-file过程给指定的文件创建一个port,并将这个port传递给第二个参数指定的过程procedure,当procedure执行完成时,call-with-input-file过程将关闭打开的输入port并返回procedure返回的值。

文件操作

上面的示例已经提了文件操作,关于文件操作,除了针对输入和输出的打开port和关闭port,判断port是否存在的过程外,我们常用还有判断文件存在,删除文件,Scheme提供的这两个过程来与文件系统交互:file-exists?和delete-file
file-exists?的作用是判断文件是否存在,其调用格式如下:
(file-exists? path)
如果文件存在,返回#t,否则返回#f

delete-file的作用是删除一个文件,其调用格式如下:
(delete-file path)

path是字符串类型,如果所给的文件不存在,则会显示错误:No such file or directory

在使用delete-file之前可以调用file-exists?来判断文件是否存在。

除了上面介绍的一些简单输入输出,Scheme还提供了更强大和灵活的输入输出机制,如对编码的处理,对二进制的处理,对字符串的操作等,具体可以见官方文档或《The Scheme Programming Language, 4th Edition》

转载请注明:爱开源 » Scheme学习笔记2: 输入和输出

您必须 登录 才能发表评论!