while文

目次
  • 解説
  • 1. ループとは
  • 2. while文
問題に挑戦!
進捗を変更する




解説

1. ループとは


配列のページで使用したサンプルコードを再度見てみましょう。

    static function practiceArray() {
        $sellCounter = [0, 0, 0]; // 配列型の変数を作成

        $sellCounter[0] += 10; // 区切られた0番目に10を加算
        $sellCounter[1] += 20; // 区切られた1番目に20を加算
        $sellCounter[2] += 30; // 区切られた2番目に30を加算

        Logger::echo($sellCounter[0]); // それぞれの「変数」で
        Logger::echo($sellCounter[1]); // 加算した値を
        Logger::echo($sellCounter[2]); // 保持できている
    }

最後の3行で配列の各要素の中身を順番にブラウザへ出力させていますね。よく見ると、添字が0から2に増えているだけで、それ以外は全く同じ処理を繰り返しています。単純な処理ではありますが、もしもこの配列の要素数が100個の場合、この行が100行必要になってしまいます!

これを解決するのがループLoop繰り返し)処理です。while文を使用した最も単純な構造のループ処理は以下のようになりますが、絶対に実行しないでください

while (true) {
    Logger::echo('止まりません');
}

これはブラウザに「止まりません」を延々と出力し続けます。キーワード「while」に続く丸括弧の中には、if文と同じように条件式を書きます。この条件式の評価結果がtrueの間、ブロック内をひたすら繰り返す、これがwhile文なのです。

さて、万一実行してしまった場合には、Chromeの該当タブを削除して強制終了させましょう。

2. while文


先ほど再掲したサンプルコードを次のように書き直してみましょう。

    static function practiceWhile() {
        $sellCounter = [10, 20, 30];                // 作成時に代入

        $counterIndex = 0;                          // 添字に使う変数
        Logger::echo($sellCounter[$counterIndex]);  // 添字に応じた
        $counterIndex++;                            // 添字を+1
        Logger::echo($sellCounter[$counterIndex]);  // 添字に応じた出力処理
        $counterIndex++;                            // 添字を+1
        Logger::echo($sellCounter[$counterIndex]);  // 添字に応じた出力処理
    }

添字の部分を変数counterIndexに置き換えると、出力処理の行はすべて同じとなり、counterIndexを増加させる処理もまた、同じコードの繰り返しとなりました。この繰り返しをwhile文を使用したループで置き換えてみましょう。

    static function practiceWhile() {
        $sellCounter = [10, 20, 30];

        $counterIndex = 0;                             // 添字に使う変数
        while ($counterIndex < 3) {                   // 添字が2以下の間
            Logger::echo($sellCounter[$counterIndex]); // 添字に応じた出力処理
            $counterIndex++;                           // 添字を+1
        }
    }

5行目の条件式がtrueの間、6行目と7行目が繰り返されます。つまり、counterIndex0の時、1の時、2の時の3回ブロック内が実行され、3になったら9行目以降に進む流れとなります。

このメソッド内でプログラムがどう実行されるか、表に整理してみましょう。

行番号行われる処理counterIndex
1メソッド内の処理を開始する-
2配列の変数sellCounterを宣言し、sellCounter[0]に10、
sellCounter[1]に20、sellCounter[2]に30を代入する
-
4変数counterIndexを作成し、0を代入する0
5counterIndexが2以下であるため、
条件式がtrueとなりブロック内に入る
0
6sellCounter[0]の中身=10を出力する0
7counterIndexを1増やして1にする1
85行目に戻る(while文のルール)1
5counterIndexが2以下であるため、
条件式がtrueとなりブロック内に入る
1
6sellCounter[1]の中身=20を出力する1
7counterIndexを1増やして2にする2
85行目に戻る(while文のルール)2
5counterIndexが2以下であるため、
条件式がtrueとなりブロック内に入る
2
6sellCounter[2]の中身=30を出力する2
7counterIndexを1増やして3にする3
85行目に戻る(while文のルール)3
5counterIndexが2以下でないため、
条件式がfalseとなりブロックをスキップ
3
9メソッド内の処理を終了してMainメソッドに戻る-

ループ処理や複雑な条件分岐などは、このように実行される行番号処理内容、そして重要な変数の中身の状態を表に書き出してみると、読み解きやすくなります。

counterIndexの値が3になったことにより、ひたすら繰り返されるwhile文から「脱出」できていることがわかると思います。つまり、条件式に使われているcounterIndexを変化させる処理を忘れてしまうと無限ループとなってしまいますので注意しましょう。

コードが整理され重複感はなくなりましたが、もうひとつ工夫をしてみましょう。条件式の中に固定で「2」を書いていましたが、「count」関数で取得できる要素数未満を条件とすることで、配列の要素数に影響されないコードとなります。

    static function practiceWhile() {
        $sellCounter = [10, 20, 30];

        $counterIndex = 0;                             // 添字に使う変数
        while ($counterIndex < count($sellCounter)) {                   // 添字が要素数未満の間
            Logger::echo($sellCounter[$counterIndex]); // 添字に応じた出力処理
            $counterIndex++;                           // 添字を+1
        }
    }

2行目で代入している要素の数をいろいろ変更して、その結果を確認してみてください。

問題

確認問題


確認問題

次のコードの中で、while文の使い方が正しく、
変数aの値が最終的に5となる構文はどれか。

実践問題


