GO BACK

Delphi教室 その2


「ソースコードと値の基本」


■ソースコードを分解してみる


 ・・さて。これから、ソースコードを理解し、文法などを覚え、少しずつDelphiのプログラミングを覚えていくわけですが、その前に1つだけ重要な注意をしておきます。これは、Delphiを学ぶ上で非常に大切なことです。

  全てを一度に理解しようと思わないこと!

 ・・これです。Delphiは非常に奥深い言語です。Visual Basicなどと違い、「あなたがいじれるのはここまで。ここから先は触れません」というものがありません。深く追求しようとすればいくらでも踏み込んでいけるのです。また、そうした「ある程度理解しないといじれない部分」が、ソースコードの中にむき出しで入っており、それがビギナーを戸惑わせる要因にもなっています。「これ、何だろ?」「これはどういう意味だ?」ということを細々と気にしていくと、全く先に進めなくなってしまうんですね。

 ですので、とりあえず慣れない内は、使い方だけ理解すれば十分、と割り切って先へ進むようにして下さい。その原理とか概念とかをいちいち追求していくと、すぐに落ちこぼれてしまいます。まずは、実際に使えるようになるのが最優先! 概念とか原理などは、ある程度Delphiが使えるようになり、全体の仕組みがわかるようになってから少しずつ考えるようにするのがいいでしょう。

 では、今回の話に進みましょう。――前回、ボタンを押してメッセージを表示するというごくごくシンプルなプロジェクトを作ってみました。これで、一応プログラム作成の手順はわかった感じですが、まだまだわからないことはたくさんあります。その代表とも言えるのが、ソースコードです。

 前回、作成したプロジェクトで、エディタウィンドウにある全ソースコードがどうなっているか調べてみましょう。だいたい、こんなものが書かれているはずです。

 


unit Unit1;


interface


uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
  Dialogs, StdCtrls;


type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;


var
  Form1: TForm1;


implementation


{$R *.dfm}
 


procedure TForm1.Button1Click(Sender: TObject);
begin
	ShowMessage('Hello!');
end;


end.

 

 ――なんだかずいぶんと難しそうでしょう? このうち、私たちが実際にちょっとだけ手を加えたりして使ってみたのは、青字で表示されている部分だけです。他は、全てDelphiが自動的に生成したものだったわけですね。まず、このソースコードがどういう仕組みになっているのか、その概略を頭に入れておきましょう。

 このソースコードを、それぞれの役割などごとに整理しまとめると、こんな感じになるでしょう。

 


unit ユニット名; 
←プログラム(?)の名前
interface
 
uses
      ・・・ここに使用するライブラリの宣言が書かれる・・・; 
ここは、一般に公開される
ものの定義や宣言が書かれる
 
type
      ・・・ここに作成したフォームに関する宣言が書かれる・・・;  
 
var
      ・・・全体で使用する変数の宣言・・・;
implementation
 
{$R *.dfm}
←コンパイラ指令
  触っちゃダメ! 
 
procedure ○○;
begin
      ・・・ルーチンその1の中身・・・
end; 
ここに、具体的に実行する
ルーチンの中身などが書かれる
 
procedure ××;
begin
      ・・・ルーチンその2の中身・・・
end; 
 
・・・必要なだけルーチンを書く・・・

        
end.

 

 これで、もうちょっとわかりやすくなりましたか? 要するに、Delphiのソースコードというのは、「interface」〜「implementation」〜「end.」という3つの単語により、2つの部分に分けられている、と考えれば良いでしょう。

 最初の「interface」から「implementation」まで(グリーンの部分)は、ここで必要な様々なものの宣言などがまとめて書かれています。これらの多くはDelphiが自動的に作成するため、私たちは、「自分で新たにルーチンを定義して追加する」なんてことをしない限り、あまり触ることはありません。まあ、最初の内はほとんど使わない部分と考えていいでしょう。

 その後の「implementation」から「end.」まで(ピンクの部分)が、私たちが一番活用する部分です。ここに、さまざまなルーチン(まとめて実行される一連の処理部分、かな? 要するに、このルーチンという単位でプログラムは書かれるわけ)を書き込むことでプログラムを作っていきます。Delphiのルーチンは、だいたい以下のような形で書きます。



