即時変数展開
forとifが使えるようになったので、Problem 1を題意どおりに書くことができます。ただし、バッチファイルにはandやorはないので、そこはifを2つ使うことになります。
@echo off set /a N = 1000 set /a M = %N% - 1 set /a s = 0 for /L %%i in (1, 1, %M%) do ( set /a r3 = %%i %% 3 set /a r5 = %%i %% 5 if %r3% == 0 ( set /a s += %%i ) else ( if %r5% == 0 ( set /a s += %%i ) ) ) echo %s%
ここで、3 %% 2だと3を2で割ったときの余りです。これを実行すると、
( の使い方が誤っています。
おや、なにやらエラーメッセージのようなものが出ていますね。しかしどこで出ているのかよくわかりません。こういうときは先頭行を
@echo on
とすると原因がわかることがあります。
>euler001d.bat >set /a N = 1000 >set /a M = 1000 - 1 >set /a s = 0 ( の使い方が誤っています。 > if == 0 (
どうやら、
if %r3% == 0 (
の部分のようです。r3になにもセットされていないんですね。なぜこうなるかというと、ifやforの中の環境変数はそれらが実行される前に評価されるからです。この場合では、forの中にsetコマンドでr3に値をセットしているように見えますが、その前にr3が評価されてしまうので、この時点ではr3には何もセットされていないことになるのです。forやifはこのようなことがしばしば起きるので厄介です。
goto
このような場合で一番お手軽なのはgotoでループを回すことです。
@echo off set /a N = 1000 set /a s = 0 set /a i = 1 :loop set /a r3 = %i% %% 3 set /a r5 = %i% %% 5 if %r3% == 0 ( set /a s += %i% ) else ( if %r5% == 0 ( set /a s += %i% ) ) set /a i += 1 if %i% LSS %N% goto :loop echo %s%
単にgoto :labelで:labelに飛ぶというだけです。
再びfor
どうしてもforを使いたかったら、forの中でcallして、call先でsに足すのでしょうね。
@echo off set /a N = 1000 set /a M = N - 1 set /a s = 0 for /L %%i in (1, 1, %M%) do call :sum %%i echo %s% exit /b 0 :sum call :is_valid %1 if %ERRORLEVEL% == 1 set /a s += %1 exit /b 0 :is_valid setlocal set /a r3 = %1 %% 3 if %r3% == 0 exit /b 1 set /a r5 = %1 %% 5 if %r5% == 0 exit /b 1 exit /b 0