(1)VSCodeを起動し、ヘッダーメニューの「ファイル」>「フォルダーを開く...」から、「php_basic」プロジェクトを開いてください。
(2)php_basic」プロジェクトの「ArrayAndLoop.php」を開いてください。
※無い場合は「配列」を先に学習しましょう。
(3)ArrayAndLoop」クラス内に次のサンプルコードのメソッドをコピー&ペーストし、
mainから呼び出せるようにして、「http://localhost/php_basic/ArrayAndLoop.php」へのアクセスで表示されることを確認してください。
(4)コメント行に記された各問題文に対し、答えとなるプログラムコードを
問題文の次の空白行以降に書き込みまたは書き換えて
、ブラウザから確認してください。
    static function questionWhile() {
        // (問1)空白行にString型の配列変数arrayQ1を作成し、
        // 「あ」「い」「う」「え」「お」の5つの要素を代入してください。
        // 続けてwhile文によるループ処理を作成し、
        // 変数displayQ1にすべて結合させてください。
        $displayQ1 = '';

        Logger::echo($displayQ1);

        // (問2)空白行にwhile文によるループ処理を作成し、
        // arrayQ1から「あ」「う」「お」のみを
        // 変数displayQ2に結合させてください。
        // ただし、arrayQ1はそのまま使用し、加工や複製をしてはいけません。
        $displayQ2 = '';

        Logger::echo($displayQ2);

        // (問3)空白行にwhile文によるループ処理を作成し、
        // 変数displayQ3にarrayQ1の中身を逆順ですべて結合させてください。
        // ただし、arrayQ1はそのまま使用し、加工や複製をしてはいけません。
        $displayQ3 = '';

        Logger::echo($displayQ3);

        // (問4)空白行にwhile文によるループ処理を作成し、
        // 変数displayQ4にarrayQ1の中身の内、
        // 「え」のみを除いて逆順で結合させてください。
        // ただし、arrayQ1はそのまま使用し、加工や複製をしてはいけません。
        $displayQ4 = '';

        Logger::echo($displayQ4);
    }
実行結果例を表示
[2020/12/31 12:34:56] あいうえお
[2020/12/31 12:34:56] あうお
[2020/12/31 12:34:56] おえういあ
[2020/12/31 12:34:56] おういあ

正解


(問1)正解を表示
$arrayQ1 = ['あ', 'い', 'う', 'え', 'お'];
$idxQ1 = 0;
while ($idxQ1 < count($arrayQ1)) {
    $displayQ1 .= $arrayQ1[$idxQ1];
    $idxQ1++;
}

(問2)正解を表示
$idxQ2 = 0;
while ($idxQ2 < count($arrayQ1)) {
    $displayQ2 .= $arrayQ1[$idxQ2];
    $idxQ2 += 2;
}

(問3)正解を表示
$idxQ3 = count($arrayQ1) - 1;
while ($idxQ3 >= 0) {
    $displayQ3 .= $arrayQ1[$idxQ3];
    $idxQ3--;
}

(問4)正解を表示
$idxQ4 = count($arrayQ1) - 1;
while ($idxQ4 >= 0) {
    if (!($arrayQ1[$idxQ4] === 'え')) {
        $displayQ4 .= $arrayQ1[$idxQ4];
    }
    $idxQ4--;
}

正解プログラムコード全文を表示
    static function questionWhile() {
        // (問1)空白行にString型の配列変数arrayQ1を作成し、
        // 「あ」「い」「う」「え」「お」の5つの要素を代入してください。
        // 続けてwhile文によるループ処理を作成し、
        // 変数displayQ1にすべて結合させてください。
        $displayQ1 = '';
        $arrayQ1 = ['あ', 'い', 'う', 'え', 'お'];
        $idxQ1 = 0;
        while ($idxQ1 < count($arrayQ1)) {
            $displayQ1 .= $arrayQ1[$idxQ1];
            $idxQ1++;
        }

        Logger::echo($displayQ1);

        // (問2)空白行にwhile文によるループ処理を作成し、
        // arrayQ1から「あ」「う」「お」のみを
        // 変数displayQ2に結合させてください。
        // ただし、arrayQ1はそのまま使用し、加工や複製をしてはいけません。
        $displayQ2 = '';
        $idxQ2 = 0;
        while ($idxQ2 < count($arrayQ1)) {
            $displayQ2 .= $arrayQ1[$idxQ2];
            $idxQ2 += 2;
        }

        Logger::echo($displayQ2);

        // (問3)空白行にwhile文によるループ処理を作成し、
        // 変数displayQ3にarrayQ1の中身を逆順ですべて結合させてください。
        // ただし、arrayQ1はそのまま使用し、加工や複製をしてはいけません。
        $displayQ3 = '';
        $idxQ3 = count($arrayQ1) - 1;
        while ($idxQ3 >= 0) {
            $displayQ3 .= $arrayQ1[$idxQ3];
            $idxQ3--;
        }

        Logger::echo($displayQ3);

        // (問4)空白行にwhile文によるループ処理を作成し、
        // 変数displayQ4にarrayQ1の中身の内、
        // 「え」のみを除いて逆順で結合させてください。
        // ただし、arrayQ1はそのまま使用し、加工や複製をしてはいけません。
        $displayQ4 = '';
        $idxQ4 = count($arrayQ1) - 1;
        while ($idxQ4 >= 0) {
            if (!($arrayQ1[$idxQ4] === 'え')) {
                $displayQ4 .= $arrayQ1[$idxQ4];
            }
            $idxQ4--;
        }

        Logger::echo($displayQ4);
    }