前言
在本文中,我們開始撰寫簡單的 Pascal 程式,以熟悉撰寫 Pascal 程式的流程。此外,我們也會介紹一些 Pascal 的基本概念。
Pascal 程式碼的副檔名
按照 Pascal 的慣例,原始碼使用 .pas 或 .pp 為副檔名。 .pas 是 Pascal 和 Delphi 所使用的副檔名。 .pp 是 Free Pascal 為了要和 Delphi 區別而新設置的副檔名。但兩者實質上沒有差別,Free Pascal 也接受用 .pas 為副檔名的原始碼。
除此之外,Pascal 的引入檔 (include file) 的副檔名為 .inc 。
撰寫第一個程式
在本節中,我們以 Pascal 版本的 Hello World 程式來熟悉撰寫 Pascal 程式的流程。
在編輯器中建立新的文字檔案,將其命名為 hello.pas 。輸入以下內容:
program main;
begin
WriteLn('Hello World');
end.
一開始不用急著了解程式碼的意義,現在的重點在於熟悉開發流程。
在命令列環境中以 Free Pascal 編譯 hello.pas :
$ fpc hello.pas
編譯成功後,會得到同名的執行檔。在 Unix 上為 hello (無副檔名),在 Windows 上為 hello.exe 。執行此程式:
$ ./hello
Hello World
如果要更改執行檔的檔名,使用 -o
參數:
$ fpc -ogreet hello.pas
使用 fpc
時,-o
和執行檔名稱間不要有空白。
以命令稿模式執行 Pascal 程式
在 Unix 系統中,我們可以把 Pascal 程式當成命令稿來執行,這是 Free Pascal 特有的功能。
在編輯器中新增文字檔案,將其命名為 hello 。不需要副檔名,因為 Unix 系統本身不依副檔名。輸入以下內容:
#!/usr/bin/env instantfpc
begin
WriteLn('Hello World');
end.
比較特別的是第一行,這裡利用 Free Pascal 附帶的 instantfpc
當成 Pascal 直譯器。
參考以下指令來執行此命令稿:
$ chmod +x hello
$ ./hello
Hello World
其實 instantfpc
會在背景編譯該 Pascal 程式,並將編譯好的程式做快取,只要程式沒有修改,第二次執行會變快。
由於這個功能有用到 Unix 本身的特性,在 Windows 上無法使用。
Pascal 程式的組成
Pascal 程式分為以下兩部分:
- 宣告 (declaration):宣告程式中的物件,包括常數 (constant)、型態 (type)、變數 (variable)、函式 (function)、程序 (procedure) 等
- 敘述 (statement):程式的實際執行步驟,會用到先前所宣告的物件
我們以虛擬碼的方式來展示 Pascal 主程式的組成:
program ProgramName;
(* declaration(s) *)
begin
(* statement(s) *)
end.
把上述虛擬碼改寫詳細一點如下:
program ProgramName;
(* Use external libraries *)
(* Constant declaration(s) *)
(* Type declaration(s) *)
(* Subprogram definition(s) *)
(* Variable declaration(s) *)
begin
(* Statement(s) *)
end.
第一行固定是 program
敘述。在該敘述中, ProgramName 的名稱可自訂,只要符合識別字的命名規則即可。筆者自己一律以 main 來命名主程式。
若有用到外部模組的話,要在一開始時即宣告。後續的程式才能理解外部模組內的物件。
接著分別命名常數和型態別名。我們會把這兩部分放到比較前面是因為有時候副程式 (subprogram) (註) 會用到這些宣告。
(註) 即函式和程序。
接著寫副程式的定義。副程式的順序沒有限制,有一派程式設計者會將功能相關的副程式放在一起,有一派會以英文字母順序來擺放副程式。只要在團隊中保持一致即可。
接著才寫變數宣告。我們會希望變數宣告離主程式近一點,這樣比較容易閱讀。
最後則是主程式的部分。Pascal 沒有主函式的概念,直接將主程式寫在一對由 begin
和 end
所組成的區塊中。
要注意主程式結尾的 end
後的 .
(dot) 是必需的,這代表整個程式的結束。
多檔案專案
Pascal 的原始碼分為 program file 和 unit file 兩種。在 Pascal 專案中,program file 相當於主程式,只會有一個。而 unit file 用來存放模組,可能有零至多個。
剛開始練習時,程式規模短小,所有的程式碼皆放在單一 program file 即可。隨著專案規模成長,我們會把程式碼從 program file 拆分到一至多個 unit file 中。unit file 有另外的組成方式。
我們把多檔案專案的寫法留到後續的文章。
大小寫敏感性 (Case Sensitivity)
Pascal 程式碼不區分大小寫,但我們仍會在程式碼中區分大小寫,以利閱讀和維護程式碼。
空白 (Space)、換行 (Blank Line)、縮進 (Indentation)
在少數情形下,空白是有意義的。例如,命名識別字 (變數、函式、子程序等) 時,識別字中不能使用空白。但在大部分情形中,空白只是讓程式碼比較美觀的手段。同樣地,換行和縮進對 Pascal 編譯器本身沒有意義,僅是為了讓程式碼好看一點。
但我們仍然會適度地用空白、換行、縮進來讓程式碼更美觀。因為程式碼不僅是給機器 (編譯器) 閱讀的,程式設計者也需要閱讀和修改程式碼。把程式碼編排整齊是為了一同合作的程式設計者,這包括未來的自己。
註解 (Comment)
註解是自由文字,用來補充說明程式碼。Pascal 中有三種風格的註解:
- 一對
(*
和*)
,可跨越多行 - 一對
{
和}
,可跨越多行 //
,僅限單行 (Object Pascal 限定)
在 Delphi 和 Free Pascal 中三種風格的註解皆可使用。歐洲的程式設計者比較喜歡第一種風格的註解,因為有些歐洲地區的鍵盤沒有大括號。
在 Pascal 中,註解除了做為說明文字外,還會用在編譯器指示詞 (compiler directive) 及條件編譯 (conditional compilation) (參考這裡)。這算是比較進階的功能,一開始不用花太多時間在這些內容上。
保留字 (Keywords)
保留字 (keywords 或 reserved words) 在程式碼中有特別的意義,不能做為識別字。以下是各個 Pascal 方言的保留字:
由於 Pascal 保留了 Algol 的慣例,以英文單字當成 (一部分的) 運算子和設置程式碼區塊,故保留字會比較多。剛從 C 語言轉換過來的程式設計者可能會感到不太適應。持續寫一段時間的 Pascal 程式就會習慣了。
對於剛學程式設計的讀者來說,可能會覺得保留字難以記憶。實際上,程式設計師不會去記憶保留字,而會在學習程式設計的過程中自然而然地學會保留字。此外,編輯器會以顏色來提示程式設計者保留字出現的位置。
鎖定 Pascal 方言 (Dialect)
在使用 Free Pascal 時,可以鎖定 Pascal 方言。以下是目前在 Free Pascal 中可用的方言:
fpc
:預設模式objfpc
:fpc
加上物件導向的特性tp
:模擬 Turbo Pascal 7.0 和 Borland Pascal 7.0delphi
:模擬 Delphi 7.0macpas
:模擬 Mac Pascaliso
:遵守 ISO/IEC 7185 Pascal 標準
在預設模式 (fpc
) 中,是以 Turbo Pascal 7.0 為基礎,但做了一些修改,去除和 DOS 相關的特性。而 objfpc
模式則在預設模式中加上物件導向相關的特性。
由於 Turbo Pascal 和 Delphi 是封閉原始碼軟體,tp
模式和 delphi
模式是模擬出來的。如果很在意相容性的話,最好還是要用 Delphi 試一下程式碼相容性。
macpas
模式是為了相容 Mac Pascal 而設置的。由於該軟體很舊了,除非是為了遷移舊程式碼,不需要刻意切到這個模式。
iso
模式則是為了遵守 Pascal 標準而設置的模式。由於主流的 Pascal 方言是 Object Pascal,除非是要遷移舊程式碼,不需要切到這個模式。
可以在命令列中以 -M
參數來切換 Pascal 方言。像是以下指令以 delphi
相容模式來編譯 Pascal 程式碼:
$ fpc -Mdelphi -oprogram source.pas
也可以在程式碼中以編譯器指示詞 (compiler directive) 來切換 Pascal 方言。像是以下程式碼會自動以 delphi
相容模式來編譯:
program main;
{$mode delphi}
begin
writeln('Hello World');
end.
切換 Pascal 的目的是為了相容於其他 Pascal 編譯器。如果專案只會用 Free Pascal 來編譯,可以用預設模式來編譯程式碼,並在必要時打開 objfpc
模式即可。
Modern Object Pascal
Pascal 在長年演進中出現多個版本。為了要使用一致的 Pascal 語法特性,且要跟上現代語言的功能,有程式設計者倡導以 Modern Object Pascal 來學習及撰寫 Pascal 程式。
所謂的 Modern Object Pascal 就是一律在 Free Pascal 程式碼中加上以下編譯器指示詞 (compiler directive):
{$mode objfpc}{$H+}{$J-}
這樣的宣告會開啟三項特性
$mode objfpc
:使用物件導向、泛型等現代語言的語法功能$H+
:使用 AnsiString$J-
:不允許對有型態的常數賦值
但筆者並沒有完全遵守這樣的建議。因為 Pascal 是有歷史的語言,遷移現有程式碼仍然是重要的考量。刻意守在某一套編譯器指示詞只是劃地自限。