ということで、Javaに続いてまた何となく Delphiを始めてみました(何となくというのもおかしいのですが、実際のところDelphiの知識が特に必要とされているわけでもないですし、ちょっと興味がある程度、趣味の範囲でDelphiを始めたという意味では「何となく」になるでしょうか)。
今回使用したコンパイラ・開発環境はBorland社の「Delphi 6 Personal」です。 これは使用者登録等の簡単な手続きが必要になりますが、フリーでダウンロードできます。 ここではインストールの説明などは特にしません。
Javaに関してはC系の言語であるので、言語仕様自体の習得はそれほど難しいものではなかったのですが、Delphiは今まで使ったことのない Pascal系の言語(Object Pascal)であるので最初からかなり手こずりました。 他の言語と比較しつつ基本的なところから勉強していくことにします。
最初はHello, world!
何はなくとも、最初のプログラムは「Hello, world!」と決まっているので、コンソールアプリでこれを表示してみます。 「新規作成」メニューの「その他」をクリックし、表示されたダイアログから「コンソール」をクリックして、コンソールアプリケーション用のプロジェクトを生成します。 DelphiはよくVisual Basicと比較されますが、Delphiにはコンソールアプリを作れないと思いこんでいたので驚きです。 VBでもコンソールアプリが作れれば良かったのですが・・・
program HelloWorld;
{$APPTYPE CONSOLE}
uses
SysUtils;
begin
{ TODO -oUser -cConsole Main : ここにプログラムコードを書いてください }
Writeln('Hello, world!');
Writeln('This is first delphi program.');
end.
Hello, world! This is first delphi program.
このプログラムの大半はテンプレートとして提供されたものです。 実際に追加したのは11,12行目だけです。 プログラムの詳細はこの次で説明するとして、ひとまず「Hello, world!」が無事表示されたことを喜ぶことにします。
Object Pascal のプログラム構造
といっても、「Hello, world!」が表示されただけではどうしようもないので、Object Pascalにおけるプログラムの構造はどのようなものなのかを見てみます。

