バッチファイルでProject Euler(2)

関数

前回、Problem 1を解きましたが、その際3と5と15で同じ処理を繰り返していましたね。こういうときに関数を使いたくなるのがプログラマです。
まず簡単な、整数を引数にして5倍する関数を例にしましょう。

@echo off

call :five_times 3
echo %ERRORLEVEL%
exit /b 0

:five_times
    setlocal
    set /a n = %1 * 5
    exit /b %n%

five_timesが関数名のようなものです。これをcallコマンドで呼びます。その後ろにあるのが引数です。
次の行のERRORLEVELという環境変数が関数の戻り値になります。
次の行のexitはよく忘れるので気をつけましょう。これを書き忘れると、次の行以降も実行されてしまいます。また、/bをつけ忘れるとコマンドプロンプトともども終了してしまうので気をつけましょう。最後の0が終了コードで、これがERRORLEVELにセットされます。ここでは意味はありません。

callコマンドが発効されると指定したラベルに制御が移ります。ここでは:five_timesになります。
setlocalコマンドを発効すると、endlocalまたはexitが呼ばれるまで環境変数がローカル変数になります。すなわち、寿命がendlocalまたはexitが呼ばれるまでということです。特に理由がない限りsetlocalをつけるようにしましょう。
関数の引数は%1、%2、…で参照できます。
exitの/bのあとの引数が戻り値となります。整数しか返せないので注意しましょう。
さて、n未満の自然数でmの倍数の総和を求める処理を関数化しましょう。この例ではあまりありがたみがないですが。

@echo off
set /a N = 1000
call :sum_seq 3 %N%
set /a s3 = %ERRORLEVEL%
call :sum_seq 5 %N%
set /a s5 = %ERRORLEVEL%
call :sum_seq 15 %N%
set /a s15 = %ERRORLEVEL%
set /a s = %s3% + %s5% - %s15%
echo %s%
exit /b 0

:sum_seq
    setlocal
    set /a d = %1
    set /a n = (%2 - 1) / %d%
    set /a s = %n% * (%n% + 1) / 2 * %d%
    exit /b %s%