Sc283(1) 情報科学応用演習I 資料 (Part 4) 

[解説] 仕事手順の典型的パターン(その3: 反復処理)

同じ(あるいは,良く似た)一連の手順を何度も繰り返すような処理を反復処理と呼ぶ. 反復の仕方としては,

などの場合がある.いずれにしても, 繰り返しを永遠に続けるようなプログラムを書かないように注意する必要がある (繰り返しを永遠に続けることを「無限ループ」と呼ぶ).

while ステートメント

while ステートメントは,繰り返しのたびに論理式を計算し, その値が真(true)である間は繰り返しを続行するような処理手順を記述するものである.

JavaScript の while ステートメントの基本的な書き方は以下の通りである.

while (論理式) 反復パート
flow of while

また,その流れ図を右に示す.

この while ステートメントは,以下のような順序で実行される.

1. 論理式を計算する
1-a. 結果が真なら 2. に進む
1-b. 結果が偽なら,この while ステートメントの実行を終えて先へ進む
2. 反復パートを実行して 1. に戻る

この 反復パート は, if ステートメントの true パートなどと同様にブロック (複数ステートメントを並べて { } でくくったもの) を用いるのが一般的である.

また,反復の条件を表す 論理式 は, いずれは偽になるようにしておかないと,反復が止まらなくなって無限ループに陥ることになるので, 注意が必要である.

