3章 変数と型

 

【学習内容とねらい】

 

 本章では、「変数」について学習します。変数といっても数学の方程式に出てくる変数とはちょっと意味が違います。プログラミングの世界では、変数とは、データの記憶(格納)場所のことを指します。 ・・・ と言っても、まだピンと来ないかもしれませんね。しかし、実はすでに皆は「変数」に“遭遇”しているのです。

 

例えば、「エディット」コンポーネントの「Text」プロパティにはエディット欄に入っている“文字”が記憶されていますし、「Width」プロパティには“欄の横幅の値”が記憶されています。この意味でコンポーネントのプロパティは変数だったのです。

 

ただし、この「Textプロパティの変数」と「Widthプロパティの変数」には大きな違いがあります。というのは、Widthプロパティは「その値を2倍する」、あるいは「5を加える」などの計算(算術演算)ができるのに対し、Textプロパティには算術演算はできないからです。ですからコンピュータの中で一律に扱うことはできません。どうやら、変数はその性質に応じて“タイプ分け”しておくことが必要なようです。そこで、「変数の型」という概念が現れます。

 

以上を念頭において、本章の各節を一つ一つ確かめながら読み進んで行けば、「変数」および「変数の型」の概念を理解することができるはずです。また、自分独自の変数をプログラム中で定義して使用することもできるようになります(これを「変数の宣言」と言います)。

 

変数はプログラミングの基礎中の基礎であり、また同時に初心者がつまずきやすいところでもあります。どうか、ていねいに流れを追いながら学習して行って下さい。本章を理解すればプログラミング学習の最初の“関門”を突破したことになります。

 

 

<第3章の構成>

 


3−1  「+」演算子 (1) −「エディット」による足し算−

3−2  「+」演算子 (2) −「スピンエディット」による足し算−

3−3  データの型

3−4  型変換 (1) −整数型と文字列型の相互変換−

3−5  型変換 (2) −「エディット」による足し算の完成−

3−6  改行・空白・コメント・大文字小文字

3−7  変数 (1) −変数としての Text プロパティ−

3−8  変数 (2) −宣言して使う変数−

3−9  実数型変数

3−10 定数 (1) −整数型定数−

3−11 定数 (2) −文字列型定数−

3−12 変数と定数 (1) −「スピンエディット」を作ろう−

3−13 変数と定数 (2) −「メモ」を使ってみよう

3−14 配列変数

 


3-1 「+」演算子 (1) ―「エディット」による足し算―

【練習問題】

という状態で「足す」ボタンを押すと足し算して

と表示するプログラムを作ってみましょう。

まずはフォーム上にコンポーネントを配置して、次の画面を作ってください。

コンポーネント

Name

上のエディット

Edit1

中のエディット

Edit2

下のエディット

EditResult

ボタン

ButtonAdd

次に、ボタンを押したときの動作をプログラミングします。「ButtonAdd」の「OnClick」イベントに対するプログラム(イベントハンドラ)を書きましょう。下線部はどのように書くとよいでしょうか?

procedure TForm1.ButtonAddClick(Sender: TObject);

begin

                   :=                  +                 ;

end;

実行結果を確かめましょう。 

【練習問題】

このプログラムで、左上のエディットに「佐藤」、左中のエディットに「さん」と入れて「足す」ボタンを押すと、左下のエディットには何と表示されますか?

                

実は現段階では、14+31=45 のような数の足し算を実現できません。どうしたらいいでしょう?  ・・・  考えながら次節へ進んで下さい。

3-2 「+」演算子 (2) ―「スピンエディット」による足し算―

【基礎課題 3-1

今度は、スピンエディットに替えて足し算をさせてみましょう。フォーム上に3つのスピンエディットを次のように配置してください。

コンポーネント

Name

左上のスピンエディット

SpinEdit1

左中のスピンエディット

SpinEdit2

左下のスピンエディット

SpinEditResult

右のボタン

ButtonAdd

ボタンを押したときの動作はどのようにプログラミングするとよいでしょうか。

procedure TForm1.ButtonAddClick(Sender: TObject);

begin

                   :=                  +                 ;

end;

出来上がったら、適当な数値を入れて「足す」ボタンを押し、プログラムの動作を確かめましょう。

 

今度はうまく足し算ができたはずです。

どうやら「エディット」コンポーネントと「スピンエディット」コンポーネントには何らかの“違い”があるようです。その種明かしは次節で行いましょう。


