跳轉到內容

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 程式設計
華夏公益教科書