多重ループから抜ける方法

Full BASICには多重ループから脱出するための構文が用意されていません。
GOTO文を使わないで多重ループから脱出するのに次のような奥の手があります。

2重ループからの脱出

2重ループの場合,FORループとDOループの入れ子の形であれば,EXIT FOR,EXIT DOの使い分けで目的の処理が記述できます。
 問題は,DOの2重ループの場合と,FORの2重ループの場合ですが,FORループ,DOループは相互に書き換え可能なので,2重ループのうちの外側か内側かどちらか一方を書き換えれば上記の手法が使えます。

多重ループからの脱出

律儀な手法(その1)

 NEXT文の次の行で,同一の条件で再度EXIT FORを実行します。
 この手法は,多重のDO〜LOOPからの脱出にも使えます。

例 c0を超える最小のピタゴラス数を探す

100 INPUT c0
110 FOR c=c0+1 TO MAXNUM
120    FOR b=1 TO SQR(c)-1
130       LET a=INT(SQR(c-b^2))
140       IF a^2+b^2 = c THEN EXIT FOR
150    NEXT b
160    IF a^2+b^2 = c THEN EXIT FOR
170 NEXT c
180 PRINT c;"=";a;"^2 +";b;"^2"
190 END

 この手法を用いる場合には,NEXT文を実行して繰り返しを抜けたときには条件を満たさないこと,その条件は,再度,評価しても同じになることなどの確認が必要です。
 その確証が得られない場合は,フラッグ(スイッチとして用いる変数)を使います。

例 c0を超える最小のピタゴラス数を探す

100 INPUT c0
110 LET f=0
120 FOR c=c0+1 TO MAXNUM
130    FOR b=1 TO SQR(c)-1
140       LET a=INT(SQR(c-b^2))
150       IF a^2+b^2 = c THEN LET f=1
160       IF f=1 THEN EXIT FOR
170    NEXT b
180    IF f=1 THEN EXIT FOR
190 NEXT c
200 PRINT c;"=";a;"^2 +";b;"^2"
210 END  

 110行で初期値0を代入された変数fがフラッグです。f=1のときループを抜けるようにプログラムを書き,ループを抜ける条件が成立したときfの値を1に変えます。

律儀な手法(その2)

 Full BASICのFOR〜NEXTループは,制御変数の値が限界(FOR文のTO句に指定された数値)を超えると繰り返しを終了します。制御変数の値はくり返しを抜けた後も保持されるので,NEXT文の次の行で制御変数の値を調べれば,EXIT FOR文を実行して繰り返しを止めたのか,最後までくり返して終了したのか分かります。そこで,もし,EXIT FOR文を実行して繰り返しを止めたことがわかったら,再度,EXIT FOR文を実行します。

例 c0を超える最小のピタゴラス数を探す

100 INPUT c0
110 FOR c=c0+1 TO MAXNUM
120    FOR b=1 TO SQR(c)-1
130       LET a=INT(SQR(c-b^2))
140       IF a^2+b^2 = c THEN EXIT FOR
150    NEXT b
160    IF b <= SQR(c)-1 THEN EXIT FOR
170 NEXT c
180 PRINT c;"=";a;"^2 +";b;"^2"
190 END

 この手法を用いる場合には,FOR文の限界と同じ数値によるテストでなければならないことに注意が必要です。(変数を含む条件を指定するような場合,その変数の値がループ内で変更されていないことの検証が必要。)

例外を利用する(推奨)

多重ループからの脱出に,WHEN EXCEPTION IN〜END WHEN内にループを記述し,例外を生成して脱出する手法が利用できます。
独自の例外を生成するのにCAUSE EXCEPTION文を使います。例外番号は1から999までが利用者用として予約されています。

例 c0を超える最小のピタゴラス数を探す

100 INPUT c0
110 WHEN EXCEPTION IN
120    FOR c=c0+1 TO MAXNUM
130       FOR b=1 TO SQR(c)-1
140          LET a=INT(SQR(c-b^2))
150          IF a^2+b^2=c THEN CAUSE EXCEPTION 999
160       NEXT b
170    NEXT c
180 USE
190    SELECT CASE EXTYPE
200    CASE 999
210    ! 正常動作なので,何もしないで例外処理区を抜けて先に進む
220    CASE ELSE
230       EXIT HANDLER   !  予期しないエラーの場合は例外を再生成する
240    END SELECT 
250 END WHEN
260 PRINT c;"=";a;"^2+";b;"^2"
270 END

この例は2重ループですが,何重ループになってもこの手法は有効です。

副プログラムを利用する

プログラムの流れを見えにくくすることが多いので推奨しませんが, ループを内部副プログラムに記述し,EXIT SUBで抜けて戻る手もあります。
ループが書かれる位置がもともと副プログラムや関数定義の内側にある場合には,この手法が推奨されます。

100 INPUT c0
110 CALL loop1
120 PRINT c;"=";a;"^2+";b;"^2"
130 SUB loop1
140    FOR c=c0+1 TO MAXNUM
150       FOR b=1 TO SQR(c)-1
160          LET a=INT(SQR(c-b^2))
170          IF a^2+b^2=c THEN EXIT SUB
180       NEXT b
190    NEXT c
200 END SUB
210 END

戻る