3-3 データの型

エディットを使った足し算とスピンエディットを使った足し算が違うのは、Edit1.TextSpinEdit1.Value の「型」というものが違うためです。型には名前がつけられています。

プロパティ

型の名前

日本語名

データ形式

足し算の結果

Edit1.Text

String

文字列型

文字 (231文字まで)

14 + 31 = 1431

SpinEdit1.Value

Integer

整数型

整数(-231〜231-1まで)

14 + 31 = 45

 

【練習問題】

SpinEdit1.Value に次の値を入れて、SpinEdit1.Value整数しか受け付けないことを確かめましょう。

 

「ヘルプ」キーを使ってプロパティの型を調べられる場合もあります。ここでは、エディットの Text プロパティの型を調べてみましょう。フォーム上にエディット (Edit1) を置き、オブジェクトインスペクタで Edit1 の 「Text」 をクリックし、[F1]キーを押してみましょう。

すると、Textプロパティに対するヘルプメニューが開き、その中に下の記述があるはずです。

これは、TextプロパティがTCaption型であることを意味しています。でも、TCaption型とはどのようなものか、よく分かりませんね。そこで、さらにTCaption部分をクリックすると、TCaption型の説明が現れ、そこに次の記述を確認することができます。

これは、TCaption型がstring(文字列)型であることを示しています。こうして、TextプロパティがString(文字列)型であることが分かります。

一般に[F1]キーを使うと、該当事項に関するヘルプメニューを開くことができます。この意味で、[F1]キーは「ヘルプ」キーと呼ばれています。

【練習問題】

Edit1Width プロパティの型を調べてください。

                

ButtonAddCaption プロパティの型を調べてください。

                


3-4 型変換 (1) ―整数型と文字列型の相互変換―

【練習問題】

「エディット」では普通の足し算はできませんでしたが、「スピンエディット」ではできました。そこで、まずは「エディット」から「スピンエディット」へのコピープログラムを作ってみましょう。次のようなフォームを作ってください。

コンポーネント

Name

左のエディット

Edit1

真中のスピンエディット

SpinEdit1

右のボタン

ButtonAdd

下のようにプログラムを入力してください。

procedure TForm1.ButtonAddClick(Sender: TObject);

begin

  SpinEdit1.Value := Edit1.Text;

end;

実行してみましょう。  

すると ・・・       次ページへ進んで下さい。


'Integer''TCaption' には互換性がありません」というエラーが出てしまいます。これは、左辺と右辺の「型が合っていません」という意味のエラーです。

では、エディットからスピンエディットへのコピーはできないのでしょうか?

実は、Delphi には、文字列型の数字を整数型の数値に変換する StrToInt() という命令があります。Edit1.TextStrToInt() で包むと、データは整数型となり、SpinEdit1.Value に代入できるようになります。

【練習問題】

プログラムを次のように変更して実行してみてください。

procedure TForm1.ButtonAddClick(Sender: TObject);

begin

  SpinEdit1.Value := StrToInt(Edit1.Text);

end;

 

【基礎課題 3-4-1】

上のプログラムを改変して、逆に、スピンエディットからエディットに値を移すプログラムを作りましょう。この場合、StrToInt() ではなく IntToStr() という命令を使います。

StrToIntStringTo Integer 型 の略です。

IntToStr IntegerTo String 型 の略です。

 


3-5 型変換 (2) ―「エディット」による足し算の完成―

【基礎課題3-5-1】

当初の目的どおり、エディットを用いて

という状態で「足す」ボタンを押すと足し算を行い

と表示するプログラムを作りましょう。

 

 

と言いたいところですが・・・

3-1の【練習問題】の足し算プログラムの時のように

procedure TForm1.ButtonAddClick(Sender: TObject);

begin

  EditResult.Text := Edit1.Text + Edit2.Text;

end;

というプログラムを作っても、数値としての足し算はしてくれないのでした。

そこで、ここではまず、エディットのかわりにスピンエディットに計算させるプログラムを作ります。まずは次のようにフォームを作ってください。コンポーネントの Name プロパティは自由に付けても構いません。


今まで学んできたこと(整数型 ←→ 文字列型の変換)を用いればできます。次の順に「型変換」あるいは「足し算」処理をプログラムすれば良いでしょう。

これで当初の足し算プログラムが完成しました。

 

