Section 1.10 繰り返し処理(その1)

今回は、ちょっと新しいことに挑戦してみよ。
今回は何やるの?
入力された値のチェックだよ。
入力された値のチェック?
前回までのスクリプトは、入力された値を数値に変換して、そのまま計算に使ってたでしょ。
うん、そうだね。
でも、このスクリプトの目的はアラームを鳴らす時間を計算することだから、 『-1分後』とかだとおかしいでしょ。
まぁ、確かにそだね。
というワケで、今回は入力された値がおかしくないかチェックして、 もし値がおかしかったら入力をやり直してもらうようにするの。
で、正しい値が入力されるかキャンセルされるまでは、何回でも入力をやり直してもらうようにするから。
うん、りょーかい。
じゃ、そのためにまずは繰り返し処理について説明するね。
繰り返し処理って?
条件が成り立たなくなるまで同じ処理をずっと繰り返し実行することだよ。
繰り返し処理は while を使ってこんな感じに書けるんだ。

<繰り返し処理の例>

var i = 1;

while(i <= 5)
{
    // i が 5 以下の間、この部分が繰り返し実行されます
    System.inform(i);
    i++;
}

まずは実行してみよっか。
うん。
……「1」、「2」、「3」、「4」、「5」って表示されたよ。
つまり、5回繰り返されたってことだね。
ってことは…、 {} で囲まれた部分が5回実行されたのかな?
ん、そうだよ。
while の条件が成り立ってる間は、{} で囲まれた部分が繰り返し実行されるんだ。
条件って、『i <= 5』ってのだよね。
なんか if と似てるね。
条件式の書き方は if と同じだからね。
ただ、if と違うのは、 while の場合は条件式が真になってる間は繰り返し実行されるってところ。
じゃあこの場合は、i の値が 5 以下になってる間は inform メソッドと i++ が繰り返されるってことだよね。
そうそう。
i++』は覚えてる?
え〜っと、確か ++ はインクリメント演算子って言って、値を 1 増やすんだったよね。
そ。§1.6 で出てきたよね。
つまり、このスクリプトの動作はこんな感じになるね。

<このスクリプトの動作>

whileの動作を表すフローチャート

1回繰り返すごとに i の値が 1 ずつ増えるから、 「5」って表示された後に i1 増えて 6 になると、条件が成り立たなくなって終わるんだね。
ん、そういうこと。
じゃあここで問題。
えっ、もう問題?
まだ while の事しか聞いてないよ?
大丈夫、while の使い方が解れば出来るから。
そうなの?
うん。じゃあ問題ね。
whileinputString メソッドを使って、 何か文字列を入力して OK ボタンが押されるまで繰り返し入力を求めるスクリプトを書いてみて。
あ、あと最後に、入力された文字列を表示してね。
うわ、なんか難しそう…
え〜っと…まず何か文字列を入力して OK ボタンが押されるまで繰り返すんだから…、 繰り返しの条件式は逆にキャンセルボタンが押された場合に真になればいいんだよね?
あと OK ボタンが押されてても、何も文字が入力されてなかったら条件式は真になるよ。
あ、そっか。
えっと…何も文字が入力されてないってのはどうやったら判るの?
何も文字が入力されてないってことは、取得した文字列が空文字列になってるってこと。
空文字列については §1.5 参照ね。
あ、なるほどね。
キャンセルボタンが押された場合は void になるんだから、条件式は……
(message === void) || (message == "")』でいいのかな?
ん、OK。
じゃあ…こんな感じかな?

<文字列を入力して OK ボタンが押されるまで繰り返し入力を求めるスクリプト>

var message = System.inputString("何か入力してOKボタンを押してください。""""");

while(message === void || message == "")
{
    // キャンセルされるか、入力された文字列が空文字列だと、この部分を実行します
    message = System.inputString("何か入力してOKボタンを押してください。""""");
}

System.inform(message, "入力された文字列");

じゃ、確認してみよ。
うん。それじゃ実行するね。

<実行結果>

文字の入力ウィンドウ

最初は『てすと。』って入力してから OK ボタンを押すね。
ん。

表示されたメッセージ

ちゃんと『てすと。』って表示されたね。
じゃあ、次は何も入力せずに OK ボタン。

文字の入力ウィンドウ

