Section 1.11 繰り返し処理(その2)

今回も繰り返し処理なんだよね?
うん。
今回は for を使って繰り返し処理をやるよ。
ふぉー?
for は基本的に while と同じなんだけど、 条件とかを指定する部分が while よりちょっと複雑なんだ。
例えば、前回1〜5 を表示するスクリプトを for を使って書くとこうなるよ。

for を使った繰り返し処理の例>

var i;
for(i = 1; i <= 5; i++)
{
    System.inform(i);
}

for の後ろのカッコの中に式が3つもあるね。
うん。for のカッコの中は『;』で3つの部分に区切られてるんだ。
まず、左側が『繰り返しを始める前に実行する式』を書く部分。
i = 1』ってことは、 繰り返しを始める前に i1 にしとくってこと?
ん、そういうこと。
で、真ん中のが while にもある条件式。
確かにここは while の条件式と同じ『i <= 5』だね。
で最後に、右側が『繰り返す部分の最後で実行する式』。
つまり inform メソッドを実行した後、条件式をチェックする前に実行する式ってこと。
inform メソッドで i の値を表示した後に、 『i++』を実行してから、『i <= 5』かどうかをチェックするってことだね。
そ。for の動作をまとめるとこんな感じ。

for を使った繰り返し処理の流れ>

forを使った繰り返し処理の流れ

あと、繰り返し処理の中身に命令が1つしかない時は {} は省略できるし、 for の左側で変数を宣言することもできるから、もっと簡単にこう書けるよ。

for(var i = 1; i <= 5; i++)
    System.inform(i);

確かにシンプルになったね〜。
ただ、こう書くと ifor の外で使えなくなっちゃうけどね。
そうなの?
うん。
for の中で宣言した変数は for の繰り返しの中でしか使えないんだ。
ま、でも別に for の外で使う必要がない時はこう書くことが多いかな。
なるほどね〜。
あと、for の左側・条件式・右側は必要なければ省略してもいいんだ。
条件式が省略されると真だとみなされるから、for(;;) って書くと無限ループになるよ。
じゃあ break でループから抜けられるの?
うん。breakcontinuewhile の時と同じように使えるよ。
あ、そうなんだ。
繰り返しについてはこんなところかな。
じゃ、今回は for を使ってもうちょっと厳密に入力をチェックするスクリプトを書いてみよっか。
厳密にチェックするって…?
単項 + 演算子は、数値と見なせない文字列も無理矢理数値に変換するんだ。
例えばこのスクリプト。

System.inform(+"abc");
System.inform(+"123xyz");

確かにどっちも数値じゃないね。
ちょっと実行してみて。
うん。
……最初は「0」で、次は「123」って表示されたよ。
単項 + 演算子は、文字列を先頭から見ていって、数値と見なせるところまでを数値に変換するんだ。
もし先頭の文字が数値と見なせなかったら 0 になるよ。
じゃあ、"abc" は最初の a が数値じゃないから 0 になって、 "123xyz"123 までが数値とみなせるから 123 になるってことだね。
うん、そゆこと。
だから、今回は入力に数字以外の文字が含まれてたら、正しくない入力って見なすようにするわけ。
うん、わかった。
でも、どうやってそんなチェックするの?
charAt っていうメソッドを使って、1文字ずつチェックしていくの。
charAt ってどんなメソッドなの?
charAt は文字列の中の任意の1文字を取得するメソッドで、こんなふうに使うんだ。

<入力された文字列を1文字ずつ表示するスクリプト>