【基礎課題 3-5-2】

上のプログラムのフォームから右下の「スピンエディット」を削除しましょう。

そのまま実行するとエラーが出ます。エラーを出さずに今までどおりに足し算ができるよう、プログラムを変更してください。

 ヒント : (3) の処理と (4) の処理を一緒におこなってしまえば…。

 

【基礎課題 3-5-3】

さらに、残りの右の「スピンエディット」も削除しましょう。

そのまま実行するとエラーが出ます。エラーを出さずに今までどおりに足し算ができるよう、プログラムを変更してください。


3-6 改行・空白・コメント・大文字小文字

Delphi でのルール

(1)    どこで改行しても、しなくてもよい。

(2)    空白がいくつ並んでいても1つの空白とみなす。

(3)    {}で囲まれた部分、(* *)で囲まれた部分、および「//」から行末までは無視される。

(4)    大文字と小文字の区別はない。

 

(1) 次の2つのプログラムは同じものです。

 


procedure TForm1.Button1Click(Sender: TObject);

begin

  EditResult.Text:= IntToStr(StrToInt(Edit1.Text) + StrTo

end;

 


procedure TForm1.Button1Click(Sender: TObject);

begin

  EditResult.Text :=

  IntToStr(StrToInt(Edit1.Text) +

  StrToInt(Edit2.Text));

       end;

 

ただし、

procedure TForm1.Button1Click(Sender: TObject);

begin

  EditResult.Text := IntT

  oStr(StrToInt(Edit1.Text) + StrToInt(Edit2.Text));

end;

 

というように字句の途中で改行してはいけません。

 

(2) 次のプログラムは文法的には正しいプログラムです。

 

procedure TForm1.Button1Click(Sender: TObject);

begin

SpinEdit1.Value:=StrToInt(Edit1.Text  );

SpinEdit2.Value  := StrToInt(  Edit2.Text);

SpinEditResult.Value:=  SpinEdit1.Value+SpinEdit2.Value;

end;

しかし、このプログラムは、「beginend; によって囲まれた部分がプログラムである」という構造が非常にわかりにくくなっています。また、余計な空白を入れると文の意味が分かりにくくなり、誤解が生じかねません。そこで、下のように記述したらどうでしょうか?

 


procedure TForm1.Button1Click(Sender: TObject);

begin

SpinEdit1.Value := StrToInt(Edit1.Text);

SpinEdit2.Value := StrToInt(Edit2.Text);

SpinEditResult.Value := SpinEdit1.Value+SpinEdit2.Value;

end;

 

かなりすっきりするでしょう?ここで特に注意して欲しいことは、beginend; の間の行は先頭に空白を入れて先頭を揃えプログラムをみやすくする、という点です。これを「字下げ」といいます。字下げは、プログラムの体裁上のことなのでどうでもいいことの様に思うかもしれません。しかし、論理構造を視覚的に分かりやすく記述することは、ミスを減らす、あるいは作業効率を上げるという観点からも重要なことです。

 

(3) Delphi はプログラムの中に半角の「  」があると、そこから半角の「 } 」までを無視します。このことを利用して、プログラムに自由にコメントをつけることができます。また、「//」を利用することもできます。コメントには全角文字を使っても構いません。プログラムをわかりやすくするため、コメントを有効に使うようにしましょう。

 


procedure TForm1.Button1Click(Sender: TObject);

begin

  // 2数の和を求めるプログラム

SpinEdit1.Value := StrToInt(Edit1.Text); {上のEditの値}

SpinEdit2.Value := StrToInt(Edit2.Text); {中央のEditの値}

SpinEditResult.Value := SpinEdit1.Value+SpinEdit2.Value;

end;

 

 

(4)  Delphi は大文字と小文字を区別しません。つまり、「Edit1.Text」も「EDIT1.TEXT」も「edit1.text」も「eDIt1.tExT」も同じものです。ですが、見易さのため、通常は「Edit1.Text」や「SpinEdit1.Value」のように、単語の先頭は大文字にします。


3-7 変数 (1) ―変数としての Text プロパティ―

 

【練習問題】

という画面で「入れ替え」ボタンを押すと

上のエディットの Text プロパティ (攻撃) と下のエディットの Text プロパティ (守備) が入れ替わる、というプログラムを作りましょう。

 まず、次のようにフォームを作ってください。

コンポーネント

Name

左上のエディット