procedure ルーチン名 ( パラメータとか ); 他に必要なものを書くこともある  

begin

	・・・ここに実行する命令を順番に書いていく・・・
end;
 

 

 つまり、最初に「procedure ○○」と書いて「○○ってルーチンの定義だよ」ということを示し、その後のbeginからendまでの間に実行する命令を書くわけですね。このことから、このひとかたまりになってるルーチンをDelphiでは「プロシージャ」とか「手続き」と呼びます。

 先に、ボタンの「OnClick」ってイベントを設定した時のことを思い出してみましょう。あれは、値部分をダブルクリックすると自動的に「Button1Click」って名前のプロシージャが作成されていたんですね。そしてOnClickイベントに、そのプロシージャ名が設定された。そうすることで、「このOnClickイベントが起きたら、このプロシージャを呼び出す」ということが設定されていたわけなんですね。

 Delphiのプログラミングの基本は、この繰り返しです。必要なイベントに、それが発生した時呼び出されるプロシージャを割り付け、そこに実行する命令を書く。それをひたすらくり返していけば、立派なアプリケーションができるわけです。とりあえず、interface部分は脇において、この「プロシージャ」というものをきちんと書けるようになるのが、最初の目標と考えていいでしょう。

 

■プロパティと変数


 さて、ソースコードの基本的な流れがわかったところで、実際にコンポーネントを使ったプログラムを作っていきましょう。コンポーネントというのは、前にも触れましたが「プロパティ」と「イベント」を設定することで利用します。このことは、実はプログラムの内部でも同じです。つまり、コンポーネントのプロパティを変更したり取り出したりすることで、コンポーネントを操作したりできるのですね。

 とりあえず、簡単なサンプルを作ってみましょう。――新たにプロジェクトを用意し、そこに「Label」「Edit」「Button」という3種類のコンポーネントをそれぞれ1つずつ作ってみて下さい。Labelはテキストを表示するためのコンポーネント、Editはテキストを入力するためのコンポーネントです。

 作成したら、オブジェクトインスペクタを使って、LabelとButtonの「Caption」プロパティ、Editの「Text」プロパティを変更しましょう。以下の図のように表示されるようになればOKです。

 わかりますか? 赤い円でかこっている2つのアイコンが、LabelとEditです。プロパティの変更の仕方は、前回Buttonでやったからだいたいわかるでしょう。――フォームが出来上がったら、例によってButton1の「OnClick」イベントをダブルクリックして、プロシージャを割り付けます。そして、以下のようにプロシージャを記述して下さい。


procedure TForm1.Button1Click(Sender: TObject);   
var
	str1: String;

begin
	str1 := Edit1.Text;
	ShowMessage('こんちは、' + str1 + 'ちゃん!');
end;

 

 ちょっとわかりにくいですか? 前回のように、単にbeginとendの間に書く、というわけにはいきませんよ。beginの前に「var 〜」というものが追加されています。OnClickイベントで自動作成されたプロシージャをよく見て、間違えないように記述しましょう。

 これでプロジェクトを実行してみましょう。そしてテキスト入力のフィールド(Eidtコンポーネント)に名前を書き込んでボタンをクリックしてみると、書き込んだ名前を使ってメッセージが表示されますよ。

 ここでは、「コンポーネントのプロパティを利用する」「変数を使う」「メッセージを画面に表示する」といったことを行なっています。これらについて、簡単に説明していきましょう。

 

・文の区切りについて

まず、何よりも最初に「ソースコードは、1つ1つの文から成り立っている」ことをよく覚えておきましょう。。そして、Delphiでは「文の終わりは改行ではなくセミコロン(;)で区切られる」こともしっかり理解しておいて下さい。1つの文を書いたら、必ず最後に;記号をつけます。これを忘れるとエラーになりますので注意しましょう。

 

・変数の利用について