var message = System.inputString("文字列を入力してください。""""");

if(message !== void)  // キャンセルボタンが押されたら何もせずに終了します
{
    for(var i = 0; i < message.length; i++)
        System.inform(message.charAt(i));  // i 文字目を取得して表示します
}

これを実行すると、入力した文字列が1文字ずつ表示されるよ。
ちょっと実行してみて。
うん。
じゃ、「ABC」って入力してみるね。
ん、で OK ボタンね。
OK…っと。
……うん、確かに「A」、「B」、「C」って1文字ずつ表示されたね。
charAt は文字列に対して使えるメソッドで、何文字目を取得するかっていう値を第1引数に指定するんだ。
ただし、最初の文字を『0文字目』って数えるから注意してね。
ってことは… for の繰り返しの中で0文字目、1文字目、って順番に表示されていくんだね。
あ、条件式のとこの『message.length』っていうのもメソッドなの?
ううん、これはメソッドじゃなくてプロパティ
文字列にはプロパティって言う、文字列の情報を取得するための機能があって、 length プロパティは文字列の文字数を取得できるんだ。
そうなんだ。
でもなんか見た目がメソッドと似てるね。
確かにね。
ここでは詳しく説明しないけど、とりあえず名前の後ろにカッコが付くのがメソッドで、付かないのがプロパティって思ってて。
うん、わかった。
じゃ、数値が入力されたかどうかを判定するように、このスクリプトを書き換えてみるね。
あと、ここで言う数値は 0 以上の整数ってことにするね。

<入力された文字列が数値(0 以上の整数)かどうかを判定するスクリプト>

var message = System.inputString("数値を入力してください。""""");

if(message !== void)  // キャンセルボタンが押されたら何もせずに終了します
{
    var i, ch;
    for(i = 0; i < message.length; i++)
    {
        ch = message.charAt(i);   // i 文字目を取得します
        if(ch < "0" || ch > "9")  // ch が数字("0"〜"9")でない → 数値でない
            break;
    }

    if(i < message.length)
        System.inform("数値ではありません。");
    else
        System.inform("数値です。");
}

ずいぶん複雑になったねぇ…
ま、でも新しい命令とかは使ってないから解ると思うよ。
じゃ、とりあえず実行しとこっか。
うん。じゃ、実行。
最初は適当に数字を入力してみて。
じゃあ「2468」って入力して、OK。
……うん、「数値です。」って表示されたよ。
じゃ、次は数字以外の文字も入れてみて。
今度は「123xyz」って入力して、OK。
……今度は「数値ではありません。」って表示されたね。
ん、OK だね。
じゃ、スクリプトの説明するね。
うん。
まず、for の繰り返し部分の1行目の…

ch = message.charAt(i);

ってのが何してるかは分かるよね?
えっと、入力された文字列の i 番目の文字を ch っていう変数に代入してるんだよね?
ん、そう。
それじゃ、その次の if ね。

if(ch < "0" || ch > "9")  // ch が数字("0"〜"9")でない → 数値でない
    break;

これって、文字列同士を比較してるんだよね?
数値に直してから比較した方がわかりやすいんじゃない?
さっきも言ったけど、単項 + 演算子は、 文字列の1文字目が数値と見なせなかった場合は 0 になるから、数値に直すと 『+ch』が 0 だった場合に、 ch が数字以外の文字か "0" かの区別がつかなくなっちゃうんだ。
あ、そっか。それじゃ数値に直してから比較できないね。
…でも文字列同士の比較ってちょっと特殊なんでしょ?
そ。§1.9 で言ったように、文字列同士の比較には文字コード順っていう順序が使われるんだ。
でも、文字コードについて説明すると長くなるし結構ややこしいから、ここでは簡単に説明するね。
うん、わかった。
文字コード順に文字を並べると、こんなふうになるんだ。

<文字の順序(文字コード順)>

←小さい                          大きい→

…… - . / 0 1 2 3 4 5 6 7 8 9 : ; < ……

