【学習内容とねらい】
これまで学習したプログラムは、上から順番に1行ずつ処理を行うというものでした。これは処理の流れの基本形ですが、身の回りを見渡してみてもこれだけでは記述できない処理が多々あります。
例えば、銀行のATMを考えてみましょう。この場合、ATMはインプットした暗証番号が正しいかどうかを判定して、正しければお金の引き出し等に応じ、間違っていれば処理を中断するようになっています。つまりある条件の判定結果に応じて処理内容を分けている(分岐させている)訳です。このような処理を「分岐処理」と言います。さらに、インプットした暗証番号が正しくなかった場合、ATMは番号が間違っている旨のメッセージを表示した上で、操作をやり直すために最初の画面に戻します。これは、操作を何度か繰り返す、つまり「繰り返し処理」に当たります。
プログラミング言語にも、当然この「分岐処理」と「繰り返し処理」の命令が用意されています。これらの命令は、処理を分岐したり、元に戻したりというように処理の流れを制御するので「制御命令」と呼ばれています。本章では、この「制御命令」の使い方を学習します。
ところで、ある処理の論理的手順(・・を行ったあと、・・を実行する等のような手順)を「アルゴリズム」と言います(本来の数学的定義からすると少しあいまいですが、ここでは問題ではありません)。ある処理のプログラムを書くという作業は、そのアルゴリズムを考案・作成するということです。そしてどのような複雑なアルゴリズムでも、この「分岐処理」と「繰り返し処理」の組み合わせによって記述することができます。ですから、本章の学習を終えれば皆は、プログラミングの基本的な“表現能力”を身に付けることになります。その意味で本章はプログラミング学習の“メインイベント”と言えるでしょう。
なお、一般に、初学者は「分岐処理」は比較的理解できるが、「繰り返し処理」の理解につまずくことが多い、と言われています。本章の後半がそれに当たりますが、どうかじっくりと学習してこの“定説”をくつがえして下さい。
<本章の構成>
![]() |
4−1 分岐処理(1)−2分岐(if 〜 else文)−
4−2 分岐処理(2)−多分岐(if〜else if〜else文)
4−3 分岐処理(3)−2分岐の特殊な形(if〜文)−
4−4 分岐処理(4)−多分岐(switch文)−
4−5 繰り返し処理(1)−累乗−
4−6 繰り返し処理(2)−for文の導入−
4−7 繰り返し処理(3)−for文の流れの観察(デバッガ利用)
4−8 繰り返し処理(4)−カウント用変数を使ったプログラム−
4−9 繰り返し処理(5)−回数が定まっていない繰り返し−
4−10 繰り返し処理(6)−while文の導入−
以前、【基礎課題1-7-3】で、下のようなフォームのプログラムを作りました。
このプログラムでは、
1. チェックされた項目の数を数える。
2. その数に応じて、診断結果を出す。
という2つの部分が必要です。
今回、このプログラムに、2. の機能をつけ加えてみましょう。
1. については、今回は考えません。項目の数は自分で数えることにします。
このプログラムを新しい名前で保存してから、下のようなフォームのプログラムに作り替えて下さい。
主なコンポーネントのNameプロパティは、次のようにして下さい。
コンポーネント |
Name |
ボタン「診断」 |
ButtonDiag |
スピンエディット「チェック項目数」 |
CSpinEditSum |
チェックボックス「6-10」 |
CheckBoxHigh |
チェックボックス「0-5」 |
CheckBoxLow |
エディット |
EditMessage |
「チェック項目数」を入力してから「診断」ボタンを押したとき、
ようなプログラムを作りましょう。
ある条件が成り立っているか成り立っていないかによって行う内容が変わる場合には、「if文」を用いて表します。
「診断」ボタンをクリックしたときのイベントハンドラを、次のように書いて下さい。
![]() |
void__fastcall Tform1::ButtonDiagClick(Tobject *Sender)
if ((CSpinEditSum->Value >= 6) == true) {
CheckBoxHigh->Checked = true;
EditMessage->Text = "少しストレスがたまっています。気分転換を。";
}
else {
CheckBoxLow->Check = true;
EditMessage->Text = "ストレスの兆候がありますが、心配は不要。";
}
注意 面倒でも、半角スペース4字分ずつの「字下げ」を必ず行って下さい。構造が見やすくなります。
この命令は、下のような構造になっています。
void__fastcall Tform1::ButtonDiagClick(Tobject *Sender)
|
if ((CSpinEditSum->Value
>= 6) == true) {
CheckBoxHigh->Checked = true;
EditMessage->Text = "少しストレスがたまっています。気分転換を。";
}
|
|||
|
|||
else {
CheckBoxLow->Check = true;
EditMessage->Text
= "ストレスの兆候がありますが、心配は不要。";
if文の終わり
}
if文は、条件が成り立っているか成り立っていないかによって、プログラムの流れを分岐させます。
条件は、
のどちらかしかありません。したがって、プログラムは、
のどちらかひとつを必ず実行し、かつ、いずれかひとつしか実行しません。
数学表記 |
意味 |
C++での表記 |
A>B |
AはBより大きい |
A > B |
A≧B |
AはB以上 |
A >= B |
A=B |
AはBに等しい |
A == B |
A≦B |
AはB以下 |
A <= B |
A<B |
AはBより小さい |
A < B |
A≠B |
AはBに等しくない |
A != B |
C++Builderでの不等号記号の書き方は右表の通りです。
注意 C++では、代入の「=」と比較の「==」を使い分けます。混同しやすいので注意してください。
上で学習したif分の使い方をもう少し練習してみましょう。
上のようなフォームを作り、「診察を希望する」チェックボックスがチェックされているかどうかによって
状態 |
メッセージ |
チェックされている |
来週水曜正午から、公民館で健康診断が行われます。 |
チェックされていない |
ストレスを溜めない生活を心掛けましょう。 |
というメッセージが表示されるプログラムを作りましょう。「OK」ボタンのイベントハンドラを次のように書いて下さい。
void __fastcall TForm1::ButtonOKClick(TObject *Sender)
{
if
(CheckBoxDoctor->Checked == true) {
Edit1->Text =
"
来週水曜正午から、公民館で健康診断が行われます。
";
Edit2->Text =
"
無料です。
";
}
else {
Edit1->Text =
"
ストレスを溜めない生活を心掛けましょう。
";
Edit2->Text =
"
体を大切に。
";
}
}
さて、if ( == true )文では、== trueを省略してもよいことになっています。 試しに == trueを省略して実行してみましょう。うまく動きましたか?
【基礎課題4-1-1】のプログラムでも、== true を省略して実行してみましょう。
次のようなフォームを持つプログラムを作って下さい。
主なコンポーネントのNameプロパティは、次のようにして下さい。
コンポーネント名 |
Name |
スピンエディット |
CSpinEditOld |
ボタン「入力完了」 |
ButtonEnter |
上のエディット |
Edit1 |
下のエディット |
Edit2 |
年齢を入力してから「入力完了」ボタンを押すと、 2つのメッセージが表示される。
年齢とメッセージの対応は、次の表にしたがってください。
年齢 |
メッセージ |
20歳以上 |
あなたは成年ですね。あなたには選挙権があります。 |
19歳以下 |
あなたは未成年ですね。あなたには選挙権がありません。 |
下の下線部を埋めて、プログラムを完成させて下さい。
void __fastcall TForm1::ButtonEnterClick(TObject *Sender)
{
if
((CSpinEditOld->Value
)
==
true) {
}
else {
}
}
新しいコンポーネント「ラジオボタン」の使い方を覚えましょう。
コンポーネントパレットからラジオボタンのアイコンを選んで、フォーム上に3つ貼って下さい。
プログラムを実行する前に、以下の動作を確認してください。
1. RadioButton1のChekedプロパティの値をtrueにして下さい。
2. RadioButton2のChekedプロパティの値をtrueにして下さい。
3. RadioButton1のCheckedプロパティの値を確認して下さい。trueおよびfalseのどちらになっていますか?
次に、プログラムを実行して、ラジオボタンを自由にクリックして下さい。
ラジオボタンはどういうはたらきをするコンポーネントか、下に書いて下さい。
次のようなフォームを持つプログラムを作って下さい。
コラム左の「ようこそいらっしゃいました。」と「性別をチェックして下さい。」は、 2つのラベルを用いて表現しています。 実は、一つのラベルに複数行のメッセージを表示させることもできます。それには、ラベルコンポーネントの「WordWrap」プロパティを「true」にすればよいのです。こうすると、指定したラベルコンポーネントの幅にメッセージが収まりきれない場合、自動的に折り返されます。つまり、ラベル幅に収まるように複数行表示してくれます。 しかし、最初から2行に分けてメッセージを表示させたい場合は、2つのラベルを用いた方が便利です。 |
プログラムの動作内容は以下の通りです。
実行してから性別をチェックしてボタンを押すと、下のように2つのメッセージが表示される。
チェック項目とメッセージの対応は、次の表にしたがって下さい。
チェック項目 |
メッセージ |
女性 |
あなたは女性ですね。右側の階段をお上り下さい。 |
男性 |
あなたは男性ですね。左側の階段をお上り下さい。 |
【基礎課題 4-1-4】
次のようなフォームを持つプログラムを作って下さい。
コンポーネント名 |
Name |
ラジオボタン「女性」 |
RadioButtonF |
ラジオボタン「男性」 |
RadioButtonM |
ボタン「OK」 |
ButtonOK |
チェックボックス「18歳以上」 |
CheckBoxAdult |
主なコンポーネントのNameプロパティは、
次のようにして下さい。
プログラムの動作内容は次の通りです。
性別と年齢をチェックしてから「OK」ボタンを押すと、2つのメッセージが表示される。
性別・年齢の条件とメッセージの対応は、次の表にしたがってください。
性別・年齢 |
メッセージ |
女性で、かつ、18歳以上 |
あなたは入会資格があります。どうぞお入り下さい。 |
それ以外 |
あなたは入会資格がありません。残念ですがお帰り下さい。 |
注意 「女性で、かつ、18歳以上」つまり、
「RadioButtonFがチェックされていて、かつ、CheckBoxAdultがチェックされている」
ことを、
(RadioButtonF->Checked == true)
&&
(CheckBoxAdult->Checked == true)
のように && を用いて表します。
もちろん、先に学習した通り、== trueを省略して
(RadioButtonf->Checked)
&&
(CheckBoxAdult->Checked)
と書くこともできます。ここでは、== trueを省略せずに見慣れた形のままにしておきます。
なお、&& の前後の条件式(論理式)には、( )をつけなくてもエラーにはなりません。しかし、条件式の区切りを明示的に示すために( )でくくることを勧めます。なお、条件式全体のかっこ「if (条件式 )」を外すと文法エラーとなりますので注意してください。
それでは、下の下線部を埋めて、プログラムを完成させて下さい。
![]() |
void
__
fastcall
TForm1::ButtonOKClick(TObject *Sender)
{
if ( (RadioButtonF->Checked
==
true )
&&
(CheckBoxAdult->Checked
==
true) ) {
}
else
{
}
}
注意 「かつ」ではなく「または」を表したいときは、 || を使います。
例 「女性、または、18歳以上」のとき
(RadioButtonF.Checked = True)
||
(CheckBoxAdult.Checked = True)
次のようなフォームを持つプログラムを作って下さい。
主なコンポーネントのNameプロパティは、
次のようにして下さい。
コンポーネント名 |
Name |
スピンエディット |
CSpinEditNumber |
スピンエディットには0〜9までの数しか入りません。それ以外の数を入力できないように、
MinValue プロパティと MaxValue プロパティの値を変更しておいて下さい。
ここで、プログラムを実行し、数を入力してからOKボタンを押したとき、
ようなプログラムを作って下さい。
注意 スピンエディットに入力された値が4以上7以下であることを表すのに、
(4 <= CSpinEditNumber->Value <= 7) == true
と書きたくなると思います。しかし、C++は、2つの不等号が同時に出てくる文を理解することができません。ですから、
( (4 <= CSpinEditNumber->Value) == true )
&&
( (CSpinEditNumber->Value <= 7) == true )
のように、条件を二つの部分に分けてから && (かつ) でつなげて書く必要があります。
【練習問題】
次のようなフォームを持つプログラムを作って下さい。
コンポーネントのNameプロパティは、次のようにして下さい。
コンポーネント名 |
Name |
スピンエディット |
CSpinEditNumber |
ボタン「判定」 |
ButtonHantei |
エディット |
EditMessage |
0以上の数を入力してボタンを押すと、 0未満の数を入力してボタンを押すと、
「入力した数は0以上です。」と表示し、 「入力した数は0未満です。」と表示する。
「判定」ボタンを押したときの処理は、以下のように書くことができます。
![]() |
void
__
fastcall
TForm1::ButtonHanteiClick(TObject *Sender)
{
if ((CSpinEditNumber->Value >= 0)
==
true) {
EditMessage->Text = "入力した数は0以上です。";
}
else
{
EditMessage->Text = "入力した数は0未満です。";
}
}
しかし、if (条件式) のあと、あるいは else のあとに、1つの処理しかしないときは、{ } を省略して、次のように書くこともできます。
![]() |
void
__
fastcall
TForm1::ButtonHanteiClick(TObject *Sender)
{
if ((SpinEditNumber->Value >= 0)
==
true)
EditMessage->Text = "入力した数は0以上です。";
else
EditMessage->Text = "入力した数は0未満です。";
}
しかし、実際 のプログラミングの場面では、最初は(処理する)実行文が1つでも、後に文を加えて複数の文になることがよくあります。その様な場合には再び {と }をつけ加えなければなりませんが、うっかり忘れてしまいやすいものです。そして、もし忘れるとエラーが発生したり思った通りの処理をしてくれなくなったりします。 そこで、処理する文が1つのときでも({ }を書いていてもエラーになるわけではないので)、{ }を消さずに残しておくようにすることを勧めます。
以前つくったストレス度診断プログラムは、もともと、下の分類にしたがって4段階の診断をするものでした。本節では、3つ以上の選択肢がある場合の処理を学習しましょう。
チェック数 |
メッセージ |
9〜10 |
かなりストレスがたまっています。医師による診察を。 |
6〜8 |
少しストレスがたまっています。気分転換を。 |
3〜5 |
ストレスの兆候がありますが、心配は不要。 |
0〜2 |
正常です。 |
【基礎課題4-1-1】のプログラムを新しい名前で保存してから、下のようなフォームのプログラムに作り替えて下さい。
主なコンポーネントのNameプロパティは、次のようにして下さい。
コンポーネント |
Name |
備考 |
ボタン「診断」 |
ButtonDiag |
変化なし |
スピンエディット「チェック項目数」 |
CSpinEditSum |
変化なし |
チェックボックス「9-10」 |
CheckBoxHigher |
|
チェックボックス「6-8」 |
CheckBoxHigh |
|
チェックボックス「3-5」 |
CheckBoxLow |
|
チェックボックス「0-2」 |
CheckBoxLower |
|
エディット |
EditMessage |
変化なし |
このように、3つ以上の分岐(選択肢)がある場合には、「if〜else if〜else文」を用います。例えば4つの分岐がある場合には、次のように記述します。
if (条件式1) {
条件式1が成立する場合の処理
}
else if (条件式2) {
条件式2が成立する場合の処理
}
else if (条件式3) {
条件式3が成立する場合の処理
}
else{
上以外の場合の処理
}
それでは、下の空欄を埋めて、4段階の診断をするプログラムを完成させて下さい。
void__fastcall TForm1::Button1Click(TObject *Sender)
if ((CSpinEditSum->Value>=9) == true) {
|
CheckBoxHigher->Checked = true;
EditMessage->Text ="かなりストレスがたまっています。医師による診断を。";
else if ((CSpinEditSum->Value>=6) == true) {
|
EditMessage->Text ="少しストレスがたまっています。気分転換を。";
else if ((CSpinEditSum->Value>=3) == true) {
|
CheckBoxLow->Checked = true;
EditMessage->Text ="ストレスの兆候がありますが、心配は不要。";
}
else {
|
CheckBoxLower->Checked = true;
EditMessage->Text ="正常です。";
}
}
※ 上の例から理解できると思いますが、この「if〜elseif〜else文」はいくつ分岐があっても対応できます。
テストの得点を入力してから「成績判定」ボタンを押すと、得点に対応して「優」「良」「可」「不可」の評価をする下のようなプログラムを作って下さい。
得点と成績の対応は、次の表にしたがって下さい。
優 |
80点〜100点 |
良 |
60点〜79点 |
可 |
50点〜59点 |
不可 |
0点〜49点 |
また、成績に応じて、それぞれ内容の異なる一行メッセージを出すようにして下さい。
メッセージの内容は自由に考えて下さい。
「テストの得点」欄には100点満点のテストの得点を入力するものとします。スピンエディットのMaxValueプロパティとMinValueプロパティの値を変えておいて下さい。
【基礎課題 4-2-1】のプログラムのチェック数は、実は「3で割ったときの商」によってメッセージが決まっています。
チェック数 |
3で割った商 |
メッセージ |
9〜10 |
3 |
かなりストレスがたまっています。医師による診察を。 |
6〜8 |
2 |
少しストレスがたまっています。気分転換を。 |
3〜5 |
1 |
ストレスの兆候がありますが、心配は不要。 |
0〜2 |
0 |
正常です。 |
したがって、予めチェック数を3で割って商を求めておくことによって、if
文の条件をもっと簡単に(見易く)することができます。プログラムを次のように変更しましょう。下線部を埋めてプログラムを完成させてください。
![]() |
void
__
fastcall
TForm1::ButtonDiagClick(TObject *Sender)
{
@
int q;
q = CSpinEditSum->Value / 3;
if ((q == 3) == true) {
}
else
if ((q == 2) == true) {
}
else
if ((q == 1) == true) {
A
}
else
if ((q == 0) == true) {
}
}
※ 上の枠@で「チェック数を3で割った商」qを求めています。除算「/」を用いて商を求められます。3-9節<様々な演算子>を参照してください。
※ 枠Aは、今の場合「else 」だけに替えても結構です。ただし、厳密に言うと、その際は「qの値が0〜4以外の値をとらない」という前提が必要になります(今の場合はこの前提が成り立ちます)。
【練習問題】
下のようなフォームのプログラムを作って下さい。
主なコンポーネントのNameプロパティは、次のようにして下さい。
コンポーネント |
Name |
チェックボックス「賛成します」 |
CheckBoxSansei |
ボタン「投票」 |
ButtonTouhyou |
エディット |
EditMessage |
スピンエディット「現在の賛成者数」 |
CSpinEditNinzu |
プログラムを実行して、「投票」ボタンを押したとき、
ようなプログラムを作ります。
このプログラムの流れを図にすると、次のようになります。
プログラムは、次のように書きます。
![]() |
void
__
fastcall
TForm1::ButtonTouhyouClick(TObject *Sender)
{
if ((CheckBoxSansei->Checked)
==
true
) {
EditMessage->Text = "賛成票ありがとうございました。";
CSpinEditNinzu->Value = CSpinEditNinzu->Value + 1;
}
![]() |
else {
何もしないので何も書かない
}
省略できる
}
解説
次のようなフォームをもつプログラムを作って下さい。
作成するプログラムは検索処理を模したプログラムです。ただし、現時点では残念ながら検索処理をプログラミングするができません。
キーワードを入力しないでボタンを押すと、「検索用キーワードを入力してください。」と警告し、
キーワードを入力してボタンを押すと
何もしない。
Ø このプログラムでは、一度警告メッセージが出てしまうと、それ以降は(例えキーワードを入力して[検索]ボタンを押しても)警告が消えてくれません。本来は、キーワードを入力してボタンを押すと、その警告は消えるべきですね。その改良については次章5-13で取り扱います。
最も基本的なif文は、 4-1で学習した「if〜else文」であり、それは
に応じて、プログラムの流れを2つに分岐させるものでした。
プログラムの流れを3つ以上に分けなければならないときは、4-2で学習したように、「if〜else if〜else〜文」を用います。実はこれで、あらゆる分岐処理を記述することができるのですが、多分岐の場合、C++言語にはswitch文が用意されており、これを使うとプログラムの記述が容易になり、かつ見易くなる場合があります。そこで、本節では、このswitch文の使い方を学習しましょう。
【基礎課題 4-2-3】は、switch文を使うと次のように書くことができます。
![]() |
void
__
fastcall
TForm1::ButtonDiagClick(TObject *Sender)
{
int q;
q = CSpinEditSum->Value / 3;
switch (q) {
case 3:
|
break;
case 2:
|
break;
case 1:
|
break;
case 0:
|
break;
}
}
注意
switch文で分岐に使用する変数(上の例ではq)は、整数型(int型)でなければなりません。
【基礎課題4-4-1】
上の空欄を埋めて、【基礎課題4-2-3】のプログラムを書き換え、動作を確認してください。
switch文を用いる際、最も注意しなければならない点は、break文の位置です。例えば前ページのプログラムにおいて、一番上のbreak文を削除すると・・・
switch (q) {
case 3:
![]() |
|||||
|
|||||
|
|||||
case 2:
|
break;
case 1:
|
|
||||
break;
case 0:
|
break;
}
この性質を利用して、変数の範囲に応じて分岐を行うことができます。
例えば、整数qの値が「0〜1」および「2〜3」に応じて処理を分岐させたい場合には、次の様に記述します。
![]() |
switch
(q) {
case 3:
case 2:
break;
case 1:
case 0:
|
break;
}
【基礎課題 4-2-1】を、switch文を使って作り直してください。
switch文には、default を使った特殊な例があります。一番下の「変数の値の範囲」を default と書いて、「今までに指定した範囲以外」という意味を表すことができます。
![]() |
switch (q) {
case 1:
|
break;
case 5:
|
break;
default:
|
break;
}
【基礎課題4-4-2】のプログラムでは、項目数として11以上の値や、負の値など、想定している範囲外の値を入力した場合、何もメッセージが表示されません。そこで、このような範囲外の項目数を誤って入力してボタンをクリックした場合は、「1〜10までの項目数を入力してください。」というメッセージを表示させるように、このプログラムを改良してください。
defaultを用いれば簡単にプログラミングできるはずです。
スーパーファミコンは 16 ビット、PlayStation は 32 ビット、NINTENDO 64 は 64 ビット、さらにはこのコンピュータのメモリは 64 MB あるいは 128 MB 等々、コンピュータ関係のもので出てくる数には決まった数が多いですね。これらの数は、2×2×2×…×2 の形で求められる、コンピュータにとって“きりのいい”数なのです。
下の表を埋めましょう。
|
|
2の個数 |
答 (計算結果) |
21 |
2 |
1 |
2 |
22 |
2×2 |
2 |
4 |
23 |
2×2×2 |
3 |
|
24 |
2×2×2×2 |
4 |
|
25 |
2×2×2×2×2 |
5 |
|
26 |
2×2×2×2×2×2 |
6 |
|
27 |
2×2×2×2×2×2×2 |
7 |
|
28 |
2×2×2×2×2×2×2×2 |
8 |
|
29 |
2×2×2×2×2×2×2×2×2 |
9 |
|
210 |
2×2×2×2×2×2×2×2×2×2 |
10 |
|
2×2×2×2×2 のように、ある数 a を b 個かけることを累乗といいます。
2×2×2×2×2 のことを、2を5個書く代わりに「25」と書いて「2の5乗」と読みます。
|
「2倍」ボタンを押したら |
|
左の値が2倍になり、さらにもう1度「2倍」ボタンを押したら |
|
さらに2倍になり、ボタンを押すごとに値がどんどん2倍になっていく、というプログラムを作りましょう。 |
まずは、フォーム上にコンポーネントを次のように配置してください。
コンポーネント |
Name |
左のスピンエディット |
CSpinEditNumber |
右のボタン |
ButtonDouble |
注意 CSpinEditNumber->Value の初期値を 1 にしておいてください。
次の空欄を埋めてプログラムを完成させて下さい。
void __fastcall TForm1::ButtonDoubleClick(TObject *Sender)
CSpinEditNumber->Value = ;
}
このプログラムを使えば、25 の値を調べたいときも「2倍」ボタンを5回押すだけで求められます。では、このプログラムをもっと改良して、ボタンを1度押すだけで 25 が求められるようにできないでしょうか。
これはそれほど難しくありません。ボタンを押したときに今までの5回分の動作をすればよいのですから、
void __fastcall TForm1::ButtonDoubleClick(TObject *Sender)
CSpinEditNumber->Value = CSpinEditNumber->Value * 2;
CSpinEditNumber->Value = CSpinEditNumber->Value * 2;
CSpinEditNumber->Value = CSpinEditNumber->Value * 2;
CSpinEditNumber->Value = CSpinEditNumber->Value * 2;
CSpinEditNumber->Value = CSpinEditNumber->Value * 2;
}
となります。実行して動作を確認してみましょう。
ボタンを1度押すだけで 215 が求められるよう、プログラムを改変して下さい。
void __fastcall TForm1::ButtonDoubleClick(TObject *Sender)
}
|
何乗の値を計算したいか (ここでは 3 乗) を入力して「計算」ボタンを押すと |
|
その値を計算してくれる、というプログラムを作りましょう。 |
コンポーネント |
Name |
左のスピンエディット |
CSpinEditJo |
右のスピンエディット |
CSpinEditResult |
下のボタン |
ButtonCalc |
まずはつぎのようにフォームを作ってください。
注意 SpinEditResult->Value を 1 にしておくのを忘れないようにしましょう。
このプログラムでは、「何回2倍するか」はプログラム実行後にユーザが決めるので、今までのようにプログラム実行前に
void __fastcall TForm1::ButtonDoubleClick(TObject *Sender)
CSpinEditResult->Value = CSpinEditResult->Value * 2;
CSpinEditResult->Value = CSpinEditResult->Value * 2;
CSpinEditResult->Value = CSpinEditResult->Value * 2;
続く
CSpinEditResult->Value = CSpinEditResult->Value * 2;
}
とあらかじめ決まった回数だけ書いておくことはできません。
そこで、同じ動作を繰り返させる 「for 文」という命令を使います。プログラムを次のように書いてください。
void__fastcall TForm1::ButtonCalcClick(TObject *Sender)
何回目かを数える変数(カウンタ)の宣言
{
int i;
|
for(i=1; i<=CSpinEditJo->Value; i=i+1){
![]() |
CSpinEditResult->Value = CSpinEditResult->Value * 2;
}
}
実行して動作を確認しましょう。この for 文は、下のような構造になっています。
![]() |
for ( カウンタ(上の例ではi)の初期化; 繰り返し条件;カウンタの変化式 ) {
繰り返し処理1;
繰り返し処理2;
・・・
}
@カウンタ初期化: i=1
意味はだいたい推測できると思いますが、処理の流れを以下に示しておきましょう。
なお、C++言語では、上のプログラムは通常、次の様に(簡略化した形で)記述されます。
void__fastcall TForm1::ButtonCalcClick(TObject *Sender)
{
for(int i=1; i<=SpinEditJo->Value; i++){
SpinEditResult->Value = SpinEditResult->Value * 2;
}
}
下線部については、3-8のコラムで説明した「変数の宣言と初期化は同時に行える」こと、また、3-9で説明した「++」演算子を用いています。
void__fastcall TForm1::ButtonCalcClick(TObject *Sender) { CSpinEdit1->Value = CSpinEdit1->Value * 2; CSpinEdit1->Value = CSpinEdit1->Value * 2; CSpinEdit1->Value = CSpinEdit1->Value * 2; CSpinEdit1->Value = CSpinEdit1->Value * 2; CSpinEdit1->Value = CSpinEdit1->Value * 2; CSpinEdit1->Value = CSpinEdit1->Value * 2; CSpinEdit1->Value = CSpinEdit1->Value * 2; CSpinEdit1->Value = CSpinEdit1->Value * 2; CSpinEdit1->Value = CSpinEdit1->Value * 2; CSpinEdit1->Value = CSpinEdit1->Value * 2; CSpinEdit1->Value = CSpinEdit1->Value * 2; CSpinEdit1->Value = CSpinEdit1->Value * 2; CSpinEdit1->Value = CSpinEdit1->Value * 2; CSpinEdit1->Value = CSpinEdit1->Value * 2; CSpinEdit1->Value = CSpinEdit1->Value * 2; } |
void__fastcall TForm1::ButtonCalcClick(TObject *Sender) { for(int i=1; i<=15; i++ ){ CSpinEdit1->Value = CSpinEdit1->Value*2; } } |
このように、for文は決まった回数の繰り返しに用いられる場合が多いです。下の左右のプログラムは全く同じ動作をします。
コラム
for ( カウンタ用変数の初期化; 繰り返し条件;カウンタの変化式 ) { 繰り返し処理1; } というように、繰り返し処理が1つしかない for 文は、if 文の場合と同様に、{ } を省略して次のように書くことが出来ます。 for ( カウンタ用変数の初期化; 繰り返し条件;カウンタの変化式 ) 繰り返し処理1;
しかし、この書き方は、後で繰り返し処理を増やしたくなった場合に { } を付け忘れる可能性があり、実際これまでもそのようなエラーは(本演習において)頻繁に見受けられました。そこで、たとえ処理が1つでも常に { }をつけることを勧めます。 |
先ほどのプログラムを改変して、
|
数値を入れたら (この例では 3) |
|
3の累乗が求められるプログラムを作ってください。 |
かけ算は、足し算の繰り返しと考えることができます。例えば、2×5は、「2を足す」ということを5回繰り返すことです。
このように考えると、かけ算の記号「*」を使わずに、for文を使ってかけ算の答を求めることができます。
前のページのプログラムを改変して
|
数値を入れたら (この場合は 6) |
|
4+4+4+…+4 を求めるプログラムを、for 文を使って作って下さい(ただし、プログラムの中でかけ算「*」を使ってはいけません。)。 |
|
怒りの度合いを数値で入力し「怒る」ボタンを押すと |
|
その度合いに応じて「こらこら…」と表示するプログラムを作りなさい。
(以下同様) |
ヒント ‘こら’という文字列を、指定回数だけ連結すれば良いのです。文字列の連結がよく分からない人は、3-11を参照してください。
【基礎課題 4-6-1】で作った「2 の累乗」プログラムで「計算」ボタンを押したときのプログラムが動作する様子を1行ずつ順に追いかけてみましょう。
まずは、ボタンが押されたら一旦プログラムを止めるため、「ブレークポイント (“一時停止”の標識) 」をおきます。コードエディタの次の部分をクリックしてください。
すると、ブレークポイント (小さな赤丸) が現れます。
それでは実行してみましょう。下のように入力して「計算」ボタンを押すと…
ブレークポイントの隣に小さな緑の矢印が現れます。これは、「プログラムをここから再開します」という標識です。ここで、[F8]キーを押すと (または「実行」→「ステップ実行」を選ぶと)
プログラムが1行実行されて、緑の矢印が次の行に移ります。
以下同じ要領で[F8]を押すと、1行ずつ処理が実行され、指定した繰り返しの回数分の処理が終了すると、下の様に、繰り返しのブロックを抜け出るはずです。
さて、今度は CSpinEditResult->Value の値を確認しながら1行ずつ実行させてみましょう。
右のスピネディットの値を1に戻して、再び、下のような状態で「計算」ボタンを押しましょう。
すると、先ほど同様、緑の矢印が表れましたね。
ここで、マウスを使って、下のようにCSpinEditResult->Value を選択してください (左ボタンを押しながら領域をなぞってください。左ボタンを離すと選択が完了します。)。
今選択した部分の上で右クリックするといくつかのメニューが現れるので、その中から次のように、「デバッグ」→「カーソル位置の単語を監視」を選びます
すると、「監視式一覧」というウィンドウが現れ、SpinEditResult.Value の値を常に表示してくれるようになります。
[F8]を押して1行進めてから、同様に、i の値も監視してみましょう。
すると、iの最初の値である「1」が表示されます。「F8」を押していくと(繰り返しが進みにつれて)iの値も増加して行くはずです。*
※ カーソルが「for (int i; ・・・) 」の行に来たとき、一時的にiの値が下のように「未定義」と表示されますが、気にせずそのまま進めてください。次の行へ進むとiの値が表示されます。
このままどんどん「F8」を押し、SpinEditResult.Value と i の値の変化を調べて下の表を埋めましょう。
SpinEditResult->Value |
1 |
|
|
|
|
i |
|
|
|
|
|
i は何回目の繰り返しかを数える変数です。これを文法用語では「制御変数」と呼びますが、ここでは分かりやすく「カウント用変数(カウンタ)」と呼びましょう。4-6のプログラム例では、{ }の間を1回実行するたびに、iは1つずつ増えます。この性質を利用すると、自然数の和などを簡単に求めることができます
下のようなフォームのプログラムを作ってください
コンポーネント |
Name |
上のスピンエディット |
CSpinEditResult |
下のボタン |
ButtonCalc |
最初の値は「0」にしておいて下さい。
このプログラムで 1+2+3+4+5 を計算させて結果を表示させます。下線部を埋めてください。
void__fastcall TForm1::ButtonCalcClick(TObject *Sender)
{
for(int i=1; i<=5; i++){
CSpinEditResult->Value = CSpinEditResult->Value + ;
}
}
|
|
上のプログラムを改良して、5 までではなく任意の数までの和を求める (どこまで足すかを指定できる) プログラムを、for 文を使って作って下さい。 |
|
2+4+6+8+… を計算するプログラムを、for 文を使って作って下さい。 |
|
1+3+5+7+・・・ を計算するプログラムを、for 文を使って作って下さい。
最初は「0」にしておきます。 |
左のピラミッドは、1番上の段は石が 12=1 個、上から2段目は 22=4 個、上から3段目は 32=9
個です。このピラミッドが5段になったときの石の個数を求めるプログラムを作って下さい。
また、このプログラムを改良して、
|
最初は「0」にしておきます。 |
||
|
答えを出力するプログラムを作って下さい。 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
2 |
4 |
6 |
8 |
10 |
12 |
14 |
16 |
18 |
3 |
6 |
9 |
12 |
15 |
18 |
21 |
24 |
27 |
4 |
8 |
12 |
16 |
20 |
24 |
28 |
32 |
36 |
5 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
6 |
12 |
18 |
24 |
30 |
36 |
42 |
48 |
54 |
7 |
14 |
21 |
28 |
35 |
42 |
49 |
56 |
63 |
8 |
16 |
24 |
32 |
40 |
48 |
56 |
64 |
72 |
9 |
18 |
27 |
36 |
45 |
54 |
63 |
72 |
81 |
右は、かけ算の九九表です。この全ての数の合計を求めるプログラムを作って下さい。
ヒント 例えば、1行目(1番上の横の並び)の和を求めることはすでにできるはずです。これに、2行目、3行目の和を順次加えて行けばよいのです。
すると・・・
最終的には「行を数えるfor文の中に列を数えるfor文が入る」という形になるはずです。
これができたら大したもの!
1分間で2個に分裂するバクテリアが、今1個あります。このバクテリアが10000個以上になるのは何分後でしょうか。
この問題を解くため、
|
「1分だけ経過」ボタンを押すと |
|
1分経過してバクテリアが2倍になり、さらに「1分だけ経過」ボタンを押していくと |
|
バクテリアがどんどん増えていき、いつかは10000個を越える、というプログラムを作ります。 |
まずは次のようにフォームにコンポーネントを配置してください。
コンポーネント |
Name |
上のスピンエディット |
CSpinEditMinute |
中のスピンエディット |
CSpinEditBact |
下のボタン |
ButtonCalc |
最初は「1」にしておきます。
ボタンを押したときの動作をプログラミングします。下線部には何が入りますか?
void__fastcall TForm1::ButtonCalcClick(TObject *Sender)
{
CSpinEditMinute->Value = ;
CSpinEditBact->Value = ;
}
また、バクテリアが10000個以上になるのは何分後でしょうか?
分後
前のプログラムでは、何度もボタンを押していくとそのうち答えが求まります。でも、ボタンを1回押すだけで答えが求まるプログラムにしたいですね。
何回もボタンを押すことは、for 文ででてきた「繰り返し」と呼ばれる操作 (作業) です。ですから、まずは for 文を使ってボタンを1回押すだけのプログラムを考えてみましょう。プログラムは次のようになります。
void__fastcall TForm1::ButtonCalcClick(TObject *Sender)
{
for(int i=1; SpinEditBact->Value<10000; i++){
CSpinEditMinute->Value = CSpinEditMinute->Value + 1;
CSpinEditBact->Value = CSpinEditBact->Value * 2;
}
}
今の場合、繰り返し条件を下線部の通りとすれば良いことは理解できると思います。これでOKなのですが、全く使わない変数(カウンタ)iを宣言し1ずつ増やすのは何か無駄ですね!? 実は今の場合カウンタは必要ありません。そこで、カウンタを用いない繰り返し文の書き方を次に学習しましょう。
カウンタを必要としない繰り返しには、「while文」を使います。プログラムを次のように変更してください。
void__fastcall TForm1::ButtonCalcClick(TObject *Sender)
{
while(SpinEditBact->Value<10000){
CSpinEditMinute->Value = CSpinEditMinute->Value + 1;
CSpinEditBact->Value = CSpinEditBact->Value * 2;
}
}
このプログラムの処理内容は上のfor文によるプログラムと全く同じです。実は、for文あるいはwhile文のいずれか一つだけでも、あらゆる繰り返し処理を実現できます。一般には、繰り返し回数などカウンタが必要になる場合はfor文、それ以外の場合はwhile文を用いると良いでしょう。
while(条件) { |
while 文は、「条件が成立している間は処理を繰り返す」という制御を行い、右のように書きます。
プログラムを実行して、結果を確かめてみましょう。ちゃんと「14分」という答が出ましたか?
条件によって処理が変わるという点で if 文と while 文は似ていますが、if 文は条件が成立してもしなくても1回きり、while 文は条件が成立している間何度でも繰り返す点が違います。
<if文>
<while文>
|
while(条件) { 繰り返し処理; } というように、繰り返し処理が1つしかない while 文は、if 文の場合と同様に、{ } を省略して次のように書くことが出来ます。 while(条件) 繰り返し処理; しかし、この書き方では、後で繰り返し処理を増やしたくなった場合に { }を付け忘れる可能性があります。これまで同様、たとえ処理が1つでも常に { }をつけることを勧めます。 |
1+2+3+4+… と足していくと、はじめて 10000 を超えるのはどこまで足したときでしょうか? プログラムを使って求めて下さい。(数列の和の公式は使わないで下さい。)
1年間に 5% の利子がつく (つまり預金が 1.05 倍になる) 口座があります(今となっては夢のような利率ですが・・・)。この口座に10000円を預けておくと、何年後に30000円以上になるでしょうか? 右のようなプログラムを作って答を求めて下さい。