関数・手続きと基本プリミティブ型

前回の授業の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); // 小数第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 lines compiled, 0.0 sec, 39248 bytes code, 2484 bytes data

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); // 小数2桁に制限
end. // 末尾の end.(ドット付き)でプログラム全体の終了を示すCode language: PHP (php)

各関数・手続きには begin と end が一組存在し、関数本体の開始と終了を表す。C/C++/JAVAの { } に相当する

WriteLn はコンソールに内容を出力し、シングルクォート ‘ ‘ は文字列リテラルを表す。WriteLn(‘A + 10 =:’, A + 10); は文字列 A + 10 =: と式の計算結果 A + 10 を順に出力する

プログラムには一番外側の beginとend. が1組だけ存在し、内部に他の関数・手続きを呼び出すメインコードを記述する

X := 15 / 5;
WriteLn(‘X is now: ‘, X); // 指数表記
WriteLn(‘X is now: ‘, X:1:2); // 小数2桁

/ は浮動小数除算で、商も浮動小数となる

最初の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}:プログラムをコンソールアプリとして指定(黒いウィンドウが起動、GUIウィンドウアプリではない)。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になるまで自身を再帰呼び出し、0になった時点で関数を抜ける。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)標準組み込み関数、変数の値を1増加させる。

var はPascalの変数宣言キーワード、変数を定義する役割。

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

var:変数宣言ブロック開始

Count, MyCount:2つの変数名

Integer:整数型

上記例のvar内で宣言した変数はグローバル変数で、プログラム内の全ての手続き・関数から参照可能

関数・手続きと基本プリミティブ型

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です