Object Pascalではこのようなプログラム構造になっています。 これはVBと言うよりはC/C++の構造に似ていると言えます。 続いて、部分毎に説明していきます。
まず、プログラムヘッダでプログラムの名前を決めます。 この名前とファイル名は一致している必要があります。 また、コンパイル命令などもここに記述します。 これはprogram文の前にあっても問題ないようです。
続いて、プログラムブロックですが、これはさらに細かいブロックに分かれます。 最初に来るuses文では使用するユニットを記述します。 ユニットとはヘッダーのようなもので、ヘッダーのインクルードや名前空間のインポートなどと似たようなことを行います。 続く変数宣言部ではvar文により変数を宣言します。 宣言すべき変数がない場合は省略できます。
最後にプログラム本体を記述します。 begin から end で囲まれる部分が Main関数 に相当する部分です。 Main関数以外の関数・手続き(プロシージャ)を記述するにはこの部分より上に記述する必要があります。
Object Pascal の文法
構造がわかったところで文法について見てみます。
{$APPTYPE CONSOLE}
program HelloWorld;
uses
SysUtils;
var
// 変数宣言部
i: integer; // integer型の宣言
j, k: integer;
begin
// メイン関数に相当する部分
{
コメント文
中括弧でくくられた部分がコメントとされる
中括弧に続いて$マークをつけるとコンパイラに対する命令文となる
例えばプログラム最初にある$APPTYPEなど
}
(*
これもコメント文
{}と同じような働き
*)
// C++スタイルのコメント
i := 3; // 代入の例
j :=
5; // 複数行にまたがっていても問題ない
k := i + j; i := 1; // 複数文含まれていても問題ない
// printf(), WriteLine(), println()に相当する手続き(プロシージャ)
Writeln( 'i = ', i );
Writeln( 'j = ', j );
Writeln( 'k = ', k );
{ 終了メッセージを表示 }
Write( 'Press any key to continue' );
Readln;
end.
i = 1 j = 5 k = 8 Press any key to continue
まず、コメントとなる部分は緑色に変えておきました。 コメントは様々な種類があります。 VB、C++と同じ感覚で使えるコメントが「//(ダブルスラッシュ)」です。 コメント文でコンパイル命令を記述することができます。 プログラムの一番はじめに記述した部分がコンパイル命令です。
Object Pascalでは大文字と小文字は区別されません。 つまり、「Integer」も「integer」も「INTEGER」も、そしてもちろん「iNtEgEr」なども同じと見なされます。 VBでは大文字小文字の区別はされなくとも自動的に単一の表記になるように調整されました。 しかし、 Delphiでは調整されることはありません。
文の終わりにはC/C++同様「;(セミコロン)」を付けます。 また、代入は「=」ではなく「:=」で行います。 VB, C/C++での代入は「=」で、C/C++で等価を表す「==」はObject Pascalでは「=」になります。 ここが注意すべきことだと思います。
また、 'と' の間が文字列リテラルになります。 文字列リテラル中にこのクォーテーションを含めたい場合はVBと同じように「''」と二つ続けることで一つのクォーテーションとして扱われます。 さらに、関数・プロシージャ呼び出しで渡すべき引数がないときは「Readln()」のように括弧を残してはならず、「Readln」としなければなりません。
最後に、変数の宣言なのですが、変数の宣言は必ずvar文で行わなければなりません。 それ以外の部分でローカル変数を宣言したりすることはできません。 ただし、プロシージャ・関数レベルで変数を宣言することはできます。
標準入出力
簡単な文字列型変数を使って標準入出力で入出力をしてみます。
program HelloWorld;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
yourName: String;
begin
Write( 'Please type your name here: ' );
Readln( yourName );
Writeln( 'Hello, ' + yourName + '.' );
{ 終了メッセージを表示 }
Write( 'Press any key to continue' );
Readln;
end.
Please type your name here: santa marta Hello, santa marta. Press any key to continue
Write, Writelnは.NET FrameworkのConsole.Write, Console.WriteLineに相当するプロシージャです。 ReadlnもReadLineに相当するものです。 しかし、入力された文字列は戻り値ではなく引数に渡されます。 文字列を連結する際にはVBのように & ではなく + を用いることができます。
ちなみに、一番最後にあるReadlnは何らかの入力があるまで終了させないためのものです。 これを省くと名前を入力した瞬間に目にもとまらぬ速さでコンソールが閉じてしまいます。
算術演算
算術演算は基本的には他の言語とは大差ありません。
program HelloWorld;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
modValue, divValue: Integer;
begin
Writeln( '算術演算のサンプル' );
Writeln( '3 + 5 = ', 3 + 5 );
Writeln( '3 - 5 = ', 3 - 5 );
Writeln( '3 * 5 = ', 3 * 5 );
Writeln( '3 / 5 = ', 3 / 5, ' = ', FloatToStr( 3 / 5 ) );
Writeln( '切捨てと四捨五入' );
Writeln( '5 / 3 = ', FloatToStr( 5 / 3 ) );
Writeln( '5 / 3 = ', Trunc( 5 / 3 ) );
Writeln( '5 / 3 = ', Round( 5 / 3 ) );
Writeln( '商と剰余' );
divValue := 5 div 3;
modValue := 5 mod 3;
Writeln( '5 ÷ 3 = ', divValue, '…', modValue );
Writeln( '偶数・奇数' );
Writeln( '2 is odd: ', Odd( 2 ) );
Writeln( '3 is odd: ', Odd( 3 ) );
{ 終了メッセージを表示 }
Write( 'Press any key to continue' );
Readln;
end.
算術演算のサンプル 3 + 5 = 8 3 - 5 = -2 3 * 5 = 15 3 / 5 = 6.00000000000000E-0001 = 0.6 切り捨てと四捨五入 5 / 3 = 1.66666666666667 5 / 3 = 1 5 / 3 = 2 商と剰余 5 ÷ 3 = 1…2 偶数・奇数 2 is odd: FALSE 3 is odd: TRUE Press any key to continue
/ 演算子は除算を行いますが、オペランドが整数でもその結果は実数型になります。 FloatToStr関数はその名の通り、浮動小数点の数値を文字列に変換します。 ただし、指数表記ではなく読みやすい表記に変えてくれます。 Trunc関数は小数部を切り捨て、Round関数は小数部を丸めて整数に変換します。 div及びmodは商と剰余を求める演算子です。 VBの\とModに相当するものといえます。 Odd関数はその整数が奇数であるかを Boolean値で返します。
その他の算術演算
平方根、べき乗、対数などの算術演算も他の言語とあまり変わりません。 ただし、これらの関数を利用する場合はMathユニットをuses文に含める必要があります。
program HelloWorld;
{$APPTYPE CONSOLE}
uses
SysUtils,
Math;
var
sinValue, cosValue, tanValue: Extended;
begin
Writeln( '平方: 1.732050807 ^ 2 = ', Sqr( 1.732050807 ) );
Writeln( '平方根: √2 = ', Sqrt( 2 ) );
Writeln( 'べき乗: 2 ^ 3 = ', Power( 2, 3 ) );
Writeln( '常用対数' );
Writeln( ' Log10(100) = ', Log10( 100 ) );
Writeln( '自然対数' );
Writeln( ' Ln(2.718281828) = ', Ln( 2.718281828 ) );
Writeln( '2を底とした対数' );
Writeln( ' Log2(256) = ', Log2( 256 ) );
Writeln( 'nを底とした対数' );
Writeln( ' Log5(125) = ', LogN( 5, 125 ) );
Writeln( 'Pi関数: π=', Pi );
Writeln( 'Sin, Cos, Tan' );
Writeln( ' Sin(π/4) = ', Sin( Pi / 4 ) );
Writeln( ' Cos(π/3) = ', Cos( Pi / 3 ) );
Writeln( ' Tan(π/6) = ', Tan( Pi / 6 ) );
Writeln( ' Sin(60) = ', Sin( DegToRad( 60 ) ) );
Writeln( ' Cos(30) = ', Cos( DegToRad( 30 ) ) );
Writeln( ' Tan(45) = ', Tan( DegToRad( 45 ) ) );
Writeln( 'SinCosプロシージャ' );
SinCos( DegToRad( 60 ), sinValue, cosValue );
tanValue := sinValue / cosValue;
Writeln( ' Sin(60) = ', sinValue );
Writeln( ' Cos(60) = ', cosValue );
Writeln( ' Tan(60) = ', tanValue );
{ 終了メッセージを表示 }
Write( 'Press any key to continue' );
Readln;
end.
算術演算のサンプル 3 + 5 = 8 3 - 5 = -2 3 * 5 = 15 3 / 5 = 6.00000000000000E-0001 = 0.6 切り捨てと四捨五入 5 / 3 = 1.66666666666667 5 / 3 = 1 5 / 3 = 2 平方: 1.732050807 ^ 2 = 2.99999999802935E+0000 平方根: √2 = 1.41421356237310E+0000 べき乗: 2 ^ 3 = 8.000000000000000E+0000 常用対数 Log10(100) = 2.000000000000000E+0000 自然対数 Ln(2.718281828) = 9.99999999831127E-0001 2を底とした対数 Log2(256) = 8.00000000000000E+0000 nを底とした対数 Log5(125) = 3.00000000000000E+0000 Pi関数: π= 3.14159265358979E+0000 Sin, Cos, Tan Sin(π/4) = 7.07106781186548E-0001 Cos(π/4) = 5.00000000000000E-0001 Tan(π/4) = 5.77350269189626E-0001 Sin(60) = 8.66025403784439E-0001 Cos(60) = 8.66025403784439E-0001 Tan(60) = 1.00000000000000E+0000 SinCosプロシージャ Sin(60) = 8.66025403784439E-0001 Cos(60) = 5.00000000000000E-0001 Tan(60) = 1.73205080756888E+0000 Press any key to continue
注意すべきことは、Sqrが平方を求め、Sqrtが平方根を求める関数であるということです。 双方非常に似た名前なので注意が必要です。 また、特殊なプロシージャにSinCosがあります。 これはあるラジアン値の正弦と余弦を同時に求めるというものです。 ヘルプによるとSinとCosを一度ずつ呼び出すよりは高速に動作するそうです。 ちなみに、Extended型は拡張精度実数型と呼ばれるもので、これらの関数の戻り値はExtended型になっています。
for文
for文の動作自体は他の言語とほとんど変わりありません。 ただ、カウンタ変数の増分は±1に固定されています。 Stepを利用したりすることができないので、それ以外の値は指定できません。 表記自体はVBのFor文と非常に似ています。
program HelloWorld;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
i, j: integer;
begin
for i := 0 to 9 do
begin
Write( i, ' ' );
end;
Writeln;
for i := 9 downto 0 do
begin
Write( i, ' ' );
end;
Writeln;
for i := 0 to 4 do
begin
for j := 0 to 4 do
begin
Write( '(', i, ', ', j, ') ' );
end;
Writeln;
end;
{ 終了メッセージを表示 }
Write( 'Press any key to continue' );
Readln;
end.
0 1 2 3 4 5 6 7 8 9 9 8 7 6 5 4 3 2 1 0 (0, 0) (0, 1) (0, 2) (0, 3) (0, 4) (1, 0) (1, 1) (1, 2) (1, 3) (1, 4) (2, 0) (2, 1) (2, 2) (2, 3) (2, 4) (3, 0) (3, 1) (3, 2) (3, 3) (3, 4) (4, 0) (4, 1) (4, 2) (4, 3) (4, 4) Press any key to continue
カウンタをインクリメントする場合はtoを用い、ディクリメントする場合はdowntoを用います。 繰り返す文をdoに続けて記述します。 繰り返す文が一行の場合はdoの後にそのまま記述し、複数行の場合はbeginとendの間に記述します。 この記述方法はC/C++に似ていると言えます。 また、二重ループなどをすることもできます。
while文, repeat文
while文は他の言語同様、前置条件判断の無限ループ、repeat文は後置条件判断の無限ループです。 for文で1以外の増分を指定したいときはwhile/repeatを使うことができます。
program HelloWorld;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
i: integer;
begin
i := 10;
while 0 < i do
begin
Write( i, ' ' );
i := i - 2;
end;
Writeln;
i := 12;
repeat
Write( i, ' ' );
i := i - 3;
until i < 0;
Writeln;
{ 終了メッセージを表示 }
Write( 'Press any key to continue' );
Readln;
end.
10 8 6 4 2 12 9 6 3 0 Press any key to continue
while文はfor文同様beginからendまでのブロックを、条件式の値が真の間繰り返します。 逆に、repeat文は条件式が真になるまで(式が偽の間)繰り返します。 repeat文ではブロック構造を成さず、repeatからuntilまでを繰り返します。 これもまたfor文同様に入れ個にして二重ループを形成することもできます。
if文
例によってif文も他の言語と大差ありません。 ただ、前述の通り、等価を表す演算子にはVB同様 = 演算子を用います。 また、一つだけ注意として、「elseはそれ単体では文になり得ない」ということからelseの前には ;(セミコロン) をつけません。 つけてしまうと構文エラーになります。
program HelloWorld;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
i, j: integer;
s: string;
begin
for i := 1 to 9 do
begin
for j := 1 to 9 do
begin
if i = j then
Write( ' ' )
else
begin
s := IntToStr( i * j );
SetLength( s, 3 );
Write( s );
end;
end;
Writeln;
end;
{ 終了メッセージを表示 }
Write( 'Press any key to continue' );
Readln;
end.
2 3 4 5 6 7 8 9 2 6 8 10 12 14 16 18 3 6 12 15 18 21 24 27 4 8 12 20 24 28 32 36 5 10 15 20 30 35 40 45 6 12 18 24 30 42 48 54 7 14 21 28 35 42 56 63 8 16 24 32 40 48 56 72 9 18 27 26 45 54 63 72 Press any key to continue
まずはじめにif文意外の注意点として、SetLengthは配列要素の長さを指定するものですが、この例のように文字列に対しても有効です。 つまり、文字列の長さを設定することができます。 この例では3バイト(Object Pascalの文字列はAsciiとして扱われるため。ちなみにVBはUnicode。)に設定して書式を併せています。
if文ではVBのEnd Ifに相当するものはありません。 形式的にはC/C++に似たものと言えます。 ただし、条件式を()でくくる必要はありません。 また、for文同様に、実行する文が一行だけの場合はbegin-endブロックを作る必要がありません。 else ifはこの次の例で使用します。
break, continue
Object Pascalではbreakとcontinueが採用されています。 その用法はC/C++と同じです。
program HelloWorld;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
i: integer;
begin
for i := 1 to 9 do
begin
if (i = 1) or (i = 4) or (i = 6) then
continue
else if i = 8 then
break;
Write( i, ' ' );
end;
Writeln;
{ 終了メッセージを表示 }
Write( 'Press any key to continue' );
Readln;
end.
2 3 5 7 Press any key to continue
この例を見てわかるとおり else if の前であっても ;(セミコロン) をつけてはいけません。 continueとbreakがC/C++と同じ動作であることは実行結果を見れば納得がいくと思います。
case文
case文はswitch文やSelect Caseステートメントと同じような働きを持つ構文です。 caseは値の分類には用いられません。
program HelloWorld;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
i: integer;
begin
for i := 0 to 9 do
begin
case i of
0, 1, 4, 6, 8, 9: Writeln( i, 'は素数ではない' );
2,
3,
5,
7: Writeln( i, 'は素数である' );
end;
end;
Writeln;
{ 終了メッセージを表示 }
Write( 'Press any key to continue' );
Readln;
end.
0は素数ではない 1は素数ではない 2は素数である 3は素数である 4は素数ではない 5は素数である 6は素数ではない 7は素数である 8は素数ではない 9は素数ではない Press any key to continue
この例では二つの表記方法を使っていますが、どちらでも問題ないと言うことだけを示している以外は特に意味はありません。 case文は「case 値 of」というように用います。 また、breakなどを用いなくても下の文に流れていくことがないので、動作はVBのSelect Caseステートメントに似ていると言えます。 case文の終わりにはend;をつけます。
さらに、複数の連続した値や、いずれの値にも当てはまらない場合などを記述することもできます。
program HelloWorld;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
s: string;
i: integer;
begin
for i := 0 to 9 do
begin
case i of
0..4:
s := ' is less than 5.';
5:
s := ' equals to 5.';
else
s := ' is greater than 5';
end;
Writeln( i, s );
end;
Writeln;
{ 終了メッセージを表示 }
Write( 'Press any key to continue' );
Readln;
end.
0 is less than 5. 1 is less than 5. 2 is less than 5. 3 is less than 5. 4 is less than 5. 5 equals to than 5. 6 is greater than 5. 7 is greater than 5. 8 is greater than 5. 9 is greater than 5. Press any key to continue
配列(静的配列)
配列という要素はほとんどの言語に存在しますが、Object Pascalにおける配列の動作はVBに近く、表記方法などはC++に似ています。
program HelloWorld;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
arr: array[0..4] of integer;
upperBound, lowerBound: integer;
i: integer;
begin
arr[0] := 2;
arr[1] := 3;
arr[2] := 5;
arr[3] := 7;
arr[4] := 11;
lowerBound := Low( arr );
upperBound := High( arr );
Writeln( 'Lower bound of arr is ', lowerBound );
Writeln( 'Upper bound of arr is ', upperBound );
Writeln( 'Values of array.' );
for i := lowerBound to upperBound do
begin
Writeln( ' arr[', i, '] = ', arr[i] );
end;
Writeln( 'Out of range.' );
for i := lowerBound - 3 to lowerBound - 1 do
begin
Writeln( ' arr[', i, '] = ', arr[i] );
end;
for i := upperBound + 1 to upperBound + 3 do
begin
Writeln( ' arr[', i, '] = ', arr[i] );
end;
{ 終了メッセージを表示 }
Write( 'Press any key to continue' );
Readln;
end.
Lower bound of arr is 0 Upper bound of arr is 4 Values of array. arr[0] = 2 arr[1] = 3 arr[2] = 5 arr[3] = 7 arr[4] = 11 Out of range arr[-3] = 9372868 arr[-2] = 9372920 arr[-1] = 0 arr[5] = 4 arr[6] = 0 arr[7] = 0 Press any key to continue
宣言方法は見ての通りです。 「arrはinteger型の配列(添え字0〜4)」のように読むことができます。 Low関数とHigh関数は配列の下限と上限を取得するものです。 VBにおけるLBound関数とUBound関数に相当するものといえます。 また、配列の長さを求めるLength関数というものも存在します。
配列への値の代入と参照は特に問題ないのですが、興味深いことに、配列の添え字の範囲外の部分を参照しようとしてもエラーにはなりませんでした。 ただ、その値は必ずしも初期化されていない意味不明な数値です。
配列(動的配列)
Object Pascalには動的に長さを変えられる動的配列も存在します。
program HelloWorld;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
arr: array of integer;
upperBound, lowerBound: integer;
i: integer;
begin
SetLength( arr, 10 );
lowerBound := Low( arr );
upperBound := High( arr );
Writeln( 'Length of arr is ', Length( arr ) );
Writeln( 'Lower bound of arr is ', lowerBound );
Writeln( 'Upper bound of arr is ', upperBound );
for i := lowerBound to upperBound do
begin
arr[i] := i;
end;
for i := lowerBound to upperBound do
begin
Writeln( 'arr[', i, '] = ', arr[i] );
end;
SetLength( arr, 5 );
lowerBound := Low( arr );
upperBound := High( arr );
Writeln( 'Length of arr is ', Length( arr ) );
Writeln( 'Lower bound of arr is ', lowerBound );
Writeln( 'Upper bound of arr is ', upperBound );
for i := lowerBound to upperBound do
begin
Writeln( 'arr[', i, '] = ', arr[i] );
end;
{ 終了メッセージを表示 }
Write( 'Press any key to continue' );
Readln;
end.
Length of arr is 10 Lower bound of arr is 0 Upper bound of arr is 9 arr[0] = 0 arr[1] = 1 arr[2] = 2 arr[3] = 3 arr[4] = 4 arr[5] = 5 arr[6] = 6 arr[7] = 7 arr[8] = 8 arr[9] = 9 Length of arr is 5 Lower bound of arr is 0 Upper bound of arr is 4 arr[0] = 0 arr[1] = 1 arr[2] = 2 arr[3] = 3 arr[4] = 4 Press any key to continue
宣言直後には長さがなく、値が割り当てられていないので、SetLengthによって配列に長さを設定します。 また、長さを変えるときもSetLenghtを用います。