Edit1

左下のエディット

Edit2

右のボタン

ButtonSwap

そして[入れ替え]ボタンをクリックした時のプログラムを下のように記述してください。

procedure TForm1.ButtonSwapClick(Sender: TObject);

begin

  Edit2.Text := Edit1.Text;

  Edit1.Text := Edit2.Text;

end;

 

上下のエディットに適当な言葉を入れて実行してみましょう。うまく動きましたか?

実はこのままではうまく入れ替えができませんね。それは何がまずいのでしょうか?また、どうしたらいいでしょうか。

 

 

                                                


【基礎課題 3-7-1】

うまく入れ替えを行うためには、Edit2.Textを取り敢えず保存しておく「エディット」が必要です。次のように、データの中継用のエディットを加えてください。(Temp temporary=一時的 の略です。)

コンポーネント

Name

上のエディット

Edit1

中のエディット

Edit2

下のエディット

EditTemp

ボタン

ButtonSwap

EditTemp

 

以下の空欄を埋めてプログラムを完成させ、動作を確かめてください。

procedure TForm1.ButtonSwapClick(Sender: TObject);

begin

                                  

                                  

                                  

end;

このままでもプログラムは正しく動きますが、中継用エディットが画面に表示されるのは格好悪いですね。次の問に対して予想を立ててから、実行して確かめてみましょう。

【練習問題】

予想 EditTempWidth8 にしても正しく動くでしょうか?

1.      エラーが出て実行できない

2.      エラーは出ないが、目的通りの動作はしない

3.      エラーは出ず、目的通りの動作をする

あなたの予想は                

 

【練習問題】

予想 EditTempVisible プロパティを False にしても正しく動くでしょうか?

1.      エラーが出て実行できない

2.      エラーは出ないが、目的通りの動作はしない

3.      エラーは出ず、目的通りの動作をする

あなたの予想は               


3-8 変数 (2) ―宣言して使う変数―

Visible Falseにすると、EditTempは画面から消えてしまうので、Height Width, Colorなどのプロパティにはどんな値を入れても意味がないですね。入れ替えに必要なのは、Textプロパティだけなのです。中継用エディットを使わない、もっとよい方法はないのでしょうか。

 

ここで、新しい方法を試してみます。まずは、EditTempを削除してください。EditTempを削除したので、EditTempを中継欄に使うことはできなくなりました。そこで、今消した EditTempのかわりにもっと単純な中継欄を作ります。procedure beginの間に、次のように付け加えてください。

 

procedure TForm1.ButtonSwapClick(Sender: TObject);

var

  Temp: String;

begin

  EditTemp.Text := Edit1.Text;

  Edit1.Text := Edit2.Text;

  Edit2.Text := EditTemp.Text;

end;

 

EditTempはなくなりましたが、これで Tempという入れ物ができ、Temp EditTemp.Textのかわりをします。EditTemp.Text String型だったので、そのかわりとなる temp String型でなくてはなりません。そのため「Temp: String;」と書きます。(もし Integer型が必要なら「Temp: Integer;」と書きます。) なお、「var」は「これから (Tempのような) 入れ物を宣言 (用意) するよ」という宣言です。

これで第一段階の準備はできましたが、まだ完成ではありません。次の基礎課題に進みましょう。

 

【基礎課題 3-8-1】

Temp を使って( EditTemp.Text を使わないで)プログラムを完成させるには、どのように変更するといいでしょうか。下の空欄を埋めてプログラムを完成させて下さい。

procedure TForm1.ButtonChangeClick(Sender: TObject);

var

  Temp: String;

begin

           := Edit1.Text;

  Edit1.Text := Edit2.Text;

  Edit2.Text :=         ;

end;

 

Tempのように値を保存しておく入れ物を「変数」といいます。(入れ物への)代入によって、その値が様々に変わるからです。今の場合 Temp は画面に現れない「エディットコンポーネントのTextプロパティ」と考えて結構です。変数の名前は Tempでなくとも自由につけても構いませんが、なるべく一目見て内容がわかる名前をつけましょう。

なお、変数宣言の「var」は変数を意味する「variable」の略です。

 

コラム

 

変数の名前は原則として自由につけて構わないのですが、いくつか例外があります。

  • 英数字 (および「_) だけで作られる名前でなくてはいけない。漢字や記号・空白を含む名前はいけない。
  • 数字で始まる名前はいけない。
  • if」や「begin」など、特別な意味を持つ名前 (予約語と呼ばれます) を使ってはいけない。

Temp」という変数を用いることは、プログラムにとって必要充分な機能を提供することになります。余計なものを使わずにこうして必要充分なものを用いるようにすると、プログラムが速くなり、プログラムサイズが小さくなります。

 


【基礎課題 3-8-2】

今度はスピンエディットの入れ替えプログラムを作ってみましょう。

左のようなフォームを作ってください。

フォームができたらプログラムを書いてください。

出来上がったら、適当な数値を入れて実行してみましょう。

基礎課題 3-8-3

【基礎課題 3-5-1】で作ったプログラム

からスピンエディットおよび、ラベルも削除して下さい。

そして、変数を用いるプログラムに修正します。下線部を埋めてプログラムを完成させて下さい。

procedure TForm1.ButtonAddClick(Sender: TObject);

var

  a:          ;

  b:          ;

  c:          ;

begin

           := StrToInt(Edit1.Text);

           := StrToInt(Edit2.Text);

           :=          +         ;

  EditResult.Text := IntToStr(        );

end;

今までどおり「足し算プログラム」として動くことを確認しましょう。

 

 

 

なお、変数の宣言では、

a: Integer;

b: Integer;

c: Integer;

をまとめて

a, b, c: Integer;

a: String;

b: String;

c: String;

をまとめて

a, b, c: String;

と、複数の変数をひとまとめにして宣言することができます。

 

コラム

 

「でも、【基礎課題3-5-3】で作ったプログラムとここで作ったプログラムと、どちらも同じく動作するけど、どちらがいいの?」という疑問を持った人がいるかもしれませんね。どちらも同じく動作するから、どちらでもいいのです。

「だけど、実行したときの速さは違うんじゃない? 【基礎課題3-5-3】で作ったプログラムの方が、命令が1行ですっきりしているから速いと思います。」なかなか鋭い質問ですね。ですが、実行する速さも同じなのです。

実は Delphi は、【基礎課題3-5-3】で作ったプログラムもここで作ったプログラムも本質的に同じものであることを理解しています。その意味で、両者は同等なプログラムなのです。

しかし、後からプログラムを見たときには、一つの式に一度にまとめて記述するよりも、こちらの様に変数を用いた方が分かりやすいということは言えます。一般に、インプットデータや、計算の答など、何らかの意味を持つ値については、いったん、変数を定義してそこに代入しておいた方が分かりやすく、また後に拡張等を行う際にもより容易になる傾向があります。

 


3-9 実数型変数

【練習問題】

【基礎課題 3-8-3】を再利用して、

というように2つの数を入れて「平均」ボタンを押すと

平均値が求まる、というプログラムを作ります。ボタンの表示は「平均」に変更しておいてください。

次に、イベントハンドラを変更します。2つの数の平均は、合計を2で割って求めるのですね。プログラムを次のように書き換えてください。(書き換える部分は下線部です。)

procedure TForm1.ButtonAddClick(Sender: TObject);

var

  a: Integer;

  b: Integer;

  c: Integer;

begin

  a := StrToInt(Edit1.Text);

  b := StrToInt(Edit2.Text);

  c := (a + b) / 2;

  EditResult.Text := IntToStr(c);

end;

実行してみましょう。エラーが出て止まってしまいましたね。

これは、割り算「(a + b) / 2」の結果は一般に小数になるのに、その小数の結果を c という整数型の変数に代入しようとしたことが原因です。

【基礎課題 3-9-1

このエラーを回避するため、c を整数型の変数ではなく小数を受け付ける型の変数にしてしまいましょう。小数を受け付ける型は実数型と呼ばれ、「Real」と表します。プログラムを以下のように修正してください。

procedure TForm1.ButtonAddClick(Sender: TObject);

var

  a: Integer;

  b: Integer;

  c: Real;

begin

  a := StrToInt(Edit1.Text);

  b := StrToInt(Edit2.Text);

  c := (a + b) / 2;

  EditResult.Text := FloatToStr(c);

end;

なお、FloatToStr() とは、実数型から文字列型への変換を行う命令です。

型変換の命令は、次のものがあります。必要になったらこのページを参照してください。

整数型から文字列型へ

IntToStr()

文字列型から整数型へ

StrToInt()

実数型から文字列型へ

