はじめに
カウンタのある基本的なFor
ループについて、迷っていたことがありました。ループを回り切ったカウンタの値がどうなるのか。わかってしまえばバカバカしいほど簡単です。
お前、ちゃんと10回ったんだろうな?
For
ループを使ったロジックで、条件によってはループを途中で抜け出したいときがある。
例えば、カウンタが5
になったら抜けたい場合は、If
文で条件を判定して条件が合えば、Exit For
で脱出する。
Private Sub Hoge()
For i = 0 To 9
Debug.Print "ループ内 i=" & i
If i = 5 Then Exit For
Next
Debug.Print "-- ループを抜けました --"
End Sub
この例では条件がi = 5
と固定されているが、ループ内の処理によって条件が変化するとき、後続処理の中で、ループを途中で抜けたのか、抜けることなく最後まで回り切ったのか、簡単に判定する方法は無いだろうか?
Next を通過するとカウンタが加算される
以下のマクロで、For
ループのカウンタがどう変化するか、ループを回り切った場合と途中で抜けた場合を見てみた。
Private Sub Hoge2()
Debug.Print "--- Forループ実験 (Exit For無し) ---"
Dim i As Integer
For i = 0 To 9
Debug.Print "ループ内 i=" & i
Next
Debug.Print "-- ループを抜けました --"
Debug.Print "ループ外 i=" & i & vbCr
Debug.Print "--- Forループ実験 (5でExit For) ---"
For i = 0 To 9
Debug.Print "ループ内 i=" & i
If i = 5 Then Exit For
Next
Debug.Print "-- ループを抜けました --"
Debug.Print "ループ外 i=" & i
End Sub
以下が結果である。
--- Forループ実験 (Exit For無し) ---
ループ内 i=0
ループ内 i=1
ループ内 i=2
ループ内 i=3
ループ内 i=4
ループ内 i=5
ループ内 i=6
ループ内 i=7
ループ内 i=8
ループ内 i=9
-- ループを抜けました --
ループ外 i=10
--- Forループ実験 (5でExit For) ---
ループ内 i=0
ループ内 i=1
ループ内 i=2
ループ内 i=3
ループ内 i=4
ループ内 i=5
-- ループを抜けました --
ループ外 i=5
最後までループを回り切る最初のFor
のi
は9
で終わると思ったら、10
になっている。
Exit For
で途中で抜けた方のi
は抜けた時点での5
のままである。
どうやらNext
を通過することでカウンタが加算されるようだ。
わかりやすいC#
これと同様のことをC#で書くとどうなるか。
Console.WriteLine("--- forループ実験 (ブレーク無し) ---");
int i;
for (i = 0; i <= 9; i++)
{
Console.WriteLine($"ループ内 i={i}");
}
Console.WriteLine("-- ループを抜けました --");
Console.WriteLine($"ループ外 i={i}\n");
Console.WriteLine("--- forループ実験 (5でブレーク) ---");
for (i = 0; i <= 9; i++)
{
Console.WriteLine($"ループ内 i={i}");
if (i == 5) { break; }
}
Console.WriteLine("-- ループを抜けました --");
Console.WriteLine($"ループ外 i={i}");
結果は、上述のVBAと同様だが、i++
があることで、この結果が当たり前に見える、、、
余談だが、i++
をi+=2
にしてループを回り切ると、i
は11
になる。
VBAなら、
For i = 0 To 9 Step 2
とすれば同様の結果となる。
おまけ
Pythonで、これはどうなるか。
Pythonのfor
ループは独特だ。カウンタが無い。
print('--- forループ実験 ---')
i=0
for i in range(10):
print(f'ループ内i={i}')
else:
print('-- 最後までループを回り切りました --')
print('-- ループを抜けました --')
print(f'ループ外i={i}')
print('') # なぜか¥nで改行できなかったので...
for i in range(10):
print(f'ループ内i={i}')
if i==5:
break
else:
print('-- 最後までループを回り切りました --')
print('-- ループを抜けました --')
print(f'ループ外i={i}')
結果は、
--- forループ実験 ---
ループ内i=0
ループ内i=1
ループ内i=2
ループ内i=3
ループ内i=4
ループ内i=5
ループ内i=6
ループ内i=7
ループ内i=8
ループ内i=9
-- 最後までループを回り切りました --
-- ループを抜けました --
ループ外i=9
ループ内i=0
ループ内i=1
ループ内i=2
ループ内i=3
ループ内i=4
ループ内i=5
-- ループを抜けました --
ループ外i=5
for
に続くelse
は、最後までループが回り切った時だけ実行される(breakされた時は実行されない)。もうお分りだろうが、このPythonのfor
は、VBAで言うところのFor Each
である。
カウンタ無しでも、ちゃんと回り切ったことを確認する方法を用意してあるところが賢いね
追記
カウンタをコレクションの如く勘違いしていた。自分がもしC言語系ネイティブだったら、こんな勘違いはしなかっただろう。カウンタは、指定したレンジから外れることでループを抜ける。コレクションは、レンジ内で処理をする