変数とは、さまざまな値を一時的に保存しておける入れ物みたいなものですね。プログラムを書く時、まず必要な値を変数に入れて、それを操作したりするわけで、変数はプログラミングのもっとも基本となる要素といっていいでしょう。Delphiでは、変数を利用する際、いくつかの決まりごとがあります。それは以下のようなものです。

・使用する前に、変数の使用宣言をして「この変数を使いますよ」と教えておくこと。
・変数への値の代入は、:=記号を使って行なうこと。
・変数には、原則として同じタイプの値しか入れられない。タイプが異なるものは入れられないと考えよう。

  いくつかわからないこともあるでしょうから補足していきましょう。――まず、変数の使用宣言からです。先ほど書いたプロシージャをよく見て下さい。beginの前に、こんなものがありますね?

var
	str1: String;

 これが、変数の使用宣言です。プロシージャの中で変数を使う場合、この「var」というものの後に、使用したい変数を記述していきます。これは基本的に、

変数名 : 変数のタイプ;

――このような形で記します。ここでは「Stringというタイプの変数str1」を宣言していたというわけですね。同じタイプの変数を複数用意する時は、カンマで続けて記述することもできます。例えば、

var
	str1,str2,str3: String;

――こんな具合で書けば、str1,str2,str2という3つのString型変数が使えるようになるわけです。また、いくつもの変数を宣言したい場合は、変数の宣言を続けて書いて、

var
	str1,str2: String;
	num1,num2: Integer;

こんな感じで宣言すれば、それらの変数がプロシージャの中で使えるようになります。・・あ、上の「Integer」ってのは整数のタイプを示す単語です。

 ここまで読んで、「変数のタイプってのは何なのか?」っていう疑問が当然わいてくるでしょう。これは、「収めることのできる値の種類」だと考えて下さい。Delphiでは、値には様々な種類があります。例えば、テキスト、整数、実数、キャラクタ・・という具合に、値の示す内容や性質ごとにいくつものタイプに分かれているのです。Delphiに限らず、たいていのプログラミング言語では、このように値のタイプというのが何種類か用意されていて、タイプの異なるものどうしを計算したりするには注意を払う必要があるのです。(タイプについてはこの後で説明します)

 実際に変数を利用するのは簡単です。:=記号を使って「○○ := ××」というように記述すると、右辺の値を左辺のものに代入します。例えば「A := 1」なんてやれば、変数Aに1を代入できるわけですね。もちろん、Aが整数のタイプの変数であれば、ですけれど。

 ここで、「えっ、Visual Basicには値のタイプなんてなかったぞ?」と思う人もいるかも知れません。VBでは、変数の宣言なんてしなくても変数を使えますし、タイプなんて考えなくても別に問題なく値をやり取りできます。これは、実はVBの内部で自動的に値のタイプを変換したりしているため、一見するとタイプがないように見えるのです。

 が、こうした「VBの便利さ」が、VBの性能を悪くしているんですね。内部でこっそり変数のタイプの変換などの作業を行なうため、VBのプログラムは非常に遅くなっています。逆にいえば、市販されているアプリケーションのように高品質のプログラムを作るための言語では、みんな変数のタイプと値のやり取りをしっかりと把握して記述するようになっているのが当たり前なのだ、といってよいでしょう。また、型がないように見えても、VBの内部ではもちろん厳格に値のタイプが存在していますから、ある程度以上のことをやろうとすると結局タイプをきちんと把握してプログラムを書かなければならなくなります。タイプについてきちんと理解していないと、ここで「なんで?」ということになってしまうでしょう。ですから、ちょっと面倒でややこしいように思えるでしょうが、「変数とタイプ」については、早い段階で慣れておくことを強くお勧めします。

 

・変数のタイプについて

というわけで、実際にどんなタイプがあるのか、主なものだけざっと紹介しておきましょう。といっても、実はDelphiには非常にたくさんのタイプがあるのです。例えば整数だけでも数種類、テキストでも数種類、というように、1つの種類の値にいくつものタイプが用意されているんですよ。

 ですから、まずはもっとも基本となるもの1つだけを覚えておくようにしましょう。

