Pascal 编程/输入输出
我们从第一章开始就已经使用 I/O 了,但只是为了入门。现在该深入一点了,这样我们就可以编写更漂亮的程序。
在鼎盛时期,Pascal 非常聪明,它定义了一个最小公用且方便的接口来与 I/O 交互。尽管各种标准化工作,但 I/O 操作在每个 OS 中都不相同,但作为语言的一部分,Pascal 定义了一组操作,无论使用的是什么编译器或 OS,这些操作都必须存在。
在 第一章 中已经提到,input
和 output
是特殊的程序参数。如果您在程序参数列表中列出它们,则可以使用这些标识符来写入和读取终端,即您正在使用的 CLI。
事实上,input
和 output
是变量。它们的类型是 text
。我们称具有类型为 text
的变量为文本文件。
文本文件的 数据 由行组成。行是(可能为空的)字符序列(例如字母、数字、空格或标点符号),直到并且包括一个终止的“换行符”。
一个文件 - 通常 - 具有以下属性
- 它可以与外部实体关联。外部意味着“在”您的程序“之外”。一个合适的实体可以是,例如,您的控制台窗口、一个设备(如您的键盘)或一个驻留在您的文件系统中的文件。
- 如果一个文件与一个外部实体关联,则它被认为是绑定的。
- 一个文件有一个模式。每个文件可以处于生成或检查模式,没有或两者都有。如果一个文件同时处于生成和检查模式,这也可以称为更新模式。 [fn 1]
- 每个文件都有一个缓冲区。这个缓冲区是用于写入或读取数据的临时存储,实际上是另一个变量。由于计算机上 I/O 的工作方式,存在此缓冲区变量。
所有这些信息都隐式提供给您,您无需关心它。您可以以预定义的方式查询和更改某些信息。
为了成功使用文件,您只需要记住,一个文件具有一个模式。文本文件 input
和 output
,一旦它们在程序参数列表中列出,就分别处于检查和生成模式。您只能从处于检查模式的文件中读取
数据。并且只能写入
数据到处于生成模式的文件中。
请注意,由于其特殊性质,input
和 output
的模式不能更改。
Pascal 定义了以下例程来读取和写入文件
get
,put
,read
/readLn
,以及write
/writeLn
。
例程 readLn
和 writeLn
只能与文本文件一起使用,而所有其他例程都适用于任何类型的文件。在接下来的部分中,我们将重点介绍 read
和 write
。这些例程建立在“低级” get
和 put
之上。在 “文件” 章中,我们将对其进行研究。
让我们看一个简单的程序
program writeDemo(output);
var
x: integer;
begin
x := 10;
writeLn(output, x:20);
end.
复制该程序,看看它做了什么。
首先,我们将学习一个新的语句,赋值。冒号等号 (:=
) 读作“变成”。在 x := 10
这行中,变量的值变成十。在左侧,您写入一个变量名。在右侧,您放置一个值。该值必须对变量的类型有效。例如,您不能将 'Hello world!'
赋值给变量 x
,因为它不是一个有效的 integer
,即 x
的类型。
write
/writeLn
的强大之处在于 - 对于文本文件 - 它会将参数转换为人类可读的格式。在现代计算机中,十的 integer
值以特定的二进制形式存储。 00001010
是设置的位 (1
) 和未设置的位 (0
) 的可视化表示,用于存储“十”。然而,尽管是二进制存储,但您在屏幕上看到的字符是 10
。这种从零和一到人类可读表示(字符序列“10”)的转换是自动完成的。
如果 write /writeLn 的目标是一个文本文件,则所有参数都将转换为人类可读的格式,前提是这种转换是必要的并且有意义的。 |
此外,在参数 x
之后是 :20
。正如您可能已经注意到的,当您运行程序时,十的值右对齐,使 0
出现在 10
中,出现在第 20 列(从左边缘开始的位置)。
:20
是一个 _格式说明符_。它确保给定参数具有 _至少_ 这么多字符的宽度,并且它可以使用空格填充左侧缺少的“宽度”。
在 write / writeLn 调用中的格式说明符只能在需要人类可读表示的地方指定,换句话说,如果目标是文本文件。 |
读取数据
[edit | edit source]看看这个程序
program iceCream(input, output);
var
response: char;
begin
writeLn('Do you like ice cream?');
writeLn('Type “y” for “yes” (“Yummy!”) and “n” for “no”.');
writeLn('Confirm your selection by hitting Enter.');
readLn(input, response);
if response = 'y' then
begin
writeLn('Awesome!');
end;
end.
需求
[edit | edit source]传递给 read
/ readLn
的所有参数都必须是变量。第一个参数,即 _源_,必须是当前处于检查模式的文件变量。我们通过将 input
放入程序参数列表来确保这一点。如果源参数是 input
,则允许您省略它,因此 readLn(response)
等效于 readLn(input, response)
。
如果源是文本文件,您只能为具有数据类型 char 、integer 、real 或“字符串类型”的变量读取值。其他与这些类型不兼容的变量无法从文本文件中读取。(“兼容”一词将在后面解释。) |
分支
[edit | edit source]我们将下一章详细介绍的一种新的语言结构是 if
- then
分支。仅当 response
等于字符值 'y'
时,才会执行 then
之后由 begin
和 end;
包围的代码。否则,我们很礼貌,不会表达我们强烈的不同意见。
任务
[edit | edit source]write
到 input
吗?为什么/它应该工作,或者不工作?write
到 input
。文本文件 input
处于 _检查_ 模式,前提是它在程序参数列表中。这意味着你只能从这个文本文件 read
数据,而不能 write
。
read
到 _常量_ 吗?read
/ readLn
的所有参数都_必须_是变量。常量,根据定义,在运行时不会改变其值。这意味着,用户也不能为常量赋值。
program valentine
并利用你在本章中学习的知识对其进行改进:使心形图(类似)居中。假设控制台窗口宽度为 80 个字符,或任何合理的宽度。program valentine(output);
const
width = 49;
begin
writeLn(' #### #### ':width);
writeLn(' ######## ######## ':width);
writeLn('## #### ##':width);
writeLn('## # ##':width);
writeLn('## ILY ##':width);
writeLn(' ## sweetie ## ':width);
writeLn(' ### ### ':width);
writeLn(' ### ### ':width);
writeLn(' ### ### ':width);
writeLn(' ### ':width);
writeLn(' # ':width);
end.
string
文字比 width
短(否则它不再像心形图),那么字符串文字在_左侧_可以更短。program valentine(output);
const
width = 49;
begin
writeLn( '#### #### ':width);
writeLn( '######## ######## ':width);
writeLn('## #### ##':width);
writeLn('## # ##':width);
writeLn('## ILY ##':width);
writeLn( '## sweetie ## ':width);
writeLn( '### ### ':width);
writeLn( '### ### ':width);
writeLn( '### ### ':width);
writeLn( '### ':width);
writeLn( '# ':width);
end.
o--------------------------------------o
| |
| |
| |
| |
o--------------------------------------o
''
。它是两个连在一起的直打字机撇号。你可以在你的解决方案中使用它。program box(output);
const
space = 38;
begin
writeLn('o--------------------------------------o');
writeLn('|', '':space, '|');
writeLn('|', '':space, '|');
writeLn('|', '':space, '|');
writeLn('|', '':space, '|');
writeLn('o--------------------------------------o');
end.
'':space
将生成 38 个空格(即常量 space
的值)。如果您真的聪明,您会注意到框的顶部和底部边缘是_相同的_文字两次。我们可以进一步缩短我们的程序program box(output);
const
space = 38;
topAndBottomEdge = 'o--------------------------------------o';
begin
writeLn(topAndBottomEdge);
writeLn('|', '':space, '|');
writeLn('|', '':space, '|');
writeLn('|', '':space, '|');
writeLn('|', '':space, '|');
writeLn(topAndBottomEdge);
end.
笔记
- ↑ “更新”模式仅在扩展 Pascal (ISO 标准 10206) 中可用。在标准(未扩展)Pascal(在 ISO 标准 7185 中规定)中,文件可以处于检查或生成模式,或者两者都不处于。