えっと、また文字を入力するウィンドウが表示されたけど…これでいいんだよね?
OK だよ。じゃあ最後はキャンセルボタンだね。
うん。キャンセルボタンをクリック、と。

文字の入力ウィンドウ

キャンセルボタン押しても、また文字の入力ウィンドウが表示されたね。
うん、これで正解!
やった!
これでちゃんとスクリプトは書けたわけだけど…
なんかこのスクリプトってスッキリしてないと思わない?
えっ? う〜ん…そう言われれば、inputString を2回書かなきゃいけないから、 1行目の inputStringwhile の中に入れられれば、もっとスッキリ書けそうだね。
実は、そうする方法があるんだ。
え、あるの?
うん。
dowhile を使えば、 inputString は1回書くだけでよくなるよ。
dowhile
while は先に条件式を見てから、条件式が真なら繰り返しの部分を実行するけど、 dowhile は繰り返しの部分を実行した後に条件式を見るんだ。
こんなふうに。

<文字列を入力して OK ボタンが押されるまで繰り返し入力を求めるスクリプト(do〜whileバージョン)>

var message;

do
{
    // この部分は最低1回は実行されます
    message = System.inputString("何か文字を入力してOKボタンを押してください。""""");
}while(message === void || message == "");

System.inform(message, "入力された文字列");

あ、while が後ろに来てるね。
そ。だから条件式を判断する前に、dowhile の間の 繰り返しの部分が実行されるんだ。
なるほどね〜。確かにこれなら inputString を1回書くだけでいいね。
あ、でも whiledowhile ってどうやって使い分けたらいいの?
繰り返しの部分を最低1回は実行したい時に dowhile を使って、 それ以外の時は while かな。
そっか。今回は最低1回は文字列を入力してもらわなくちゃいけないから、dowhile の方がいいってことだね。
ん、そういうこと。
ま、でも別にどっちを使うかにこだわる必要はないから、使いやすいと思う方を使えばいいんじゃないかな。
うん、わかった。
じゃ、次は break
ぶれいく?
break はループからすぐに抜けたいときに使うんだ。
例えば、さっきのスクリプトを break を使って書き換えるとこんな感じ。

<文字列を入力して OK ボタンが押されるまで繰り返し入力を求めるスクリプト(breakバージョン)>

var message;

while(true)   // 無限ループ
{
    message = System.inputString("何か文字を入力してOKボタンを押してください。""""");
    if(message !== void && message != "")
        break;   // 文字が入力されたらループから抜けます
}

System.inform(message, "入力された文字列");

while の条件式が true になってるけど、これってどういうこと?
true っていうのは真っていう意味。
ちなみに偽は false ね。
じゃあ、条件式は真ってこと?
そ。『while(true)』ってのは、『条件式がいつでも真』ってことだから、 つまり無限ループってこと。
無限ループ!?
…ってことは、永久に繰り返されてループから抜けられなくなっちゃうんじゃないの?
うん、だから break を使うの。
break が実行されると、条件式に関係なくその場でループから抜けられるからね。
あ、じゃあ if の条件式が真になれば break が実行されるから、ループから抜けられるんだね。
ん、そう。
if の条件式は…まず『message !== void』だから、 『キャンセルボタンが押されてない』ってことだよね。
あと『message != ""』ってのは『入力された文字列が空文字列じゃない』ってことだよね。
言い換えると、最初のは『OK ボタンが押された』ってことで、次のは『何か文字が入力された』ってことだね。
それが && 演算子でつながってるから、 『何か文字が入力されてる状態で OK ボタンが押されたらループから抜ける』ってことになるわけだね。
そういうこと。
繰り返し処理って色んな書き方が出来るんだね。
でも、どの書き方にしたらいいのかわかんなくなりそう…
う〜ん、確かにどの書き方がいいか判断するのはちょっと難しいかもね。
まぁ、自分で書きやすそうと思う書き方でいいんじゃないかな。
うん、そうだね。
じゃ、最後に continue。これはループの途中で条件式をチェックする所にジャンプしたい時に使うんだ。
使い方はこんな感じ。

<文字列を入力して OK ボタンが押されるまで繰り返し入力を求めるスクリプト(continue使用)>

var message;

