SML输入输出操作全解析
立即解锁
发布时间: 2025-08-18 00:31:30 阅读量: 1 订阅数: 4 

### SML 输入输出操作全解析
在编程中,输入输出(I/O)操作是与外界进行数据交互的重要手段。SML(Standard ML)作为一种功能强大的编程语言,也提供了丰富的 I/O 功能。本文将详细介绍 SML 中的输入输出操作,包括基本概念、不同类型数据的输出、键盘输入、交互式 I/O 以及异常处理等方面。
#### 1. 引言
在 SML 编程中,以往我们主要在 SML 系统内部进行操作,输入数据和输出结果都是 SML 值。现在,我们将探讨如何从 SML 系统外部,如键盘或文件获取输入数据,以及如何在屏幕或文件中呈现结果,而不受 SML 值形式的限制。
SML 的输入输出操作基于字符序列。系统提供了从输入源获取字符序列作为字符串,并将其发送到输出目标的函数,我们将以此为基础进行更复杂的 I/O 操作。
I/O 操作有两种互补的方法:
- 整体处理:对于输出,可以将整个字符串组装好后一次性显示或发送到文件;对于输入,可以一次性读取整个字符串,然后使用之前章节讨论的词法和字符串处理技术提取信息。
- 逐项处理:逐次输出和输入值,而不是一次性打包或解包。嵌套的 let 表达式在这种情况下对于 I/O 操作的排序非常有用。
这两种方法可以结合用于交互式 I/O,即程序提示用户输入信息,显示结果后再提示用户输入更多信息。
SML 的 I/O 基于流(streams),流分为输入流(instream)和输出流(outstream),但同一时间一个流只能用于输入或输出。通常,通过打开文件来建立流,系统会分配一个新的流。流值不能直接显示,但也无需显示,而是将流值与一个名称关联,使用该名称将流传递给 I/O 函数。内置的输入流 `std_in` 可用于从键盘输入,内置的输出流 `std_out` 可用于向屏幕输出。需要注意的是,`instream` 和 `outstream` 不是可比较类型,不能通过比较两个流来识别它们。
#### 2. 单元类型
单元类型只有一个值 `()`,例如 `()` 的类型就是 `unit`。单元类型用于在操作后给出中性结果,或向函数传递中性参数。在模式匹配中,`()` 可作为虚拟参数使用。许多 I/O 函数返回 `()` 作为结果。以下是一些示例代码:
```sml
– ( );
> () : unit
– fun hello( ) = "hello";
> val hello = fn : unit -> string
– hello( );
> "hello" : string
```
#### 3. 屏幕输出
基本的屏幕输出使用系统函数 `output`,它接受一个由输出流和字符串组成的元组作为参数,将字符串显示在指定的输出流上,不显示引号,并返回单元值 `()`。例如:
```sml
– output;
> fn : outstream * string -> unit
– output (std_out, "banana");
banana > ( ) : unit
```
可以使用换行符 `\n` 使后续输出出现在新的一行。为了方便使用,我们可以封装 `output` 函数,创建字符串输出到屏幕的函数:
```sml
– (* string write to standard output *)
fun swrite s = output (std_out, s);
> val swrite = fn : string -> unit
– swrite "fritters";
fritters > ( ): unit
```
在此基础上,我们可以创建一个在显示字符串后添加换行符的函数:
```sml
– (* newline terminated string write to standard output *)
fun swriteln s = swrite (s^"\n");
> val swriteln = fn : string -> unit
– swriteln "split";
split
> ( ) : unit
```
#### 4. 字符串列表输出
当我们有一个字符串列表并想在屏幕上显示时,可以直接将列表内的字符串拼接并打印,但 `implode` 函数会将列表元素连接在一起,中间没有间隔。为了在字符串之间添加空格,我们可以编写一个递归函数 `spimplode`:
```sml
– (* space separated implode *)
fun spimplode [ ] = " " |
spimplode [s] = s |
spimplode (h::t) = h^" "^spimplode t;
> val spimplode = fn : string list -> string
– spimplode ["water","for", "wetness"];
> "water for wetness" : string
```
然后,我们可以定义一个函数 `slwrite` 来输出用空格分隔的字符串列表:
```sml
– (* space separated string list write to standard output *)
fun slwrite s = swrite (spimplode s);
> val slwrite = fn : string list -> unit
– slwrite ["water", "for", "wetness"];
water for wetness > ( ) : unit
```
为了在字符串序列后添加换行符,我们可以定义 `slwriteln` 函数:
```sml
– (* newline terminated, space separated string list write to standard output *)
fun slwriteln s = swriteln (spimplode s);
> val slwriteln = fn : string list -> unit
– slwriteln ["water", "for", "wetness"];
water for wetness
> ( ) : unit
```
如果想将字符串列表的每个元素显示在单独的一行,可以使用 `addnl` 函数在每个字符串末尾添加换行符,然后使用 `slwritelns` 函数输出:
```sml
– (* join newline to each in string list *)
val addnl = map (fn s => s^"\n");
> val addnl = fn : string list -> string list
– addnl ["able", "baker", "charlie"];
> ["able\n", "baker\n", "charlie\n"] : string list
– (* separate line string list write to standard output *)
fun slwritelns s = swrite (implode (addnl s));
> val slwritelns = fn : string list -> unit
– slwritelns ["able", "baker", "charlie"];
able
baker
charlie
> ( ) : unit
```
#### 5. 整数列表输出
在之前的章节中,我们编写了将整数转换为字符串的函数 `iconv` 和 `iconv1`。利用这些函数,我们可以将整数输出到屏幕:
```sml
– (* convert integer to string *)
fun iconv 0 = "0" |
iconv n = iconv1 n
> val iconv = fn : int -> string
(* convert integer to string ignoring single 0 *)
and iconv1 0 = " " |
iconv1 n = iconv1 (n div 10)^chr (n mod 10+ord "0");
> val iconv1 = fn : int -> string
– (* integer write to standard output *)
fun iwrite i = swrite (iconv i);
> val iwrite = fn : int -> unit
– iwrite 777;
777> ( ) : unit
```
若要将整数显示在一行的末尾,可以在其字符串表示后添加换行符:
```sml
– (* newline terminated integer write to standard output *)
fun iwriteln i = swriteln (iconv i);
> iwriteln = fn : int -> unit
– iwriteln 888;
888
> ( ) : unit
```
对于整数列表,可以先将每个整数转换为字符串,然后使用 `slwrite` 函数输出用空格分隔的整数列表:
```sml
– (* space separated integer-list write to standard output *)
fun ilwrite l = slwrite (map iconv l);
> val ilwrite = fn : int list -> unit
– ilwrite [1, 3, 5, 7];
1 3 5 7> ( ) : unit
```
同样,为了在整数列表显示后添加换行符,可以定义 `ilwriteln` 函数:
```sml
– (* newline terminated, space separated integer list write to standard output *)
fun ilwriteln s = slwriteln (map iconv s);
> val ilwriteln = fn : int list -> unit
– ilwriteln [3, 6, 9, 12];
3 6 9 1 2
> ( ) : unit
```
#### 6. 格式化输出
在很多情况下,我们希望在固定宽度的字段中打印项目,例如排版表
0
0
复制全文
相关推荐










