函式、程序與基礎原生型別

修改上一堂課的dpr檔案,替換為以下內容

{$ifdef FPC} {$mode objfpc}{$H+}{$J-} {$endif}
{$ifdef MSWINDOWS} {$apptype CONSOLE} {$endif}
program MyProgram;
procedure MyProcedure(const A: Integer);
begin
  WriteLn('A + 10 is: ', A + 10);
end;
function MyFunction(const S: string): string;
begin
  Result := S + 'strings are automatically managed';
end;
var
  X: Single;
begin
  WriteLn(MyFunction('Note: '));
  MyProcedure(5);
  // 斜線「/」除法永遠產生浮點數結果,若要整數除法請使用「div」
  X := 15 / 5;
  WriteLn('X is now: ', X); // 科學記號輸出
  WriteLn('X is now: ', X:1:2); // 限制小數兩位
end.Code language: PHP (php)
D:\fpcdemo>fpc mydemo.dpr
Free Pascal Compiler version 3.2.2 [2021/05/15] for i386
Copyright (c) 1993-2021 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling mydemo.dpr
Linking mydemo.exe
20 行編譯完成,0.0 秒,39248 位元組程式碼,2484 位元組資料

D:\fpcdemo>mydemo
Note: strings are automatically managed
A + 10 is: 15
X is now:  3.000000000E+00
X is now: 3.00

D:\fpcdemo>Code language: CSS (css)

下方為逐行註解說明。非英文字元可能出現亂碼,請設定主控台編碼以正常顯示繁體中文。

{$ifdef FPC} {$mode objfpc}{$H+}{$J-} {$endif}
{$ifdef MSWINDOWS} {$apptype CONSOLE} {$endif}
program MyProgram; 
// 自訂程式名稱。Pascal 主控台程式必須以 program 名稱; 開頭,後續宣告變數、程序與主執行程式碼

// 無回傳值:procedure 程序。程序與函式僅在被呼叫時才會執行
procedure MyProcedure(const A: Integer);
begin
  WriteLn('A + 10 =:', A + 10);
end;

// 有回傳值:function 函式
function MyFunction(const S: string): string;
begin
  Result := S + '字串記憶體由系統自動管理';
end;

// Object Pascal 沒有 main 函式,最外層 begin...end. 區塊為程式進入點,以下是主區塊
var
  X: Single; // 單精準度浮點基礎型別
begin 
  // 所有要執行的邏輯皆寫在此處
  WriteLn(MyFunction('提示:'));
  MyProcedure(5);

  // 運算子「/」永遠回傳浮點數,整數除法使用 div
  X := 15 / 5;
  WriteLn('X is now:', X); // 自動以科學記號輸出
  WriteLn('X is now:', X:1:2); // 限定輸出兩位小數
end. // end. 加上句號代表整支程式結束Code language: PHP (php)

每個函式與程序都有一組 begin、end 標示函式本體的開頭與結尾,等同 C、C++、JAVA 的大括號 { }。

WriteLn 會將內容輸出至主控台,單引號 ‘ ‘ 包覆字串常值。WriteLn('A + 10 =:', A + 10); 會依序輸出字串 A + 10 =: 以及運算結果 A + 10。

一支程式只能有一組最外層的 begin 與 end. 區塊,內部放置主程式碼,並呼叫其他函式、程序。

X := 15 / 5;
WriteLn(‘X is now: ‘, X); // 科學記號
WriteLn(‘X is now: ‘, X:1:2); // 兩位小數

/ 為浮點除法,商永遠是小數型數值。

最前兩行是前置編譯指令

{$ifdef FPC} {$mode objfpc}{$H+}{$J-} {$endif}Code language: PHP (php)

這是 FPC 專屬條件式編譯指令

  • {$ifdef FPC}:只有編譯器為 Free Pascal 時,才執行中間的設定
  • {$mode objfpc}:切換至 ObjFpc 語法模式
  • {$H+}:啟用 長字串(具自動記憶體管理的現代 string 型別,必要設定)
  • {$J-}:停用可變常數(常數執行期不可修改,提升安全性)
  • {$endif}:條件區塊結尾

作用:僅在使用 FPC 編譯時開啟現代語法;Delphi 編譯器會忽略整個區塊。

{$ifdef MSWINDOWS} {$apptype CONSOLE} {$endif}Code language: PHP (php)

跨平台條件編譯

  • MSWINDOWS:僅在 Windows 作業系統生效
  • {$apptype CONSOLE}:將程式定義為 主控台應用程式(開啟黑色終端視窗,而非圖形介面視窗)。在 Linux/macOS 編譯時此行會被忽略。