FloatToStr() 又は
FloatToStrF() (小数点以下の表示桁数を調整する場合)

文字列型から実数型へ

StrToFloat()

整数型から実数型へ

(命令がなくても自動的に変換される)

実数型から整数型へ

Ceil(), Floor(),  Round(), Trunc()
(状況に応じて使い分ける。詳しくはヘルプを見ること。)

 

以上の「変換命令」使用法の詳細については、Delphiの「ヘルプ」メニュを参照して下さい。

 

 

 

 

以下にDelphiでよく用いられる算術演算子をまとめておきます。

演算

加算

減算

乗算

除算

剰余

表記

div

mod

※ 「a div babで割った時の商を与えます。演算結果(例)は次の通り。

     11 div 3 → 3     11 div 5 2

※ 「a mod b」はabで割った時の余りを与えます。演算結果(例)は次の通り

11 mod 3 → 2    11 mod 5 → 1    12 mod 4 → 0

 

 

【基礎課題 3-9-2】

3つの数の平均を求めるプログラムを作ってください。

 

【基礎課題 3-9-3

下のようなフォームをもつ、分数を小数にするプログラムを作ってください。

注意


3-10 定数 (1) ―整数型定数―

 

【基礎課題 3-10-1】

今は午後3時だとします。

「換算」ボタンを押したら

午後の時刻の12時間表記から24時間表記を求める、というプログラムを作ってみましょう。

下の下線部には何と書いたらいいでしょうか。

procedure TForm1.ButtonAddClick(Sender: TObject);

begin

  SpinEditResult.Value := SpinEdit1.Value +         ;

end;

 

※ コンポーネントのNameプロパティを次のようにしています。

上のスピンディット

SpinEdit1

下のスピンエディット

SpinEditResult

ボタン

ButtonKansan

 

【基礎課題 3-10-2】

上のプログラムに手を加え、下2桁の西暦略記から4桁の西暦表記を求めるプログラムを作ってください。ただし、西暦2000年以降とします。

 

 

12や2000のように、いつも決まった値であるものを「定数」といいます。この定数とは対照的に、変数は、代入によってその内容(値)が変わります。


3-11 定数 (2) ―文字列型定数―

左上の欄に女性の名前を入れてボタンを押すと

頭に「Miss」とつけるプログラムを作ります。

     実はMissやMr.などの呼称は名字(姓)につけるもので、名前にこれをつけるのは英語としては不自然なのですが、ここでは気にしないでください。

 

まずはフォームにコンポーネントを配置してください。

コンポーネント

Name

左上のエディット

Edit1

左下のエディット

Edit2

右のボタン

ButtonMiss

 

【練習問題】

あとは「敬称付け」ボタンのイベントハンドラを書くだけです。下線部には何が入ると思いますか?

procedure TForm1.ButtonMissClick(Sender: TObject);

begin

  Edit2.Text :=              + Edit1.Text;

end;

実行してみましょう。

次ページへ


下線部に単に「Miss」と入れて実行すると、「未定義の識別子 : 'Miss'」というエラーが出て止まってしまったと思います。これは、「Miss っていうのは変数 (か何か) のつもりだろうけど、どこにも用意されていないよ」という意味のエラーです。

Miss は変数じゃない、単なる文字列 (定数) なんだ」ということを Delphi に伝えるには、「'Miss'」と書きます。つまりアポストロフィ「’」で囲みます

【練習問題】

プログラムを次のように修正して実行してみましょう。

procedure TForm1.ButtonMissClick(Sender: TObject);

begin

  Edit2.Text := 'Miss' + Edit1.Text;

end;

 

 

【基礎課題 3-11-1】

次のように「さん」づけするプログラムを作りましょう。

 

 

【基礎課題 3-11-2

ボタンを押すと「Hello, Delphi.」と表示するプログラムを作ってください。

 

【応用課題 3-11-A】

次のように来年が何年か教えてくれるプログラムを作りましょう。

今年の年を入力した画面

来年の年が表示された画面

 


3-12 変数と定数 (1) ―「スピンエディット」を作ろう―

【基礎課題 3-12-1】

「▲」ボタンを押すと

「エディット」の中身が1つ増える、という「スピンエディット」のようなプログラムを「エディット」と「ボタン」だけで作ってみましょう。

コンポーネント

Name

左のエディット

Edit1

右のボタン

ButtonInc

