反復文の考え方

今回、1~10000までの数の和を求めるプログラムを作りたいとします。 まずは合計値を入れる「all」という変数を用意しますね。 そして、1~10000の和を計算する

all = 1+2+3+4+5+...10000

気が遠くなりそうな作業ですね。 おまけに、これだけたくさんの数を記入していけば、どこかでタイプミスも出そうなもの。

ただ、数学に強い方なら、これは計算で求める事が出来るでしょ、と思うかもしれません。 では、こんにちはという表示を100回に分けて出したければどうしますか?

System.inform("こんにちは")
System.inform("こんにちは")
……
System.inform("こんにちは")
System.inform("こんにちは")

やはり日が暮れそうなくらいコピーとペーストを繰り返す必要があります。

このようにある処理を複数回繰り返して行わせたい場合に反復文が便利なのです。

連接、選択、反復。この三つを習得できれば、大抵のプログラムが作れてしまいます。 心してかかりましょう。

while文の基本

まずは基本的な書式を見てみましょう。

while(条件式)
{
    //処理内容
}
				
while.png(7269 byte)

if文と書式は似ていますね。 if文とは違い、条件式の部分が「真」ならば{}内の処理を繰り返し行います。 では、数値の10~1までカウントダウンを行うプログラムの例を見てみましょう。

var num=10;
while ( num > 0 )
{
    // 変数numの値を表示(減算子『--』により値が1引かれる)
    System.inform("numの値は"+(num--)+"です");
}
				

変数numを、少し難しく使っていますので、一つ一つ処理を見ていきましょう。

(1)whileの括弧の中を評価
中には「>演算子」を使用した式「num > 0」が書かれています。 これはnumが0より大きければ真を返すものでしたよね? 最初のnumの値は10、という事は0より大きいので処理を行います。
(2)「num--」の処理
numの指定は「num--」と書かれています。 「--」が後ろにある!という事は、まずnumの値を返します。(ここでは10) そして、記号「--」によってnumの値から1を引きます。(ここでnumの値は9になります)
(3)「num--」が返した値を表示
「num--」が返した値は「10」ですので「numの値は10です」と表示し、最初の処理は終了します。 全てを「+」記号でくっ付け、文字列の加算を行っています。
(4)while()に指定した条件式を再度評価
ここがif文とは違うところですね。 この時点でのnumは9になっていますので、0より大きいです。 つまり、もう一度{}の中の処理を行います。(今度は「numの値は9です」と表示します)
(5)numが0になるまで繰り返し
同様に繰り返され、numが0になりました。 ここで「num > 0」を評価しますが、 変数numは0「より」大きくはないので、whileの処理を抜けて終わります。

無限ループに注意

while文を使う場合、()に指定する式に注意しなければなりません。 ()の中の式が真ならば繰り返して処理を行うという事は、 式の値に変動が無ければ延々と処理を続けるという事になってしまいます。 例えば……

while ( cnt ){ …処理… }

このように指定すると変数cntが真である限り、ずっと処理を行います。 このような状況を無限ループと呼び、プログラムの重大な不具合です。 これは、処理中で変数cntの値を「偽」に変えてやれば解決出来ます。

無限ループに陥ると、環境によっては吉里吉里が固まって応答しなくなったり、 最悪の場合OSすらフリーズしてしまう事だってあります。 ですから、反復文を使う時は「指定する式が偽になるか」を必ず確認しましょう。

一文には一つだけの意味を持たせる

慣れないうちは一つの文に複数の意味を持たせない事を推奨します。

例えば、最初のプログラムの場合。 表示するnumの値に「num--」を指定していますが、これは素直に次のように書けば分かりやすいですよね。

System.inform("numの値は"+num+"です");
num = num - 1;
//表示した後でnumから1を引く

「numから1を引くだけ」「numの値を表示するだけ」というように、 一つの文には一つだけの意味を持たせるように心がけるだけでも、プログラムは格段に読みやすくなります。

プログラムによっては、簡潔に記述したほうが実行速度が向上する例もありますが、 実行速度を気にするのはまだまだ早いです。 最初は一つ一つ、確実にプログラミングしていきましょう。

ループ変数を使う

一般的に、while文などで一定の処理を繰り返し行う場合、 処理を行わせる回数を制御する変数を用意するのが普通です。 例えば、次のプログラムは「挨拶を9回行う」プログラム例です

var i = 9;//ループする回数
while ( i )
{
    System.inform("こんにちは、お元気ですか?");
    --i;
}
				

ここで使われている「変数i」は、実際にループを繰り返す回数を指しています。 ()の中には変数iを指定していますから、変数iが偽になると処理を終えます。 処理の最後に「--i」とありますから、iから1を引いて処理が終わります。 この「--i」によって、変数iが偽(つまり0)になった時点で、while文のループは終了という事です。

このように、繰り返し回数を制御する為に使われる変数を特にループ変数と呼びます。 ループ変数は、必ず処理内で偽にさせないと、前述した無限ループとなりますので注意してください。 ループ変数は「i」「j」「k」のような文字を使う事が多いので、当入門でも従っておくことにします。

このプログラムは次のように書いても同じです。

