連載
» 2014年10月08日 17時32分 公開

第6回 繰り返し処理(1): while/do ... while文TypeScriptで学ぶJavaScript入門(3/5 ページ)

[羽山博,著]

while文を確実に書くための考え方

 プログラミングにある程度慣れると、あまり意識せずにwhile文などの繰り返し処理が書けるようになるが、最初のうちは、理屈は分かっていても実際に書くとなると途方に暮れてしまうことが多い。そのような場合は、繰り返しを意識せずに、処理そのものがどういう順序で実行されるかを書き出してみるとうまくいく。

 例えば、上記のプログラムでやっていることを日本語で書き下してみると次のようになる。

図4 処理そのものの流れを順に書き出してみる 図4 処理そのものの流れを順に書き出してみる

 このように書くと、繰り返しのパターンが見えてくる。慣れないうちは、以下のように考えてしまうが、これではうまくいかない。

図5 同じパターンを見つけて処理をまとめてみる(うまくいかない例) 図5 同じパターンを見つけて処理をまとめてみる(うまくいかない例)

 while文の形式を見れば、条件となる式が最初に書かれていることに気付くだろう。そこで、条件が先頭になるように区切る。最初の処理だけがパターンから外れるので、特別扱いになるが、気にせず区切っていこう。

図6 同じパターンを見つけて処理をまとめてみる(うまくいく例) 図6 同じパターンを見つけて処理をまとめてみる(うまくいく例)

 同じパターンの部分を素直に1つにまとめると、繰り返し処理の骨格が出来上がる。条件の部分をwhile文の()の中に書いて、それ以外の文は{}の中に書けばよい。ただし、while文は条件が成り立っている間繰り返すので、条件には終了条件(乱数が6ならば終わり)を書くのではなく、繰り返しを実行する場合の条件(乱数が6でない)を書くことに注意。パターンから外れた最初の1文もちゃんと書いておこう。

図7 同じパターンの部分を1つのwhile文にすると骨格が出来上がる 図7 同じパターンの部分を1つのwhile文にすると骨格が出来上がる

 最初に示したプログラムと見比べてみると、この書き方とそのまま対応していることが分かる。このように順に考えていけば、それほど頭を使うこともなく、繰り返し処理が書ける。実際のところ、繰り返し処理の書き方にはすぐに慣れてしまうので、毎回毎回、このような手順で骨格を作っていく必要はないが、どう手を付けていいか悩んでしまう場合には、この手順を思い出してみるといいだろう。

[コラム]無限ループにご注意

 while文では、条件として指定する式がtrueの間、文を繰り返して実行するので、式がfalseにならないと無限に繰り返しが実行されてしまいます。いわゆる無限ループに陥ってしまうわけです。無限ループに陥ると、プログラムからの応答が返ってこないので、Playgroundなどの開発環境の操作もできなくなってしまいます。

 例えば、最初のプログラムの条件を以下のように書いてしまったとします。

while(6){
  ...
}

無限ループになってしまうwhile文の例(その1)

 「dice!=6」と書くべきところを、間違って「6」だけしか書かなかったというわけです。JavaScriptでは、0以外がtrueになり、0がfalseになるので、この条件は常にtrueとなってしまいます。従って、繰り返し処理が永久に終わらないことになります。whileの部分を以下のように書いても、無限ループになってしまいます。

while(dice = 6){        // 正しくはdice != 6
  ...
}

無限ループになってしまうwhile文の例(その2)

 変数diceの値が6でない間、というつもりで条件を書いたのですが、間違って、代入の「=」演算子を使ってしまいました。従って、常に変数diceに6が代入され、式の値として6が返されるので、条件は常にtrueとなり、やはり無限ループになってしまいます。

 等しいかどうかを調べるための比較演算子は「==」または「===」です。また、等しくないかどうかを調べるための比較演算子は「!=」または「!==」です。なお、このようなプログラムを書いてもPlaygroundではエラーにはならず、プログラムはJavaScriptにコンパイルされます。十分な注意が必要です。

 万一、無限ループに陥って反応がなくなった場合は、プログラムを強制終了させる必要があります。Google Chromeでは、反応がなくなってしばらくすると以下のようなメッセージが表示されます。ここで[ページを強制終了]ボタンをクリックすれば、無限ループを停止させられます。次にエラー画面が表示されますが、プログラムから開いたタブやウィンドウをそのまま閉じれば、Playgroundのページに戻れます(Playgroundのページもエラーになっている場合は[再読み込み]ボタンをクリックすると、エラーから回復する場合があります。[再読み込み]ボタンをクリックしても回復しない場合はPlaygroundのページを再度開く必要があります)。

図8 無限ループなどでページからの反応がなくなった場合に表示されるダイアログボックス(Google Chromeの例) 図8 無限ループなどでページからの反応がなくなった場合に表示されるダイアログボックス(Google Chromeの例)

 Internet ExplorerでPlaygroundを開いている場合は画面の下の方に「Webページが応答しません。」というメッセージと[Webページの回復]というボタンが表示されます。ボタンをクリックするか、プログラムから開いたタブやウィンドウを閉じれば、無限ループを停止させられます。何も表示されないままのときには、そのタブを閉じると、Playgroundに戻れます。


while文を簡潔に書く

 最初のプログラムでは、乱数を発生させる同じ文が2カ所に出てくるので、多少冗長に感じられるかもしれない。これを簡潔に書くには、次の2つの方法がある。

  • while文の「式」の部分に乱数を発生される文を書く
  • 乱数を発生させる文を関数にまとめる

 関数についてはあらためて説明することになるが、併せて示しておこう。以下のように書き替えると、最初の乱数を作る文をwhile文の前に書く必要がなくなる。また、変数diceも不要になる。

var count: number = 0;
while ((Math.floor(Math.random() * 6) + 1) != 6) {
  count++;
}
alert(count);
window.close();


 この書き方では、while文の条件が複雑になってしまう。そこで、乱数を発生させる処理を別の関数にするとスッキリとしたプログラムになる。

var count: number = 0;
while (dice() != 6) {   // (3)
  count++;
}
alert(count);
window.close();

function dice(): number {       // (1)
  return Math.floor(Math.random() * 6) + 1;       // (2)
}


 (1)では「function」の後に、作成したい関数の名前を書く。ここでは、「dice」という関数名にした。関数名の後にある「()」の中には仮引数(関数に与えられた値を受け取るための変数名)を書くのだが、この関数に与える値はないので何も書いていない。注目すべきは、その次だ。TypeScriptでは、「:」に続けて、関数が返す値のデータ型も指定できる。この書き方は変数を宣言したときの書き方と同じである。

 (2)では関数が返す値をreturn文の後に書いている。1以上6以下の乱数を返すというのは説明するまでもないだろう。

 このようにして関数を作っておけば、関数名と実引数を指定するだけで関数が呼び出され、値が返される。(3)の中で、このdice関数を呼び出して、乱数を求めている。

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。