核心知識重點

  • string 原生基礎型別;FPC/Delphi 自動管理記憶體,不需手動釋放
  • procedure 程序:無回傳值;function 函式:具回傳值,儲存於內建變數 Result
  • 除法區分:/ 浮點除法;div 截斷小數的整數除法
  • 格式化輸出 變數:總寬度:小數位數 控制浮點數顯示格式
  • 無參數遞迴函式必須加上空括號 (),避免語義歧義
  • Exit(數值) 可直接指定回傳值並提前離開函式
  • 函式可忽略回傳值直接呼叫,適用於修改全域變數等帶有副作用的邏輯

函式回傳值規則

  1. 內建特殊變數 Result 存放函式回傳數值,讀寫方式與區域變數完全相同
function MyFunction(const S: string): string;
begin
  Result := S + 'One';
  Result := Result + 'Two';
end;
Code language: PHP (php)
  1. 舊式語法允許直接對函式名稱賦值(MyFunction := xxx),可讀性差不建議使用,統一使用 Result

C/C++/Java/C# 使用 = 賦值、== 相等比較。Pascal 剛好相反::= 用於變數賦值,單一個 = 做相等判斷,與數學記號規則一致。

Pascal 不存在 == 運算子

將範例原本的 MyFunction 替換為上方版本。此函式會在呼叫傳入的字串後面先串接 One,再接 Two。

最終回傳字串:原始字串 + One + Two

遞迴呼叫

無參數函式做遞迴呼叫時,必須加上空括號 (),區分「執行呼叫函式」與「讀取當前回傳值」:

function SumIntegersUntilZero: Integer;
var I: Integer;
begin
  ReadLn(I);
  Result := I;
  if I <> 0 then
    Result := Result + SumIntegersUntilZero(); // 遞迴呼叫需帶 ()
end;
Code language: JavaScript (javascript)

無參數函式 SumIntegersUntilZero 兩種寫法差異說明:

  1. SumIntegersUntilZero()遞迴執行函式並取得回傳值
  2. SumIntegersUntilZero → 存取內部變數 Result(函式自身的回傳值)

移除括號後的程式碼:

Result := Result + SumIntegersUntilZero;

編譯器會解讀成:

Result := Result + Result;

等同 Result := Result * 2,整份遞迴邏輯完全失效,產生無限迴圈且數值持續加倍。

本範例邏輯:函式會持續呼叫自身,直到輸入數值為 0 才結束;只要輸入不為零,遞迴就會持續執行。

Exit:提前結束函式

  1. 無參數 Exit:立即離開函式,回傳已賦值完成的 Result
  2. Exit(數值):直接指定回傳值並終止函式,等同 C 語言的 return x
function AddName(const ExistingNames, NewName: string): string;
begin
  if ExistingNames = '' then
    Exit(NewName); // 直接回傳 NewName 並中斷執行
  Result := ExistingNames + ', ' + NewName;
end;
Code language: PHP (php)
{$ifdef FPC} {$mode objfpc}{$H+}{$J-} {$endif}
{$ifdef MSWINDOWS} {$apptype CONSOLE} {$endif}
program MyProgram;
procedure MyProcedure(const A: Integer);
begin
  WriteLn('A + 10 is: ', A + 10);
end;

function AddName(const ExistingNames, NewName: string): string;
begin
  if ExistingNames = '' then
    Exit(NewName); 
  Result := ExistingNames + ', ' + NewName;
end;

var
  X: Single;
begin
  WriteLn(AddName('Tom','Jack'));
  WriteLn(AddName('Tom',''));
  WriteLn(AddName('','Jack'));
end.Code language: PHP (php)

將函式當程序呼叫(忽略回傳值)

即便函式具有回傳值,也可只執行邏輯而忽略結果;適用於修改全域變數等具備副作用的程式邏輯:

var
  Count, MyCount: Integer;
function CountMe: Integer;
begin
  Inc(Count); // 副作用:全域變數加一
  Result := Count;
end;
begin
  Count := 10;
  CountMe;   // 捨棄回傳值,僅執行邏輯,Count 變成 11
  MyCount := CountMe; // 儲存回傳數值,Count 變成 12
end.
Code language: PHP (php)

完整可執行範例

{$ifdef FPC} {$mode objfpc}{$H+}{$J-} {$endif}
{$ifdef MSWINDOWS} {$apptype CONSOLE} {$endif}
program MyProgram;

var
  Count, MyCount: Integer;

function CountMe: Integer;
begin
  Inc(Count); 
  Result := Count;
end;

begin
  Count := 10;
  WriteLn(CountMe);   
  MyCount := CountMe;
  WriteLn(MyCount);
end.Code language: PHP (php)

Inc 是 Pascal(FPC/Delphi)內建標準函式,功能為將變數數值加一。

var 是 Pascal 的變數宣告關鍵字,用途為定義變數。

var
  Count, MyCount: Integer;Code language: JavaScript (javascript)

var:開啟變數宣告區塊

Count, MyCount:兩個變數名稱

Integer:整數型別

本範例 var 區塊宣告的變數屬於全域變數,整支程式所有程序、函式皆可存取使用。

函式、程序與基礎原生型別

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *