【学習内容とねらい】
本章では、「変数」について学習します。変数といっても数学の方程式に出てくる変数とはちょっと意味が違います。プログラミングの世界では、変数とは、データの記憶(格納)場所のことを指します。 ・・・ と言っても、まだピンと来ないかもしれませんね。しかし、実はすでに皆は「変数」に“遭遇”しているのです。
例えば、「エディット」コンポーネントの「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 配列変数
|
という状態で「足す」ボタンを押すと足し算して |
|
と表示するプログラムを作ってみましょう。 |
まずはフォーム上にコンポーネントを配置して、次の画面を作ってください。
コンポーネント |
Name |
上のエディット |
Edit1 |
中のエディット |
Edit2 |
下のエディット |
EditResult |
ボタン |
ButtonAdd |
次に、ボタンを押したときの動作をプログラミングします。「ButtonAdd」の「OnClick」イベントに対するプログラム(イベントハンドラ)を書きましょう。下線部はどのように書くとよいでしょうか?
void __fastcall TForm1::ButtonAddClick(TObject *Sender);
{
= + ;
}
実行結果を確かめましょう。
このプログラムで、左上のエディットに「佐藤」、左中のエディットに「さん」と入れて「足す」ボタンを押すと、左下のエディットには何と表示されますか?
実は現段階では、14+31=45 のような数の足し算を実現できません。どうしたらいいでしょう? ・・・ 考えながら次節へ進んで下さい。
今度は、スピンエディットに替えて足し算をさせてみましょう。フォーム上に3つのスピンエディットを次のように配置してください。
コンポーネント |
Name |
左上のスピンエディット |
CSpinEdit1 |
左中のスピンエディット |
CSpinEdit2 |
左下のスピンエディット |
CSpinEditResult |
右のボタン |
ButtonAdd |
ボタンを押したときの動作はどのようにプログラミングするとよいでしょうか。
void __fastcall TForm1::ButtonAddClick(TObject *Sender);
{
= + ;
}
出来上がったら、適当な数値を入れて「足す」ボタンを押し、プログラムの動作を確かめましょう。
今度はうまく足し算ができたはずです。
どうやら「エディット」コンポーネントと「スピンエディット」コンポーネントには何らかの“違い”があるようです。その種明かしは次節で行いましょう。
エディットを使った足し算とスピンエディットを使った足し算が違うのは、Edit1->Text と SpinEdit1->Value の「型」というものが違うためです。型には名前がつけられています。
プロパティ |
型の名前 |
日本語名 |
データ形式 |
足し算の結果 |
Edit1->Text |
AnsiString 型 |
文字列型 |
文字 (231文字まで) |
14 + 31 = 1431 |
CSpinEdit1->Value |
int 型 |
整数(-231〜231-1まで) |
14 + 31 = 45 |
CSpinEdit1->Value に次の値を入れて、CSpinEdit1->Value は整数しか受け付けないことを確かめましょう。
「ヘルプ」キーを使ってプロパティの型を調べられる場合もあります。ここでは、エディットの
Text
プロパティの型を調べてみましょう。フォーム上にエディット (Edit1) を置き、オブジェクトインスペクタで Edit1 の 「Text」 をクリックし、[F1]キーを押してみましょう。
すると、次のようなTextプロパティに対するヘルプメニューが開きます。
枠内の記述から、TextプロパティがAnsiString(文字列)型であることが分かります。
一般に[F1]キーを使うと、該当事項に関するヘルプメニューを開くことができます。この意味で、[F1]キーは「ヘルプ」キーと呼ばれています。
Edit1 の Width プロパティの型を調べてください。
ButtonAdd の Caption プロパティの型を調べてください。
「エディット」では普通の足し算はできませんでしたが、「スピンエディット」ではできました。そこで、まずは「エディット」から「スピンエディット」へのコピープログラムを作ってみましょう。次のようなフォームを作ってください。
コンポーネント |
Name |
左のエディット |
Edit1 |
真中のスピンエディット |
CSpinEdit1 |
右のボタン |
ButtonAdd |
下のようにプログラムを入力してください。
void __fastcall TForm1::ButtonAddClick(TObject *Sender);
{
CSpinEdit1->Value = Edit1->Text;
}
実行してみましょう。
すると ・・・ 次ページへ進んで下さい。
「 'AnsiString' 型は 'long' 型に変換できない 」というエラーが出てしまいます。これは、左辺と右辺の「型が合っていません」という意味のエラーです。
![]() |
![]() |
では、エディットからスピンエディットへのコピーはできないのでしょうか?
実は、Delphi には、文字列型の数字を整数型の数値に変換する StrToInt() という命令があります。Edit1->Text を StrToInt() で包むと、データは整数型となり、SpinEdit1->Value に代入できるようになります。
![]() |
![]() |
プログラムを次のように変更して実行してみてください。
void __fastcall TForm1::ButtonAddClick(TObject *Sender);
{
CSpinEdit1->Value = StrToInt(Edit1->Text);
}
上のプログラムを改変して、逆に、スピンエディットからエディットに値を移すプログラムを作りましょう。この場合、StrToInt() ではなく IntToStr() という命令を使います。
StrToInt は String 型 To Integer 型 の略です。
IntToStr は Integer 型 To String 型 の略です。
当初の目的どおり、エディットを用いて
|
という状態で「足す」ボタンを押すと足し算を行い |
|
と表示するプログラムを作りましょう。
|
と言いたいところですが・・・
3-1の【練習問題】の足し算プログラムの時のように
void __fastcall TForm1::ButtonAddClick(TObject *Sender);
{
EditResult->Text = Edit1->Text + Edit2->Text ;
}
というプログラムを作っても、数値としての足し算はしてくれないのでした。
そこで、ここではまず、エディットのかわりにスピンエディットに計算させるプログラムを作ります。まずは次のようにフォームを作ってください。コンポーネントの Name プロパティは自由に付けても構いません。
今まで学んできたこと(整数型 ←→ 文字列型の変換)を用いればできます。次の順に「型変換」あるいは「足し算」処理をプログラムすれば良いでしょう。
これで当初の足し算プログラムが完成しました。
上のプログラムのフォームから右下の「スピンエディット」を削除しましょう。
そのまま実行するとエラーが出ます。エラーを出さずに今までどおりに足し算ができるよう、プログラムを変更してください。
ヒント : (3) の処理と (4) の処理を一緒におこなってしまえば…。
さらに、残りの右の「スピンエディット」も削除しましょう。
そのまま実行するとエラーが出ます。エラーを出さずに今までどおりに足し算ができるよう、プログラムを変更してください。
C++Builder でのルール
(1) どこで改行しても、しなくてもよい。
(2) 空白がいくつ並んでいても1つの空白とみなす。
(3) 「/*」と「*/」で囲まれた部分、および「//」から行末までは無視される。
(4) 大文字と小文字を区別する。
(1) 次の2つのプログラムは同じものです。
![]() |
void __fastcall TForm1::Button1Click(TObject *Sender);
{
EditResult->Text = IntToStr(StrToInt(Edit1->Text) + StrTo…
}
![]() |
void __fastcall TForm1::Button1Click(TObject *Sender);
{
EditResult->Text =
IntToStr(StrToInt(Edit1->Text) +
StrToInt(Edit2->Text));
}
ただし、
void __fastcall TForm1::Button1Click(TObject *Sender);
{
EditResult->Text = IntT
oStr(StrToInt(Edit1->Text) + StrToInt(Edit2->Text));
}
というように字句の途中で改行してはいけません。
(2) 次のプログラムは文法的には正しいプログラムです。
void __fastcall TForm1::Button1Click(TObject *Sender);
{
SpinEdit1->Value = StrToInt(Edit1->Text );
SpinEdit2->Value = StrToInt( Edit2->Text);
SpinEditResult->Value = SpinEdit1->Value + SpinEdit2->Value;
}
しかし、このプログラムは、「{ と } によって囲まれた部分がプログラムである」という構造が非常にわかりにくくなっています。また、余計な空白を入れると文の意味が分かりにくくなり、誤解が生じかねません。そこで、下のように記述したらどうでしょうか?
void __fastcall TForm1::Button1Click(TObject *Sender);
{
SpinEdit1->Value = StrToInt(Edit1->Text);
SpinEdit2->Value = StrToInt(Edit2->Text);
SpinEditResult->Value = SpinEdit1->Value + SpinEdit2->Value;
}
かなりすっきりするでしょう?ここで特に注意して欲しいことは、{ と } の間の行は先頭に空白を入れて先頭を揃えプログラムをみやすくする、という点です。これを「字下げ」といいます。字下げは、プログラムの体裁上のことなのでどうでもいいことの様に思うかもしれません。しかし、論理構造を視覚的に分かりやすく記述することは、ミスを減らす、あるいは作業効率を上げるという観点からも重要なことです。
(3) C++Builder はプログラムの中に半角の「 /* 」があると、そこから半角の「 */ 」までを無視します。このことを利用して、プログラムに自由にコメントをつけることができます。また、「//」を利用することもできます。コメントには全角文字を使っても構いません。プログラムをわかりやすくするため、コメントを有効に使うようにしましょう。
![]() |
void __fastcall TForm1::Button1Click(TObject *Sender);
{
// 2数の和を求めるプログラム
SpinEdit1->Value = StrToInt(Edit1->Text); /*上のEditの値*/
SpinEdit2->Value = StrToInt(Edit2->Text); /*中央のEditの値*/
SpinEditResult->Value = SpinEdit1->Value + SpinEdit2->Value;
}
(4) C++Builder は大文字と小文字を区別します。ですから、「Edit1->Text」と「EDIT1->Text」や「edit1->text」などは、全て異なるものとして認識されます。このため、最初の内は、「Edit1->Text」のつもりで、「edit1->Text」などと記述してエラーになることがよくあります。注意してください。C++Builderはコンポーネントやプロパティの名前は通常「Edit1->Text」や「SpinEdit1->Value」のように、単語の先頭を大文字にするようになっています。
|
という画面で「入れ替え」ボタンを押すと |
|
上のエディットの Text プロパティ (攻撃) と下のエディットの Text プロパティ (守備) が入れ替わる、というプログラムを作りましょう。 |
まず、次のようにフォームを作ってください。
コンポーネント |
Name |
左上のエディット |
Edit1 |
左下のエディット |
Edit2 |
右のボタン |
ButtonSwap |
そして[入れ替え]ボタンをクリックした時のプログラムを下のように記述してください。
void __fastcall TForm1::ButtonSwapClick(TObject *Sender);
{
Edit2->Text = Edit1->Text;
Edit1->Text = Edit2->Text;
}
上下のエディットに適当な言葉を入れて実行してみましょう。うまく動きましたか?
実はこのままではうまく入れ替えができませんね。それは何がまずいのでしょうか?また、どうしたらいいでしょうか。
うまく入れ替えを行うためには、Edit2.Textを取り敢えず保存しておく「エディット」が必要です。次のように、データの中継用のエディットを加えてください。(Tempは temporary=一時的 の略です。)
コンポーネント |
Name |
上のエディット |
Edit1 |
中のエディット |
Edit2 |
下のエディット |
EditTemp |
ボタン |
ButtonSwap |
EditTemp
以下の空欄を埋めてプログラムを完成させ、動作を確かめてください。
void __fastcall TForm1::ButtonSwapClick(TObject *Sender);
{
}
このままでもプログラムは正しく動きますが、中継用エディットが画面に表示されるのは格好悪いですね。次の問に対して予想を立ててから、実行して確かめてみましょう。
予想 EditTemp の Width を 8 にしても正しく動くでしょうか?
1. エラーが出て実行できない
2. エラーは出ないが、目的通りの動作はしない
3. エラーは出ず、目的通りの動作をする
あなたの予想は 。
予想 EditTemp の Visible プロパティを False にしても正しく動くでしょうか?
1. エラーが出て実行できない
2. エラーは出ないが、目的通りの動作はしない
3. エラーは出ず、目的通りの動作をする
あなたの予想は 。
Visibleを Falseにすると、EditTempは画面から消えてしまうので、Heightや Width, Colorなどのプロパティにはどんな値を入れても意味がないですね。入れ替えに必要なのは、Textプロパティだけなのです。中継用エディットを使わない、もっとよい方法はないのでしょうか。
ここで、新しい方法を試してみます。まずは、EditTempを削除してください。EditTempを削除したので、EditTempを中継欄に使うことはできなくなりました。そこで、今消した EditTempのかわりにもっと単純な中継欄を作ります。次のように下線部を付け加えてください。
void __fastcall TForm1::ButtonSwapClick(TObject *Sender);
{
AnsiString Temp;
EditTemp->Text = Edit1->Text;
Edit1->Text = Edit2->Text;
Edit2->Text = EditTemp->Text;
}
EditTempはなくなりましたが、これで Tempという入れ物ができ、Tempが EditTemp.Textのかわりをします。EditTemp.Textは AnsiString型だったので、そのかわりとなる Tempも AnsiString型でなくてはなりません。そのため「AnsiString Temp;」と書きます。(もし int型が必要なら「int Temp;」と書きます。) このように、プログラム中で用いる変数の変数名およびその型を指定することを、「変数の宣言」と呼びます。
これで第一段階の準備はできましたが、まだ完成ではありません。次の基礎課題に進みましょう。
Tempを使って(EditTemp->Textを使わないで)プログラムを完成させるには、どのように変更するといいでしょうか。下の空欄を埋めてプログラムを完成させて下さい。
void __fastcall TForm1::ButtonSwapClick(TObject *Sender);
{
AnsiString Temp;
= Edit1->Text;
Edit1->Text = Edit2->Text;
Edit2->Text = ;
}
Tempのように値を保存しておく入れ物を「変数」といいます。(入れ物への)代入によって、その値が様々に変わるからです。今の場合 Temp は画面に現れない「エディットコンポーネントのTextプロパティ」と考えて結構です。変数の名前は Tempでなくとも自由につけても構いませんが、なるべく一目見て内容がわかる名前をつけましょう。
コラム
変数の名前は原則として自由につけて構わないのですが、いくつか例外があります。
|
「Temp」という変数を用いることは、プログラムにとって必要充分な機能を提供することになります。余計なものを使わずにこうして必要充分なものを用いるようにすると、プログラムが速くなり、プログラムサイズが小さくなります。
今度はスピンエディットの入れ替えプログラムを作ってみましょう。
|
左のようなフォームを作ってください。 |
フォームができたらプログラムを書いてください。
出来上がったら、適当な数値を入れて実行してみましょう。
【基礎課題 3-5-1】で作ったプログラム
からスピンエディットおよび、ラベルも削除して下さい。
そして、変数を用いるプログラムに修正します。下線部を埋めてプログラムを完成させて下さい。
void __fastcall TForm1::ButtonAddClick(TObject *Sender);
{
a; //変数の宣言
b;
c;
= StrToInt(Edit1->Text);
= StrToInt(Edit2->Text);
= + ;
EditResult->Text = IntToStr( );
}
今までどおり「足し算プログラム」として動くことを確認しましょう。
なお、変数の宣言では、
int a; int b; int c;
|
をまとめて |
int a, b, c; |
AnsiString a; AnsiString b; AnsiString c;
|
をまとめて |
AnsiString a, b, c: |
と、複数の変数をひとまとめにして宣言することができます。
コラム
「でも、【基礎課題3-5-3】で作ったプログラムとここで作ったプログラムと、どちらも同じく動作するけど、どちらがいいの?」という疑問を持った人がいるかもしれませんね。どちらも同じく動作するから、どちらでもいいのです。 「だけど、実行したときの速さは違うんじゃない? 【基礎課題3-5-3】で作ったプログラムの方が、命令が1行ですっきりしているから速いと思います。」なかなか鋭い質問ですね。ですが、実行する速さも同じなのです。 実は Delphi は、【基礎課題3-5-3】で作ったプログラムもここで作ったプログラムも本質的に同じものであることを理解しています。その意味で、両者は同等なプログラムなのです。 しかし、後からプログラムを見たときには、一つの式に一度にまとめて記述するよりも、こちらの様に変数を用いた方が分かりやすいということは言えます。一般に、インプットデータや、計算の答など、何らかの意味を持つ値については、いったん、変数を定義してそこに代入しておいた方が分かりやすく、また後に拡張等を行う際にもより容易になる傾向があります。 |
【基礎課題 3-8-3】を再利用して、
|
というように2つの数を入れて「平均」ボタンを押すと |
|
平均値が求まる、というプログラムを作ります。ボタンの表示は「平均」に変更しておいてください。 |
次に、イベントハンドラを変更します。2つの数の平均は、合計を2で割って求めるのですね。プログラムを次のように書き換えてください。(書き換える部分は下線部です。)
void __fastcall TForm1::ButtonAddClick(TObject *Sender);
{
int a,b,c; //変数宣言を一度に行っています。
a = StrToInt(Edit1->Text);
b = StrToInt(Edit2->Text);
c = (a + b)/2;
EditResult->Text = IntToStr(c);
}
実行してみましょう。結果は次のようになるはずです。
答えの小数点以下が切り捨てられていますね。これは、平均を代入する変数cがint型(整数型)であることが原因です。整数には、少数点以下が代入されず、切り捨てられてしまうのです。そこで、「実数型」の変数が必要になります。次の基礎課題に進みましょう。
c を整数型の変数ではなく小数を受け付ける型の変数にしてしまいましょう。小数を受け付ける型は実数型と呼ばれ、「double」と表します。プログラムを以下のように修正してください。
void __fastcall TForm1::ButtonAddClick(TObject *Sender);
{
int a,b; //変数宣言を一度に行っています。
double c;
a = StrToInt(Edit1->Text);
b = StrToInt(Edit2->Text);
c = (a + b)/2.0;
EditResult->Text = FloatToStr(c);
}
なお、FloatToStr() とは、実数型から文字列型への変換を行う命令です。
実行してみましょう。今度はきちんと少数点以下も表示されるはずです。
![]() |
型変換の命令は、次のものがあります。必要になったらこのページを参照してください。
整数型から文字列型へ |
IntToStr() |
文字列型から整数型へ |
StrToInt() |
実数型から文字列型へ |
FloatToStr() 又は |
文字列型から実数型へ |
StrToFloat() |
整数型から実数型へ |
命令がなくても自動的に変換される |
実数型から整数型へ |
Ceil(),
Floor(), Trunc() ※実数を整数型変数に代入すると少数点以下切り捨て |
以上の「変換命令」使用法の詳細については、Delphiの「ヘルプ」メニュを参照して下さい。
以下にC++で通常よく用いられる演算子をまとめておきます。
T.算術演算子
演算 |
加算 |
減算 |
乗算 |
除算 |
剰余 |
表記 |
+ |
− |
* |
/ |
% |
※除算の場合、分母、分子が共に整数であれば答は整数(少数点以下切り捨て)、それ以外は実数。
※剰余(余り)計算の演算結果(の例)は次の通り。
11 % 3 → 2 11 % 4 → 3
U.代入演算子
プログラムを記述する場合は、「a = a + b」のようなタイプの式がよく出てきます。この入力の手間を省くため、以下の代入演算子が用意されています。
演算子 |
使用例 |
式の意味 |
+= |
a += b |
a = a + b |
-= |
a -= b |
a = a – b |
*= |
a *= b |
a = a * b |
/= |
a /= b |
a = a / b |
%= |
a %/ b |
a = a % b |
※ 「a += b」などの場合、「a + = b」のように、二つの演算子の間に空白を空けてはいけません。
V.変数の値を一つ増やす、あるいは一つ減らす演算子
演算子 |
使用例 |
式の意味 |
++ |
a++ あるいは ++a |
a = a + 1 |
-- |
a-- あるいは --a |
a = a - 1 |
※ C++言語は、C言語にオブジェクト指向プログラミングの要素が加わった言語ですが、「++」の意味は、C言語から一つ加わった、つまり一歩進んだ言語という意味合いで名付けられたようです。
★ UやVは入力の手間を省くために用意された演算子であり、これを知らなくてもプログラミングはできます。しかし、C++言語では、本来の書式よりも、UやVのような省略した演算子が好んで用いられる傾向があります。
3つの数の平均を求めるプログラムを作ってください。
下のようなフォームをもつ、分数を小数にするプログラムを作ってください。
注意
今は午後3時だとします。
|
「換算」ボタンを押したら |
|
午後の時刻の12時間表記から24時間表記を求める、というプログラムを作ってみましょう。 |
下の下線部には何と書いたらいいでしょうか。
void __fastcall TForm1::ButtonKansanClick(TObject *Sender);
{
CSpinEditResult->Value = CSpinEdit1->Value + ;
}
※ コンポーネントのNameプロパティを次のようにしています。
上のスピンディット |
|
下のスピンエディット |
|
ボタン |
上のプログラムに手を加え、下2桁の西暦略記から4桁の西暦表記を求めるプログラムを作ってください。ただし、西暦2000年以降とします。
12や2000のように、いつも決まった値であるものを「定数」といいます。この定数とは対照的に、変数は、代入によってその内容(値)が変わります。
|
左上の欄に女性の名前を入れてボタンを押すと |
|
頭に「Miss」とつけるプログラムを作ります。 |
※ 実はMissやMr.などの呼称は名字(姓)につけるもので、名前にこれをつけるのは英語としては不自然なのですが、ここでは気にしないでください。
まずはフォームにコンポーネントを配置してください。
コンポーネント |
Name |
左上のエディット |
Edit1 |
左下のエディット |
Edit2 |
右のボタン |
ButtonMiss |
あとは「敬称付け」ボタンのイベントハンドラを書くだけです。下線部には何が入ると思いますか?
void __fastcall TForm1::ButtonMissClick(TObject *Sender);
{
Edit2->Text = + Edit1->Text;
}
実行してみましょう。
次ページへ
下線部に単に「Miss」と入れて実行すると、「未定義のシンボル Miss」というエラーが出て止まってしまったと思います。これは、「Miss っていうのは変数 (か何か) のつもりだろうけど、どこにも用意されていないよ」という意味のエラーです。
「Miss は変数じゃない、単なる文字列 (定数) なんだ」ということを C++Builder に伝えるには、「”Miss”」と書きます。つまり「”」で囲みます。
プログラムを次のように修正して実行してみましょう。
void __fastcall TForm1::ButtonMissClick(TObject *Sender);
{
Edit2->Text = "Miss" + Edit1->Text;
}
次のように「さん」づけするプログラムを作りましょう。
|
→ |
|
ボタンを押すと「Hello, C++Builder.」と表示するプログラムを作ってください。
|
→ |
|
次のように来年が何年か教えてくれるプログラムを作りましょう。
|
→ |
|
|
「▲」ボタンを押すと |
|
「エディット」の中身が1つ増える、という「スピンエディット」のようなプログラムを「エディット」と「ボタン」だけで作ってみましょう。 |
コンポーネント |
Name |
左のエディット |
Edit1 |
右のボタン |
ButtonInc |
まずはフォームにコンポーネントを配置しましょう。
Edit1 はそのままでは数値の計算ができないので、整数型変数 a を用意し、
(1) Edit1 から a に値を代入
(2) a の値を1増やす
(3) a から Edit1 に値を代入
の順に処理するようにしましょう。下線部を埋めてプログラムを完成させて下さい。
void __fastcall TForm1::ButtonIncClick(TObject *Sender);
{
a; // 変数aの宣言
a = StrToInt(Edit1->Text);
a = ;
Edit1->Text = IntToStr(a);
}
実行してみましょう。
※ このプログラムがすんなりできたら大したもの!あなたは「代入」の意味をよく理解していることになります。
上のプログラムを、値が1ずつ増えるのではなく、2ずつ増えるように変更しましょう。
メモと呼ばれるコンポーネントを使ってみましょう。メモはを使ってフォームに配置することが出来ます。
下のようなフォームのプログラムを作ってください。
オブジェクトインスペクタで Memo1 を選んで ScrollBars を ssNone から ssBoth に変えると、プログラムはどのように変わりますか?
WordWrap プロパティを False にすると、何が変わりますか? (ヒント:実行中にメモに大量の文章を入力すると違いが分かります。)
Lines プロパティの値を変えて、プログラムを実行したとき、メモに
虹と雪のバラード |
と表示されるようにしましょう。
下のように、左のメモに情報が入っている状態で、「何行目」を指定して「取り出す」ボタンを押すと
その内容が右下のエディットに取り出される、というプログラムを作ってみましょう。
まずは、フォームの上に次のようにコンポーネントを配置します。
コンポーネント |
Name |
左のメモ |
MemoMain |
右上のスピンエディット |
CSpinEditGet |
右のボタン |
ButtonGet |
右下のエディット |
EditEachLine |
次に、プログラムを書きます。MemoMain の各行は、
MemoMain->Lines->Strings[行番号]
という形でアクセスすることができます。次のプログラムを作成して下さい。
void __fastcall TForm1::ButtonGetClick(TObject *Sender);
{
EditEachLine->Text =
MemoMain->Lines->Strings[CSpinEditGet->Value];
}
注意 メモの各行は、最初が0行目、次が1行目、その次が2行目、…というように順序がつけられています(0行目から始まっています)。
上の【練習問題】を改良しましょう。下の状態で「送り込む」ボタン(NameプロパティをButtonPutとします)を押すと
ここに、新たに付加したスピンエディットとボタンのNameプロパティは次に様にしてください。
[送り込む]ボタン : ButtonPut
2行目のスピンエディット : CSpinEditPut
3行目に「北の国から」、4行目に「ロマンスの神様」を送り込んでみてください。プログラムはどのように動作しましたか?
・・・
4行目以降には情報が入らないですね。 → コラム参照
コラム
このプログラムで、7行目や10行目など、4行目以降に情報を送り込もうとしても、うまく行きません。これは、現在存在していない行へのアクセスをメモが許してないからなのです。 「では、100行の情報を書き込むためには、各行にアクセスできるよう、メモにあらかじめ100行の無駄なデータを書き込んでおかなくてはならないのか?」 という疑問ももっともです。 実は、Memo には Add() という、行を付け足す命令があります。プログラムを次のように変更すると、ボタンを押すたびに行が増えていきます。 void __fastcall
|
フォームにメモを置くだけで MemoMain->Lines->Strings[0], MemoMain->Lines->Strings[1], MemoMain->Lines->Strings[2], …が利用できるようになったように、普通の変数も1行の宣言だけでいくつもの入れ物を用意することができます。
【基礎課題 3-13-2】からメモを削除し、その代わりとなる変数を使って同じプログラムを作りましょう。
MemoMain->Lines->Strings[0]、MemoMain->Lines->Strings[1]、・・・の代わりに、Data[0]、Data[1]、・・・という新しい変数を導入することにします。変数名Dataは適当に付けた変数名です。
まずは、【基礎課題 3-13-2】のプログラムから MemoMain
を削除し、代わりにヘッダファイル (どこでもいいからプログラムコードの上で右クリックし、「ソース/ヘッダー ファイルを開く」を選ぶと出現する)に次の下線部を挿入してください。
![]() |
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include "CSPIN.h"
#include <vector>
using namespace std;
//------------------------------------------------------
class
TForm1 :
public
TForm
{
__published
:
// IDE
管理のコンポーネント
TCSpinEdit *SpinEditGet;
TLabel *Label1;
TButton *ButtonGet;
TEdit *EditEachLine;
TCSpinEdit *SpinEditPut;
TLabel *Label2;
TButton *ButtonPut;
void __fastcall ButtonGetClick(TObject *Sender);
void __fastcall ButtonPutClick(TObject *Sender);
private
:
//
ユーザー宣言
public
:
//
ユーザー宣言
__fastcall
TForm1(TComponent* Owner);
vector<AnsiString> Data;
}
;
これで、Data[0]
, Data[1]
, Data[2]
, …というように、いくつもの文字列型変数を使う準備 (の第1段階) が出来ました。このときの
0
, 1
, 2
, … を添え字といいます。そして、このように添え字がつく変数を配列変数と呼びます。
※ ここで、「vector」という初めて耳にする用語が出てきましたが、ここでは、配列を宣言する際に使うものだ、という様に理解しておいてください。
※ 「using namespace std;」を記述することによって、本来
std::vector<AnsiString> Data;
と書くべきところを、
vector<AnsiString> Data;
と、略することができます。これは、「vector」がstd名前空間(namespace)に属しているからなのですが、もう少し詳しく説明するためにはいくつかの前提知識が必要になります。とりあえずここでは、現在のC++言語では、通常「using namespace std;」を用いる、と理解しておいてください。
さて、ところで、…, Data[100]
, Data[101]
, Data[102]
, … と続いていって、添え字はどこまで使えるようになっているのでしょうか (メモリをどれだけ準備しているでしょうか)?
実は、「配列 (の要素) が実際に何個必要か」は、プログラムの中で指示してやる必要があります。フォームに次のようにボタン (Nameプロパティを
ButtonSetSize
とします
) を配置し、そのイベントハンドラに次のように書いて下さい。
void
__fastcall
TForm1::ButtonSetSizeClick(TObject *Sender)
{
Data.resize(100);
}
これで、100個の変数 Data[0]
, Data[1]
, Data[2]
, …, Data[99]
が用意されました。もし変数の数が100個で足りなくなった場合も、同じ命令で変数の数を増減させることが出来ます。
では、プログラム本体部分を変更して、メモがないこのプログラムが正しく動くようにしましょう。空欄部分は自分で埋めて下さい。
void
__fastcall
TForm1::ButtonGetClick(TObject *Sender)
{
EditEachLine->Text =
Data[CSpinEditGet->Value];
}
//------------------------------------------------------------
void
__fastcall
TForm1::ButtonPutClick(TObject *Sender)
{
= EditEachLine->Text;
}
では、実行して動作を確認してみましょう。
最初に「100個用意」ボタンを押して下さい。これで100個の変数が使えるようになります。(押し忘れると、1個の変数も使えるようにならないため、エラーが発生します。)
1. 「睦月」という文字列を「0」行目へ「送り込む」。
2. 「如月」という文字列を「1」行目へ「送り込む」。
3. 「0」行目から文字列を「取り出す」と「睦月」と表示される。
4. 「むつき」という文字列を「0」行目へ「送り込む」。
5. 「1」行目から文字列を「取り出す」と「如月」と表示される。
6. 「0」行目から文字列を「取り出す」と「むつき」と表示される。
正しく動きましたか?