・テキストのタイプ
これは「String」というものを使います。テキストは、Delphiでは両端をシングルクォート(')でくくって記します。ですから「A := 'ABC'」というように書くわけですね。またテキストは+記号でいくつもつなげることができます。「A := 'ABC' + 'XYZ'」なんてやれば、ABCXYZというテキストをAに代入できるわけです。

・整数のタイプ
これは「Integer」というものを使うのが一般的です。 整数は、やはり:=記号で代入できますし、演算記号で式を書いて、その結果を代入したりできます。例えば「A := 1 + 2」なんてやれば、答えの3が代入されるわけです。利用可能な演算記号としては「+」「-」「*」「/」記号、そして()などが使えます。また、割算については「div」「mod」というものもあります。これは、それぞれ割算の整数部分および余り部分を計算するものです。例えば「10 div 3」とすれば3が、「10 mod 3」とすれば1がそれぞれ得られます。

・実数のタイプ
これは「Double」というものが一般的でしょう。実数は、プログラミング言語の世界では「だいたいこのぐらい」という感じで扱われます。要するに、完璧な精度で値を記憶することができず、「だいたい何桁ぐらいまで保証はするけど、それより細かいのは切り捨てちゃうかもよ」てな扱いになってるんです。Doubleの場合、だいたい15〜16桁ぐらいまでは正確です。また、演算や値の代入などは整数と基本的に同じです。演算記号なども全く違いはありません。

・文字のタイプ
文字列は一続きの文字をまとめて扱いますが、これとは別に「1文字だけの値」を扱うためのものがあります。それが文字型です。これは通常、「Char」というタイプを用います。文字型の値は、テキストと同様、シングルクォートで前後を括って表します。例えば「A := 'X'」てな感じです。まぁ、この文字型の値というのは、実際に必要になってみないとどういう使い方をするのかわからないでしょう。ですから今は気にしなくていいです。

・真偽値のタイプ
これは「Boolean」というものを使います。真偽値っていうのは、平たくいえば「正しいか、正しくないか」といった二者択一の値のことです。プログラミングの世界では、何かの式を設定し、それが成立するかしないかをチェックするようなことがよくあります。こうした場合に真偽値は用いられます。また、プロパティでも「画面に表示するかどうか」というように二者択一の値はけっこうありますが、こうしたものでも真偽値は用いられます。このBooleanの変数では、「True」「False」という、あらかじめ用意されている2つの値だけが代入できます。それ以外のものは一切入れられません。

 

・プロパティの利用について

サンプルのプロシージャでは、Editコンポーネントに書かれたテキストを利用してメッセージを表示していました。このEditコンポーネントでは、「Text」というプロパティで表示したテキストを設定していました。つまり、Textプロパティを使えば、現在のEditのテキストを調べたり、変更したりできるのですね。

 Delphiのプログラミングは、このように「コンポーネントのプロパティを取り出したり書き換えたりする」ことでコンポーネントを操作し、動かしていきます。――プロパティの値というのは、以下のような形で記述します。

コンポーネント名 . プロパティ名

 コンポーネント名の後にプロパティ名をドットでつなげて書けばいいわけですね。サンプルのプロシージャを見ると、「str1 := Edit1.Text」なんて実行していました。これで、Edit1のTextプロパティを、変数str1に収めていたわけです。同様に、「Edit1.Text := 'Hello'」なんてやれば、Edit1の表示テキストを変更することだってできるのです。

 また、このことからもわかるように、プロパティにも「値のタイプ」が決められています。例えば、Textプロパティならば、Stringの値なのです。ですから、整数などをそのままTextに設定したりはできません。プロパティを覚える時には、あわせて「このプロパティは何のタイプの値か?」についても考えるようにしましょう。

 

・メッセージの表示について

サンプルでは、テキストをメッセージウィンドウで表示していました。これはShowMessageという命令で行ないます。非常に簡単なものですので、ちょっとしたメッセージを表示するのに重宝しますよ。使い方は簡単で、

ShowMessage( テキスト );

このように、表示したいテキスト(Stringの値)を()内に記すだけです。ここでは、「ShowMessage('こんちは、' + str1 + 'ちゃん!」なんて書いてありますけど、こんな具合に式や変数を記すこともできます。要するに、その結果の値がテキストであれば問題ないわけです。

 

■整数とテキストのタイプ変換


 では、値と変数、プロパティの基礎が頭に入ったところで、今度は数字を使った簡単なサンプルを作ってみましょう。先ほどのサンプルで作ったButton1Clickプロシージャをそのまま書き換えて利用してみましょう。


procedure TForm1.Button1Click(Sender: TObject);
var
	str1,str2: String;
	num1: Integer;


begin
	str1 := Edit1.Text;
	num1 := StrToInt(str1);
	num1 := num1 * num1;
	str2 := IntToStr(num1);
	ShowMessage(str1 +'の二乗は、' + str2 + 'です。');  
end;


 

 これが修正したプロシージャです。これは、入力した数字の二乗を計算して表示するというプログラムです。できあがったらプロジェクトを実行し、整数を書き込んでからボタンをクリックしてみましょう。その二乗がメッセージとして表示されますよ。

 ここでの最大の問題点は、「数字とテキストの間をいかにやりとりするか」でしょう。先に述べたように、Textプロパティの値はテキストです。これを使って計算するには、まずテキストを整数に変換し、それから計算をして、計算結果をまたテキストに変換する、といった作業が必要です。

 こうしたタイプの変換のことを「キャスト(型変換)」と呼びます。Delphiの場合、専用の関数を使ってキャストするのが一般的です。とりあえず「テキスト」と「整数」の間で変換する関数を覚えておきましょう。

・テキスト→整数
整数の変数 := StrToInt( テキスト );

・整数→テキスト
テキスト変数 := IntToStr( 整数 );

 これが、キャストのための関数です。どちらもそう複雑なものでないですから、わかることでしょう。これらを使い、テキストと数字の間を変換していけば、入力したテキストを使って計算をすることもできるようになるのです。

 ただし! これではまだ完璧とはいえません。なぜなら「数字に変換できないテキストが入力されたらどうなるか?」を考慮していないからです。例えば「ABC」なんて入力してボタンをクリックしたら一体どうなるでしょう? これはいくらStrToInt関数を使っても数字にはできませんよね?

 こうした場合、Delphiでは「例外」と呼ばれるエラーが発生します。そこで、こうした例外が発生した時のために、「例外処理」というものを使って命令を書くようにするのが一般的です。


procedure TForm1.Button1Click(Sender: TObject);
var
	str1,str2: String;
	num1: Integer;


begin
	try
		str1 := Edit1.Text;
		num1 := StrToInt(str1);
		num1 := num1 * num1;
		str2 := IntToStr(num1);
		ShowMessage(str1 +'の二乗は、' + str2 + 'です。');  
	except
		ShowMessage('整数を入力して!');
	end;
end;

 

 これが例外処理を行なった修正版ソースコードです。この例外処理というのは、「try」「except」「end」という3つの単語で間を挟んで記述します。ざっとこんな感じです。

 try
  ・・・例外が発生しそうな処理を書く・・・ 
 except
  ・・例外が発生した時の処理・・
 end;

 これで、try以降で例外が発生すると、プログラムはその場でexcept部分にジャンプし、そこにある処理を実行してからend;以降に抜けていきます。――といっても、Personal版では、Delphi上で「実行」メニューで動作確認しても、エラーが起きると「ソースコードが見つからない」うんぬんのエラーメッセージが現れます。詳しい説明は省きますが、Delphi上では例外が起きるとデフォルトでデバッガに落ちるようになってる関係で、こうしたエラーが現れます。コンパイルして作成されたEXEでは、ちゃんと例外発生時にはtryがキャッチしてexceptの処理が実行されるようになるので心配はいりません。

 ・・まあ、例外とか構文とかまだよくわからないでしょうが、とりあえず「テキスト→数字」という実行に失敗する可能性のある処理を行なう時には、このtry〜except〜endという構文を使って書くのだ、ということだけ頭に入れておくと良いでしょう。

 


GO NEXT


GO HOME