以下に例を示す.(こちらで実行できる流れ図はこちら

var i;
i=1;
while (i<=10) {
  document.write("i = ");
  document.writeln(i);
  i=i+1;    // i++; や i+=1; としても同じ(→特殊な代入)
}

(参考: 繰り返し(while) in とほほのJavaScriptリファレンス)

do-while ステートメント

do-while ステートメントも while ステートメントと同じように, 繰り返しのたびに論理式を計算して,その値が真(true)である間は繰り返しを続行する. ただし,while ステートメントとは異なり,論理式の計算は反復の末尾で行う.

JavaScript の do-while ステートメントの基本的な書き方は以下の通りである.

do 反復パート while (論理式);
flow of do-while

また,その流れ図を右に示す.

この do-while ステートメントは,以下のような順序で実行される.

1. 反復パートを実行する
2. 論理式を計算する
2-a. 結果が真なら 1. に戻る
2-b. 結果が偽なら,この do-while ステートメントの実行を終えて先へ進む

なお,while ステートメント等と同様に,反復パートブロック を用いるのが一般的である. また,やはり,反復の条件を表す 論理式 は, いずれは偽になるようにしておくことも必要である.

以下に例を示す.(こちらで実行できる流れ図はこちら

var i;
i=1;
do {
  document.write("i = ");
  document.writeln(i);
  i=i+1;    // i++; や i+=1; としても同じ(→特殊な代入)
} while (i<=10);

(参考: 繰り返し(do) in とほほのJavaScriptリファレンス)

while と do-while

flow of do-while(2)

while と do-while の違いは,反復条件の論理式を計算するタイミングのように見えるが, いずれの場合も,計算結果が真であれば再び反復パートを実行するし, 偽であれば反復を終了するので,その点ではあまり大きな違いはない.

見方を変えれば,while と do-while の違いは, 反復を開始するポイントの違いと見ることもできる. 上に挙げた do-while の流れ図を,接続の関係は変えずに変形すると, 右のような流れ図も作成できるが,これと,while の流れ図とを比較してもらいたい. そうすれば do-while は, while の最初の反復の最初の条件判定を素通りしたものともみなせることがわかるだろう.

つまり,do-while は,最初の反復だけは無条件に実行するような while ともみなせるのである.

for ステートメント

反復処理の中には,反復を制御するための変数 (制御変数) を用意して, その変数の内容を反復ごとに更新し, その変数が一定の条件を満たす間は反復を繰り返すようなタイプのものがある. 例えば,反復の回数を数える変数を用意しておき, その回数が一定値に達するまで繰り返すような場合である.

そのような反復処理を記述するために,JavaScript では for ステートメントが用意されている.

JavaScript の for ステートメントの基本的な書き方は以下の通りである.

for (式1 ; 式2 ; 式3 ) 反復パート
flow of for

また,その流れ図を右に示す.

この for ステートメントは,以下のような順序で実行される.

1. 式1を計算(実行)する (初期設定)
2. 式2を計算する (反復条件)
2-a. 結果が真なら 3. に進む
2-b. 結果が偽なら,この for ステートメントの実行を終えて先へ進む
3. 反復パートを実行する
4. 式3を計算(実行)して 2. に戻る (制御変数等の更新)

for ステートメントの典型的な使い方としては,例えば以下のようなものがある.
i++i=i+1 と同じ働き.(参考:特殊な代入))

var i;
for (i=1 ; i<=n ; i++) {
  反復パート
}

この場合,変数 i の値を 1 から順に 1 ずつ増やしながら, n を越えるまで反復することになるので, 反復パート は都合 n 回実行されることになる.以下に例を示す.(こちらで実行できる流れ図はこちら

var i;
for (i=1; i<=10; i++) { // i++ は i=i+1 と同じ働き(→特殊な代入)
  document.write("i = ");
  document.writeln(i);
}
for (i=10; i>0; i--) {  // i-- は i=i-1 と同じ働き(→特殊な代入)
  document.write("i = ");
  document.writeln(i);
}

また,後述する break ステートメント を用いることを前提に, 無条件の反復 (無限ループ) を記述したい場合,for の式を省略して for (;;) 反復パート とする場合も多い.

(参考: 繰り返し(for) in とほほのJavaScriptリファレンス)

break ステートメント

反復処理の途中で,強制的に処理を中断して反復を抜け出したい場合がある. そのような場合,JavaScript では break ステートメントを用いる.

JavaScript の break ステートメントの基本的な書き方は以下の通りである.

break;

while や do-while や for などの反復ステートメントの 反復パート の途中で break ステートメントが実行された場合,反復パート の残りの部分 (break より後の部分) は実行されずに, ただちにその反復ステートメントを終了してその次へ進む.(右下図参照)

flow of break

以下に例を示す.(こちらで実行できる流れ図はこちら

var i;
i=1;
for (;;) {  // break がなければ無限の反復
  document.write("i = ");
  if (i>10) break;
  document.writeln(i);
  i=i+1;    // i++; や i+=1; としても同じ
}

上の for (;;) { … } という表現は無条件の反復を意味し, 通常は無限ループになるため,使用は避けなければならないが, break ステートメントを用いれば,そのような無条件反復の途中からでも脱出できる.

break はまた,switch ステートメント の途中から脱出するためにも用いられる.

(参考: ループを抜ける(break) in とほほのJavaScriptリファレンス)

continue ステートメント

反復処理の途中では,その回の反復は中断して,次の回に移行したい場合もある. そのような場合,JavaScript では continue ステートメントを用いる.

JavaScript の continue ステートメントの基本的な書き方は以下の通りである.

continue;

while や do-while や for などの反復ステートメントの 反復パート の途中で continue ステートメントが実行された場合,反復パート の残りの部分 (continue より後の部分) は実行されずに,ただちに次の反復へ進む. ただし,その場合でも,for の 式3論理式 は計算(実行)されるので,厳密に言えば,

ジャンプすることになる.

flow of do-wile + continue
do-while での continue
flow of for + continue
for での continue

以下に例を示す.(こちらで実行できる流れ図はこちら

var i;
for (i=1; i<=10; i++) { // i++ は i=i+1 と同じ働き
  document.write("i = ");
  if (i%3==0) continue; // i が 3 で割り切れるときのみ continue を実行する
  document.writeln(i);
}

(参考: ループを続ける(continue) in とほほのJavaScriptリファレンス)

多重反復とラベル

flow of double loop

反復処理の反復パートの中に,さらに反復処理のパターンが埋め込まれているような場合, 多重反復と呼ばれる.

意味的には,「『反復処理』を反復するような処理」と考えると良い. 例えば,1枚の餃子の皮を作るのに,8回伸ばす動作が必要で,それを枚数分繰り返すようなものである. (右図参照)

多重反復における問題点は,内側の反復パート内で break や continue が実行された場合, それが「どの」反復に対するものかが曖昧になるということである.これを明示するためには, 反復のステートメントに名前を付けておき,break や continue でその名前を指定して 「どの」反復に対する break や continue であるかを示す.(下図参照)

flow of double loop + break/continue

この「ステートメントにつけた名前」はラベルと呼ばれる. どんなステートメントでも,その前にコロン(:)で区切って,このラベルをつけることができる.

  例: inner: while (…) { … }

break や continue では,break inner; のように, 後ろにラベルを付けて,対応するステートメントを指定する.

(参考: とほほのJavaScriptリファレンス: ループを抜ける(break)ループを続ける(continue)


[タスク] 最大値プログラム (2)

概要

5つの数値を入力し,反復を用いて,その中の最大の値を見つけて答えるプログラム. 入力には prompt() を, 出力には document.writeln() を用いる. ファイル名は js04-1.html とする.

備考

雛形を以下に示す.

<!DOCTYPE html>
<title>JavaScript Sample 4-1</title>
<body>
<script type="text/javascript">
<!--
// 変数の宣言
var i, x, m;    // i:カウント,x:入力,m:最大値

// 入力・計算
// ここは自分で考えよう.前回の課題(分岐処理 a)が参考になるはず.
// どのやり方が反復に向いているだろうか?

// ヒント・注意
//   1. 流れ図を書いてみよう.( - できれば自分で書いてから見てみよう)
//   2. prompt() で表示する文字列など瑣末なことは気にしなくてよい.
//      "?" だけでもOK.余力のある人は,"x1=?", "x2=?" とか聞いてくる
//      ようにしてみては?
//   3. prompt() で入力されるデータは文字列なので,Number関数で
//      数値に変換するとよい.
//   4. for を使うとスマートにできるが,while でもできる.

// 出力
document.writeln("<p>最大のものは" + m + " です.</p>");

// -->
</script>
</body>

例を以下に示す.リンクをクリックすれば実行できる.(別ウィンドウで実行される)

js04-1a.htmljs04-1b.html
各例のコードと流れ図


[タスク] 最大値プログラム (3)

概要

複数個の数値を入力し,反復を用いて,その中の最大の値を見つけて答えるプログラム. 個数はあらかじめ定めず,空 (空文字列) の入力でデータ入力の終了を表すものとする (少なくとも1個はデータを入力するものとする). 入力には prompt() を, 出力には document.writeln() を用いる. ファイル名は js04-2.html とする.

備考

雛形を以下に示す.

<!DOCTYPE html>
<title>JavaScript Sample 4-2</title>
<body>
<script type="text/javascript">
<!--
// 変数の宣言
var x, m;    // x:入力,m:最大値

// 入力・計算
m = Number(prompt("?"));

// ここは自分で考えよう.前回の課題(分岐処理 a)が参考になるはず.
// どのやり方が反復に向いているだろうか?

// ヒント・注意
//   1. 流れ図を書いてみよう.( - できれば自分で書いてから見てみよう)
//   2. prompt で表示する文字列など瑣末なことは気にしなくてよい.
//      "?" だけでもOK.
//   3. 入力はとりあえず文字列で変数に格納しておいて,空文字列かどうかの
//      判定に用いるとよい.大小の比較をするときには,Number関数で数値に
//      変換する必要がある.
//   4. while を使うのが一般的だが,意外に for (;;) { … } の中で
//      if (…) break; と言うのも悪くなかったりする.

// 出力
document.writeln("<p>最大のものは" + m + " です.</p>");

// -->
</script>
</body>

例を以下に示す.リンクをクリックすれば実行できる.(別ウィンドウで実行される)

js04-2a.htmljs04-2b.htmljs04-2c.html
各例のコードと流れ図


[課題] 反復処理

課題番号: 4-1, 4-2
課題名: 反復処理 a, b
ファイル名:task04-1.html, task04-2.html
締切: 次回の演習日の直前の日曜日,18:00まで

概要

下記の各々のプログラムを作成すること.

  1. (課題4-1) 入力された5つの数値の合計を(反復を用いて)求めるプログラム (task04-1.html).
    既出のタスク (最大値プログラム (2)) を参考にすること.
  2. (課題4-2) 入力された複数の (不定個の) 数値の合計を求めるプログラム (task04-2.html).
    既出のタスク (最大値プログラム (3)) に倣い, 空の入力でデータ入力の終了を表すものとする (少なくとも1個はデータを入力するものとする).

方法

入力には prompt() を, 出力には document.writeln() を用いる.

報告について

Moodle の各々の課題ページから各々のファイルを提出すること.ファイル名はすべて半角文字とする.