var i = 0;//ループ変数。最初は0
while ( i < 9 ) // iが9より少なければ処理
{
    System.inform("こんにちは、お元気ですか?");
    ++i; //「++」になってる点に注意
}
					

ループ制御

時には、ある回数までループしたら表示を止めたり、 特定の回数の時だけ表示を止めたり…といった処理が必要になる場面があります。

そこで、ある条件ならば途中で処理を中止したり、 ある条件の場合は今回の処理を見送る、という制御方法がありますので紹介します。

処理を抜けるbreak

breakを見て「あ、なるほど!」と思った方は、前回のswitch文を理解できている人ですね。 breakって何だっけ?と思った方は、条件分岐(2) switchとその他を読み直してみると良いかもしれません。

while文でもこの「break」が扱えます。 switch文の時と同様に、breakが登場すると強制的に処理を終えます。図に表すと次のようなものです。

breakの動作

例えば、次の例では一回だけ「こんにちは!」を表示して終わります。 whileに指定した条件式は真(ここでは数値の1)である事を確認してください。

while ( 1 ) //1を指定。永久に式は「真」
{
    System.inform("こんにちは!");
     //下のbreakによって無限ループは回避される
    break;
}
					

この方法では、処理が一回しか行えません。これでは全く意味がないです。 そこで、処理を分岐させて「ある値なら処理を終える」というようにしたいのですが、使えそうな命令は何でしょうか?

そう、if文ですね。 プログラムでは様々な命令を組み合わせてプログラムを作ります。 これまでの知識で使えそうな処理はどんどん使いましょう。

という事で、次の例は「ループ変数i」が5になったら処理を抜けるプログラムです。

var i = 1;
while ( i )
{
    System.inform("現在"+i+"回目の処理です");

    if ( i == 5 )
    {
        break;
    }
    ++i;
}
					

処理を飛ばすcontinue

continueはbreakとは違い、処理を中断しませんが、今回の処理は見送るという制御方法です。

例えば、ある値が9の時には処理を行わない、という事を可能にします。 図に表すと次のようなものです。

continueの動作

次のプログラムは、ループ変数の値を9~1まで表示していきますが、 値が5の時だけは飛ばす、というものです。

var i = 9; // 9回処理をする
while ( i )
{
    if ( i == 5 )
    {
        --i; //見落としやすいポイント!
        continue;
    }

    System.inform("ループ変数iは"+i+"です");
    --i; // 最後に変数iから1を引く
}
					

「ループ変数は5です」という表示はされませんでしたね? これはcontinueによって処理が飛ばされた証拠です。

ここで注意したいのはif文の{ }の中にも「--i」がある事です。 このif文はwhile文の処理の最初に書かれています。 ですから、変数iが5になったら、最後の処理である「--i」が実行されずに戻ります。 という事は、変数iは5のままですよね? だから、もう一度if文を実行し……と永遠に続きます。これも無限ループですので要注意です。

上の例では、条件式は次のように書いても構いません。

while ( i > 0 )

むしろ、より分かり易いプログラムにするならば、 この書き方のほうが望ましいかもしれませんね。

do~while文

whileにはもう一つの文があり、「最初の一回は必ず処理をする」という書き方が出来ます。

do
{
    // 処理内容
}
while( 条件式 );
				

見た目が全然違うので戸惑うかもしれませんが、通常のwhile文と考え方は全く同じです。 違いは、最初に書いたとおり「一回は必ず処理をする」という事だけです。 言い換えるなら最初は条件式の判定をしないとも言えます。

例えば次のプログラムをみてください。

do
{
    System.inform("一度はこの文を表示します。");
}
while( 0 ); //条件式は0なので偽
				

条件式に0を指定しているので偽です。 なので、本来は処理されないはずですが、do~while文は一度は処理を行うので、 「一度はこの文を表示します。」と表示した後、条件式の判定に戻り、終了します。

do~while文の注意点は、while()の後にセミコロン(;)が必要だという事です。 通常のwhile文と異なる所なので覚えておきましょう。

do~while文は、一度処理させた後で条件式を評価するという特徴から、 名前入力などによく使われます。

  1. ユーザに名前入力を促す
  2. 名前を条件式で判定し、誤っていれば再度名前入力に戻す

キーボードから何かを入力させるプログラムは、かなり先で説明することになりますが、 とりあえず、do~while文の存在だけは記憶に留めて置いてください。

借金返済プログラム

あなたに借金が1000万円あったとして、1年に50万円ずつ返済します。 ただし、残りの借金額の2%分を毎年支払わなくてはなりません。

元金ではなく借金残額の2%ですので、最初は20万…返済する毎にその額は減っていきます。 この時、全額返済するのに必要な年数をwhile文を使って調べてみましょう。

var money=1000000; //借金額は100万円
var year=0; //返済に掛かる年数

while ( money > 0 )
{
    ++year;
    // 返済額から2%の利子を引いた分が実返済額
    money -= 500000 - ( money * 0.02 );
}
System.inform("全額返済に"+year+"年掛かります");
				

このように、計算機を使っても面倒な計算が簡単に行えるのもコンピュータの強みですね。