第15回 いつも心にカーソルを「3.繰り返し」

15−3 繰り返し

人間が行えば「面倒だなぁ」と途中で投げ出してしまうような単純作業の繰り返し、そんな作業でも、文句を言わず働くのがコンピュータです。
NS Basicにも、そんな繰り返しを指示する(鬼のような)コマンドが2つほど用意されています。

1つは、For〜Nextというコマンドです
    
    For 変数 = 初期値 To 最終値 Step 刻み値
      {処理}
    Next
    
長ったらしい書式ですが、日本語訳すると『変数の値が、初期値から最終値を超えるまで繰り返しなさい』という指示です。最後の刻み値は、変数の値を変化させる度合いで、『初期値に刻み値だけ加え(減らし)続けて、最終値になるまで』という意味です。
例えば、
    
    For i = 0 To 9 Step 2
      {処理}
    Next
    
とした場合、刻み値がですから、変数の値は 0,2,4,6,8と変化し、{処理}の部分が5回繰り返されることになります。
また、この刻み値は小数でも、マイナスの値でも構いません。
    
    For i = 10 To 0 Step -1
      {処理}
    Next
    
この場合、変数は 10,9,8,7,6,5,4,3,2,1,0、と、まさにカウントダウンですが、このように負の刻み値を設定しても問題ありません。
ちなみに、この変数iのことを『カウンタ』ということもあります。

For〜Nextの正式な書式としては「Step」で刻み値を指定しますが、刻み値が 1 の時に限って STEP の部分を省略してもエラーにならないような取り決め(?)が出来ていますので覚えておいて下さい。
また、Stepについて、次のような例もあります。
    
    For i = 0 To 10 Step -1
      {処理}
    Next
    
このように初期値よりも最終値が大きいのに、刻み値がマイナスでも間違いではありません。
プログラムの動作上は問題があるかもしれませんが、BASICの文法上は誤りではありませんので、コンパイル時にエラーにならない訳です。
ただし、動作上、このループは1回も繰り返しを行いませんので、プログラムの作成者から見れば(たぶん)誤りです。
こういうコンパイル時に出ないエラーやミスは、時として探すのが困難になりますので、特に注意すべきポイントだと思います。

 さて、For〜Nextが開始値・最終値により決められた回数を繰り返すコマンドであるのに対し、回数の決まっていない場合には、Do〜Loopを使います。
NS Basicでは2通りの書式が用意されています。
    
    【書式1】
          Do While 条件
         {処理}
          Loop
    
    【書式2】
          Do Until 条件
         {処理}
          Loop
    
For〜Nextと同じ図のようですが、原則として、ループの外で繰り返し回数が決まっているのが For〜Next、ループの中で繰り返しを終了させる条件が決まるのが Do〜Loopです。
 Do〜Loopには2通りの書式が用意されていますが、この両者の違いは、単純に終了を判定する方法にあります。
Whileを使うと条件が「成り立っている間」繰り返し、Untilは、その逆で、条件が「成り立っていない間」繰り返します。
「成り立っていない間」とは、分かりにくい日本語ですが、これは「成り立つまでの間」繰り返します、と紹介した方がわかりやすいでしょうか。
どちらにしろ、繰り返しを終了する条件が決まっていても、いつ、その条件が成り立つのかわからない、という状況で使用します。

ゴチャゴチャしてきましたので、少し整理しながら進めましょう。
まず、Do〜Loopの働きですが、例えば、サイコロを転がして3が出るまでの間繰り返す、という処理を考えて見ると、次のようになります。
    
    Do Until サイコロ=3
    
     (サイコロを振る)
    
    Loop
    
Whileを使えば、次のようになります。
    
    Do While サイコロ<>3
    
     (サイコロを振る)
    
    Loop
    
これを見て、お分かり頂けるかと思いますが、WhileとUntilは逆の関係になっています。
したがって、どちらか一方だけを使うように習慣付けしていれば、特に問題なく扱うことが出来ます。
また、Do〜Loopは、文字通り『繰り返し』を意味する『ループ』から作られたコマンドだと思いますが、一般にループといった場合、このDo〜Loopはもちろん、For〜Nextやその他、繰り返し行われる処理のことをまとめてループと呼びます。
このサイコロを使ったループ処理、For〜Nextでは実現しにくいことが、お分かり頂けると思いますが、このForとDoの差をよく理解して使い分けましょう。


細かい話ですが、先ほどのサイコロのサンプルでは1回もサイコロを振らないうちから条件判定を行っていますよね?
このサンプルでは、場合によっては、ループに入る前に条件が成立して、Do〜Loopの中に入らないまま、処理が進んでしまう場合があります。
そういった場合には、適切な初期値を与えて、必ずDo〜Loop内の処理を実行させるという手もありますが、Visual BASICなどではそういう場合に便利な別の書式があります。
    
    【書式3】
          Do
         {処理}
          Loop While 条件
    
    【書式4】
          Do
         {処理}
          Loop Until 条件
    
こちらの書式だと、一度、Doコマンドを通過してから条件をチェックしますので、必ず1回はDo〜Loop内の処理が実行されます。
場合によっては便利な書式ですが、残念ながら、NS Basicの現バージョンには用意されていません。

さて、NS Basicに戻りましょう。
繰り返しの途中で、どうしても抜け出したい場合が発生しますが、DoでもForでも途中で抜け出しができるコマンドがキチンと用意されています。
次のコマンドを実行すれば即座にループから抜けることが可能です。
    
    【Doの場合】
          Exit Do
    
    【Forの場合】
          Exit For
    
どちらも回数や条件によって、いずれはループから抜けられるのに途中で抜け出すコマンドが用意されているのは不思議な気もしますが、ループを終わらせる条件が1種類ではない時に使います。
例えば、配列変数Am(1)〜Am(20)に数字が入っていて、どれかが10と等しいか探す時は、次のように、For〜Nextを使って最後まで検索しなくても、途中で見つかればループを続ける必要がありませんので、Exit Forで抜け出せばよい訳です。
    
    For i=1 To 20
        If Am(i)=10 Then
            Exit For
        End If
    Next
    
また、Do〜LoopではWhileやUntilといった条件部分を省略した次の書式も使えますので、Exit Doの必要性が、より明確になります。
    
    Do
        {処理}
    Loop
    
前後に条件がないため、具体的には次のようにExit Doを使ってループから抜けます。
    
    Do
    
        {処理}
    
        If 条件 Then
            Exit Do
        End If
    
    Loop
    
もし、このような場合に Exit Doを入れ忘れてしまったら、電池が切れるまで処理は繰り返されます。
オートパワーオフのイベントもDo〜Loopの中で処理をしている間は保留されますので、本当に電池が切れるまでループしています。
こうなった場合は、リセットしか受付けませんが、Exit Doを忘れていなくても、条件式を作り間違えて永遠に条件を満たさない場合も同じように永遠にループが続きます。
このようなループを『無限ループ』と言いますが、開発中の発生はともかく、プログラムとして公開するときには絶対に発生させないよう心がけましょう。
一応、補足ながら、Do〜Loopなどに起因する無限ループによって、本体やプログラムが壊れることはありませんので、慌てずリセットピンを探せば十分対応できます。

このように、2種類の方法が用意されている繰り返しですが、その使い分けの境界はあまりありません。
しかし、繰り返しの『回数』が決まっている場合には「For〜Next」を、繰り返しの『条件』が決まっている場合には「Do〜Loop」を使うと覚えておけば良いでしょう。

前へ     目次へ     次へ

第15回 いつも心にカーソルを「3.繰り返し」