while(true)  // 無限ループ
{
    message = System.inputString("何か文字を入力してOKボタンを押してください。""""");
    if(message === void || message == "")
        continue;  // キャンセルされるか何も入力されなければ while の行に戻ります

    break;  // そうでなければループから抜けます
}

System.inform(message, "入力された文字列");

キャンセルボタンが押された場合と、文字を入力せずに OK ボタンを押した場合は continue が実行されるから、 次の break は実行されずに、先頭の while(true) に戻るんだ。
なるほどね〜。
でもなんかこのスクリプトって不自然じゃない?
ま、確かにこの場合は continue の後に1行しかないから、 continue は使わずにさっきみたいに break だけで書くのが普通だね。 continue はもっとループが長い場合に、ループの前半とかで先頭に戻りたい時に使うと便利かな。
だよね。
じゃ、これで while を使った繰り返し処理の説明は終わり。
次は前回のスクリプトに入力をチェックする機能を追加していくよ。
は〜い。
具体的には、入力された値を数値に変換した結果が 1 以上 1439 以下に なってるかチェックして、この範囲外になってたら、もう一回入力ウィンドウを表示して、入力をやり直してもらうっていう感じ。
1 以上ってのはわかるけど、何で 1439 以下じゃなきゃいけないの?
日付を考えてないからだよ。
? どういうこと?
1 日は 24 時間だから、分に直すと 1440 分。 だから今が 12 時ちょうどだとしたら、1440 分後は次の日の 12 時ちょうどだよね。
うん。そうなるね。
でも今書いてるスクリプトは、日付を考えてないから、今日の 12 時と次の日の 12 時の区別がつかないんだ。
だから、1440 分以上になると、ちゃんと指定した時間にアラームを鳴らせなくなるの。
なるほどね。だから 1439 分以下じゃないといけないんだ。
そういうこと。
じゃ、前回のスクリプトを書き換えて、入力をチェックする機能を追加してみて。
キャンセルされた場合も、もっかい入力ウィンドウを表示するの?
ううん。キャンセルされた場合はそのまま終わっちゃってOK。
わかった。
えっと… if より後は書き換えなくてもよさそうだから、1行目だけ書き換えるね。
うん。
あとは…最低1回は入力が必要だから、do〜while がいいかな。
そだね。
問題は条件式がどうなるかだよね…
え〜っと、『キャンセルボタンが押された場合』か『正しい数値が入力された場合』にループから抜ければいいんだから…… 条件式はその逆で、『OK ボタンが押された場合』で『数値が正しくない場合』に真になればいいんだよね。
うん、いい感じだね〜。
『OK ボタンが押された場合』は『value !== void』で、 『数値が正しくない場合』は『value < 1 || value > 1439』だから…

<入力チェック機能を追加したスクリプト>

var value;

do
{
    // 正しい値が入力されるまでこの部分を繰り返し実行します
    value = System.inputString("何分後?""1 以上 1439 以下の数字を入力してください。""");
}while((value !== void) && (+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。
……うん、ちゃんと 100 分後の時間が表示されたよ。
次は範囲外の数値を試してみよっか。
じゃあ『-1』で OK …… あ、また入力ウィンドウが表示されたよ。
次は『1440』で OK …… これもまた入力ウィンドウが表示されたね。
ん、OK だね。
じゃ最後はキャンセルボタン。
キャンセル…っと。
うん、「キャンセルされました。」って表示されたよ。
ん、これで完成だね!
ちなみに、同じ動作をするスクリプトを無限ループと break を使って書くとこんな感じ。

<入力チェック機能を追加したスクリプト(その2)>

var value;

while(true)  // 無限ループ
{
    value = System.inputString("何分後?""1 以上 1439 以下の数字を入力してください。""");
    if(value === void)
    {
        // キャンセルボタンが押されたら、メッセージを表示してループから抜けます
        System.inform("キャンセルされました。");
        break;
    }

    value = +value;
    if(value >= 1 && value <= 1439)
    {
        // 正しい値が入力されたら、時刻を表示してループから抜けます
        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 + " 分です。");
        break;
    }
}

へぇ〜、こんなふうにも書けるんだね。
while を使った繰り返し処理は、色々書いてみて自分に合った書き方を見つけてね。
はーい。
それじゃ、今回はここまで。
次回も繰り返し処理をやるよ。
えっ? また繰り返し処理なの?
繰り返し処理には while の他にもう1つあるんだ。
あ、そうなんだ。
というわけで、また次回ね!


前へ | TOP | 次へ