文字の種類はいっぱいあるから、ホントはもっと長〜い列になるんだけど、 数字の近くの順番はこんな感じになってるんだ。
えっと、じゃあ "/""0" より小さくて、 ":""9" より大きいってこと?
ん、そういうこと。
だから、もし ch が数字じゃなかったら、ch"0" より小さいか "9" より大きくなるってワケ。
なるほど、だから『ch < "0" || ch > "9"』 が真になったら ch が数字じゃないってわかるんだね。
そ。で、1文字でも数字じゃない文字があるって判ったら、 その文字列は数値じゃないってことだから、もうそれ以上は文字をチェックする必要がなくなるんだ。
あ、だから break して for のループから抜けてるんだね。
そうそう。
そーいえば、メッセージを表示するとこの『i < message.length』っていう条件式はどうしてこうなるの?
入力された文字列に数字以外の文字が入ってなかったら、break しないよね?
うん、そうだね。
じゃあ、break しなかったら、for ループから抜けた時 i の値はどうなってると思う?
えっと… for の条件式が 『i < message.length』で、 これが偽になったらループから抜けるんだから…
ループを抜ける時には、i の値は message.length になってるのかな…?
ん、そのとーり。
じゃあ、途中で break したら?
その時は、条件式が真になってるわけだから…、 imessage.length より小さいんだよね。
あ、だからその時は『i < message.length』が真になるんだ。
そ。そういうこと。
だから、こう書いても OK。

var message = System.inputString("数値を入力してください。""""");

if(message !== void)  // キャンセルボタンが押されたら何もせずに終了します
{
    var i, ch;
    for(i = 0; i < message.length; i++)
    {
        ch = message.charAt(i);   // i 文字目を取得します
        if(ch < "0" || ch > "9")  // ch が数字("0"〜"9")でない → 数値でない
            break;
    }

    if(i == message.length)   // 文字列の中身が全部数字だと break しないので i == message.length が真になります
        System.inform("数値です。");
    else
        System.inform("数値ではありません。");
}

確かにこう書いても同じ結果になるね。
それじゃ、前回のスクリプトを書き換えてみよっか。
do〜while の所を書き換えればいいんだよね。
ん、そだね。
ん〜っと、基本的にはさっきのスクリプトをそのまま当てはめればいいんだから…

var value;

do
{
    // 正しい値が入力されるまでこの部分を繰り返し実行します
    value = System.inputString("何分後?""1 以上 1439 以下の数字を入力してください。""");
    if(value !== void)
    {
        var i, ch;
        for(i = 0; i < value.length; i++)
        {
            ch = value.charAt(i);     // i 文字目を取得します
            if(ch < "0" || ch > "9")  // ch が数字("0"〜"9")でない → 数値でない
                break;
        }
    }
}while((value !== void) && (i < value.length || (+value < 1 || +value > 1439)));

if(value === void)
{
    // value が void → キャンセルボタンが押された時の処理をします
    System.inform("キャンセルされました。");
}
else
{
    // value が void でない → OK ボタンが押された時の処理をします
    value = +value;
    var d = new Date();
    var hour = d.getHours();
    var minute = d.getMinutes() + value;
    hour += minute \ 60;
    minute %= 60;  
    hour %= 24;  
    System.inform("今から " + value + " 分後は " + hour + " 時 " + minute + " 分です。");
}

こんな感じでどうかなぁ?
あっ、まだアレの説明してなかった…
? なんか言った?
ううん、なんでもないよ。
ま、とりあえず実行してみたら?
う、うん…。じゃあ実行するね。
まずは「100」って入力して、OK。

<実行結果>

エラーメッセージ:『メンバ"i"が見つかりません』

えっ!? これどういうこと!?
例外が起きちゃったんだね。
例外?
いわゆる『エラー』のことだよ。
TJS のルールに合わないスクリプトを実行したりすると起こるんだ。
とりあえず、コントローラの×ボタンでプログラムを終わらせて。
コントローラ?
これのこと。
右端の×ボタンを押すとプログラムを強制終了させられるよ。

<コントローラ>

コントローラ

あ、ほんとだ。終了できたね。
じゃあ、何でエラーが起きたかなんだけど…
うん、なんで?
それは次回説明するね。
えっ、次回に続くの!?


前へ | TOP | 次へ