标签归档:函数式编程

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

本文包括以下内容:

作为一门语言,它需要提供与外设交互的方式,在各种语言中都提供了输入输出,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):

(define (main)
 
(let ((a (read)) (b (read)))
 
(if (not(eof-object? a))
(begin
(display (+ a b))
(newline)
(main)
)
)
)
 
)
 
(main)

题目很简单,就是输入两个数,输出和。这里的难点是对于输入结束的判断,在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的返回值。

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

(define input_port (open-input-file "temp"))
 
(define read-char-with-file (lambda (port)
(if (eof-object? (peek-char port))
'()
(cons (read-char port) (read-char-with-file port))
)
)
)
 
(if (input-port? input_port)
(begin
(display (read-char-with-file input_port))
(close-input-port input_port)
)
 
(begin
(display "read file form temp failed")
(newline)
)
)

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

(define output-chars
(call-with-input-file "temp"
(lambda (p)
(let f ((x (read-char p)))
(if (eof-object? x)
'()
(cons x (f (read-char p)))
) 
)
)
)
)
 
(display output-chars)
(newline)

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》