まずはフォームにコンポーネントを配置しましょう。

Edit1 はそのままでは数値の計算ができないので、整数型変数 a を用意し、

(1)      Edit1 から a に値を代入

(2)      a の値を1増やす

(3)      a から Edit1 に値を代入

の順に処理するようにしましょう。下線部を埋めてプログラムを完成させて下さい。

procedure TForm1.ButtonIncClick(Sender: TObject);

var

  a:             ;

begin

  a := StrToInt(Edit1.Text);

  a :=             ;

  Edit1.Text := IntToStr(a);

end;

実行してみましょう。

※ このプログラムがすんなりできたら大したもの!あなたは「代入」の意味をよく理解していることになります。

 

【基礎課題 3-12-2】

上のプログラムを、値が1ずつ増えるのではなく、2ずつ増えるように変更しましょう。


3-13 変数と定数 (2) ―「メモ」を使ってみよう―

メモと呼ばれるコンポーネントを使ってみましょう。メモはを使ってフォームに配置することが出来ます。

下のようなフォームのプログラムを作ってください。

【練習問題】

オブジェクトインスペクタで Memo1 を選んで ScrollBarsssNone から ssBoth に変えると、プログラムはどのように変わりますか?

                                                        

WordWrap プロパティを False にすると、何が変わりますか? (ヒント:実行中にメモに大量の文章を入力すると違いが分かります。)

                                                         

 

【基礎課題 3-13-1】

Lines プロパティの値を変えて、プログラムを実行したとき、メモに

虹と雪のバラード
晴れたらいいね
白い恋人達

と表示されるようにしましょう。


【練習問題】

下のように、左のメモに情報が入っている状態で、「何行目」を指定して「取り出す」ボタンを押すと

 

その内容が右下のエディットに取り出される、というプログラムを作ってみましょう。

まずは、フォームの上に次のようにコンポーネントを配置します。

コンポーネント

Name

左のメモ

MemoMain

右上のスピンエディット

SpinEditGet

右のボタン

ButtonGet

右下のエディット

EditEachLine

 

次に、プログラムを書きます。MemoMain の各行は、

MemoMain.Lines.Strings[行番号]

という形でアクセスすることができます。次のプログラムを作成して下さい。

 

procedure TForm1.ButtonGetClick(Sender: TObject);

begin

  EditEachLine.Text := MemoMain.Lines.Strings[SpinEditGet.Value];

end;


注意 メモの各行は、最初が0行目、次が1行目、その次が2行目、というように順序がつけられています(0行目から始まっています)。

 

コラム

 

他の Delphi の教科書を読んでみると、

MemoMain.Lines.Strings[2]

ではなく

MemoMain.Lines[2]

という記述を用いていることがあります。本来の書き方は前者なのですが、Delphi はどちらの書き方でも同じ物と解釈するので、より簡単な後者の表記が用いられることが多いようです。ただ、Delphiの兄弟分であるC++Builderでは、後者の(省略した)記述が認められません。そこで、C++Builderを学習する際に混乱が起きないように、ここでは、本来の書き方で説明しました。

 

【基礎課題 3-13-2】

 

上の【練習問題】を改良しましょう。下の状態で「送り込む」ボタン(NameプロパティをButtonPutとします)を押すと

 

指定された場所に情報を送り込む(内容が更新される)、というプログラムを作って下さい。

 

ここに、新たに付加したスピンエディットとボタンのNameプロパティは次に様にしてください。

 

 [送り込む]ボタン     : ButtonPut

 2行目のスピンエディット : SpinEditPut

 

3行目に「北の国から」、4行目に「ロマンスの神様」を送り込んでみてください。プログラムはどのように動作しましたか?

 

・・・

 

4行目以降には情報が入らないですね。 → コラム参照

 

 

 

 

 


コラム

 

このプログラムで、7行目や10行目など、4行目以降に情報を送り込もうとしても、うまく行きません。これは、現在存在していない行へのアクセスをメモが許してないからなのです。

「では、100行の情報を書き込むためには、各行にアクセスできるよう、メモにあらかじめ100行の無駄なデータを書き込んでおかなくてはならないのか?」 という疑問ももっともです。

実は、Memo には Add() という、行を付け足す命令があります。プログラムを次のように変更すると、ボタンを押すたびに行が増えていきます。

procedure TForm1.ButtonPutClick(Sender: TObject);

