跳转到内容

Pascal 编程/输入输出

来自维基教科书,自由的教学读物

我们从第一章开始就已经使用 I/O 了,但只是为了入门。现在该深入一点了,这样我们就可以编写更漂亮的程序。

在鼎盛时期,Pascal 非常聪明,它定义了一个最小公用且方便的接口来与 I/O 交互。尽管各种标准化工作,但 I/O 操作在每个 OS 中都不相同,但作为语言的一部分,Pascal 定义了一组操作,无论使用的是什么编译器或 OS,这些操作都必须存在。

特殊文件

[编辑 | 编辑源代码]

第一章 中已经提到,inputoutput 是特殊的程序参数。如果您在程序参数列表中列出它们,则可以使用这些标识符来写入和读取终端,即您正在使用的 CLI

文本文件

[编辑 | 编辑源代码]

事实上,inputoutput 是变量。它们的类型是 text。我们称具有类型为 text 的变量为文本文件

文本文件的 数据 由组成。是(可能为空的)字符序列(例如字母、数字、空格或标点符号),直到并且包括一个终止的“换行符”。

一个文件 - 通常 - 具有以下属性

  • 它可以与外部实体关联。外部意味着“在”您的程序“之外”。一个合适的实体可以是,例如,您的控制台窗口、一个设备(如您的键盘)或一个驻留在您的文件系统中的文件。
  • 如果一个文件与一个外部实体关联,则它被认为是绑定的。
  • 一个文件有一个模式。每个文件可以处于生成检查模式,没有或两者都有。如果一个文件同时处于生成检查模式,这也可以称为更新模式。 [fn 1]
  • 每个文件都有一个缓冲区。这个缓冲区是用于写入或读取数据的临时存储,实际上是另一个变量。由于计算机上 I/O 的工作方式,存在此缓冲区变量。

所有这些信息都隐式提供给您,您无需关心它。您可以以预定义的方式查询和更改某些信息。

为了成功使用文件,您只需要记住,一个文件具有一个模式。文本文件 inputoutput,一旦它们在程序参数列表中列出,就分别处于检查和生成模式。您只能从处于检查模式的文件中读取数据。并且只能写入数据处于生成模式的文件中。

请注意,由于其特殊性质,inputoutput 的模式不能更改。

Pascal 定义了以下例程来读取和写入文件

  • get,
  • put,
  • read/readLn,以及
  • write/writeLn

例程 readLnwriteLn 只能与文本文件一起使用,而所有其他例程都适用于任何类型的文件。在接下来的部分中,我们将重点介绍 readwrite。这些例程建立在“低级” getput 之上。在 “文件” 章中,我们将对其进行研究。

写入数据

[编辑 | 编辑源代码]

让我们看一个简单的程序

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”)的转换是自动完成的。

Note 如果 write/writeLn 的目标是一个文本文件,则所有参数都将转换为人类可读的格式,前提是这种转换是必要的并且有意义的。

格式化输出

[编辑 | 编辑源代码]

此外,在参数 x 之后是 :20。正如您可能已经注意到的,当您运行程序时,十的值右对齐,使 0 出现在 10 中,出现在第 20 列(从左边缘开始的位置)。

:20 是一个 _格式说明符_。它确保给定参数具有 _至少_ 这么多字符的宽度,并且它可以使用空格填充左侧缺少的“宽度”。

Note 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)

Note 如果源是文本文件,您只能为具有数据类型 charintegerreal 或“字符串类型”的变量读取值。其他与这些类型不兼容的变量无法从文本文件中读取。(“兼容”一词将在后面解释。)

分支

[edit | edit source]

我们将下一章详细介绍的一种新的语言结构是 if - then 分支。仅当 response 等于字符值 'y' 时,才会执行 then 之后由 beginend; 包围的代码。否则,我们很礼貌,不会表达我们强烈的不同意见。

任务

[edit | edit source]
你能 writeinput 吗?为什么/它应该工作,或者不工作?
你不能 writeinput。文本文件 input 处于 _检查_ 模式,前提是它在程序参数列表中。这意味着你只能从这个文本文件 read 数据,而不能 write
你不能 writeinput。文本文件 input 处于 _检查_ 模式,前提是它在程序参数列表中。这意味着你只能从这个文本文件 read 数据,而不能 write


你能 read 到 _常量_ 吗?
不,read / readLn 的所有参数都_必须_是变量。常量,根据定义,在运行时不会改变其值。这意味着,用户也不能为常量赋值。
不,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.
注意,“开启”的打字机撇号在第一个井号之前开始。但是,缩进已保留,因此您仍然可以在源代码中识别心形,并且不需要运行程序就可以看到它。
改进后的版本可能如下所示
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.
注意,“开启”的打字机撇号在第一个井号之前开始。但是,缩进已保留,因此您仍然可以在源代码中识别心形,并且不需要运行程序就可以看到它。


创建一个程序,绘制一个 40x6 的框,如下所示,但(出于教育目的)我们_不想_在源代码中四次输入 38 个空格。
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.
一个可接受的实现可能如下所示
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.

笔记

  1. “更新”模式仅在扩展 Pascal (ISO 标准 10206) 中可用。在标准(未扩展)Pascal(在 ISO 标准 7185 中规定)中,文件可以处于检查或生成模式,或者两者都不处于。


下一页: 表达式和分支 | 上一页: 变量和常量
首页: Pascal 编程
华夏公益教科书