begin

  MemoMain.Lines.Add(EditEachLine.Text);

end;


3-14 配列変数

フォームにメモを置くだけで MemoMain.Lines.Strings[0], MemoMain.Lines.Strings[1], MemoMain.Lines.Strings[2], …が利用できるようになったように、普通の変数も1行の宣言だけでいくつもの入れ物を用意することができます。

 

【基礎課題 3-14-1】

【基礎課題 3-13-2】からメモを削除し、その代わりとなる変数を使って同じプログラムを作りましょう。MemoMain.Lines.Strings[0]MemoMain.Lines.Strings[1],・・・の代わりに、Data[0]Data[1]、・・・という新しい変数を導入することにします。変数名Dataは適当に付けた変数名です。

まずは、【基礎課題 3-13-2】のプログラムから MemoMainを削除し、代わりにプログラムコードの上の方に次の下線部を挿入してください。

 


type
  TForm1 = class(TForm)
  SpinEditGet: TSpinEdit;
  Label1: TLabel;
  ButtonGet: TButton;
  EditEachLine: TEdit;
  SpinEditPut: TSpinEdit;
  Label2: TLabel;
  ButtonPut: TButton;
  procedure ButtonGetClick(Sender: TObject);
  procedure ButtonPutClick(Sender: TObject);
private
  { Private 宣言 }
public
  { Public 宣言 }
  Data: Array of String;
end;
 
 

これで、Data[0], Data[1], Data[2], …というように、いくつもの文字列型変数を使う準備 (の第1段階) が出来ました。このときの 0, 1, 2, … を添え字といいます。そして、このように添え字がつく変数を配列変数と呼びます。

でも、…, Data[100], Data[101], Data[102], と続いていって、添え字はどこまで使えるようになっているのでしょうか (メモリをどれだけ準備しているでしょうか)?

実は、「配列 (の要素) が実際に何個必要か」は、プログラムの中で指示してやる必要があります。フォームに次のようにボタン (NameプロパティをButtonSetSizeとします) を配置し、そのイベントハンドラに次のように書いて下さい。

 

 

 

procedure TForm1.ButtonSetSizeClick(Sender: TObject);

begin

  SetLength(Data, 100);

end;

これで、100個の変数 Data[0], Data[1], Data[2], , Data[99]が用意されました。もし変数の数が100個で足りなくなった場合も、同じ命令で変数の数を増減させることが出来ます。

では、プログラム本体部分を変更して、メモがないこのプログラムが正しく動くようにしましょう。空欄部分は自分で埋めて下さい。

 


procedureTForm1.ButtonGetClick(Sender: TObject);

begin

  EditEachLine.Text := Data[SpinEditGet.Value];

end;

 


procedureTForm1.ButtonPutClick(Sender: TObject);

begin

                       := EditEachLine.Text;

end;

 

では、実行して動作を確認してみましょう。

最初に「100個用意」ボタンを押して下さい。これで100個の変数が使えるようになります。(押し忘れると、1個の変数も使えるようにならないため、エラーが発生します。)

 

1.        「睦月」という文字列を「0」行目へ「送り込む」。

2.        「如月」という文字列を「1」行目へ「送り込む」。

3.        0」行目から文字列を「取り出す」と「睦月」と表示される。

4.        「むつき」という文字列を「0」行目へ「送り込む」。

5.        1」行目から文字列を「取り出す」と「如月」と表示される。

6.        0」行目から文字列を「取り出す」と「むつき」と表示される。

 

正しく動きましたか? 


テキスト ボックス: コラム 動的配列変数と静的配列変数
配列変数を宣言する際に、

Data: Array of String;

ではなく

Data: Array[0..99] of String;

と書くことがあります。これは静的配列変数と呼ばれ、この1行だけで Data[0]〜Data[99] が利用可能になりますが、一度用意した変数の個数を後から変更することは出来ません。一方、先ほどの配列変数は、プログラム実行中でも変数の個数を変更することが出来るため、動的配列変数と呼ばれます。

静的配列変数では、「最大で100個の変数が必要になりそうだ」と思ったら最初から100個用意 (宣言) しなくてはいけないため非効率なプログラムになりやすく、万一プログラム実行中に101個以上の変数が必要になっても打つ手がありません。動的配列変数であれば、その時に必要な個数分だけ変数を用意することが出来、効率的です(ただし、動的配列変数は動作が遅くなることがあります。)。