3

この問題の一部に対処する他の質問を見たことがありますが、すべてを達成する解決策は見当たりませんでした。もちろん、コマンドプロセッサには「while」のようなものはありません。また、goto:lineステートメントはすべてのループから抜け出すため、次の値に進む前に特定の期間、値のセットを反復処理するオプションではありません。

これが、私が目指している論理フローの擬似コードです。コマンドプロセッサは、これまでのところ実行しようとする私の試みを失敗させました。これをどのように構築しますか(バッチスクリプトを破棄してc#などに移動する以外に)?

擬似コード

SET %%durationMinutes=60
FOR %%X IN (10 20 40 80 160 200 0) DO (
  :: calculate elapsed minutes...
  WHILE %elapsedMinutes < %%durationMinutes DO (
    :: unrelated hocus pocus here, uses %%X as a variable
    call :foo %%X 
    // can't use goto to simulate the WHILE loop since it breaks %%X, so...?
  )
)
4

3 に答える 3

5

この問題には2つの面があります。そもそも、gotoネストしているIF / FORコマンドを中断するという事実ですが、おそらくもっと重要なのは、Whilegotoが非常に遅いという事実です。1つの解決策は、無限ループを使用してしばらくシミュレーションすることです。そして、サブルーチン内でfor /L %%i in () do ...それを中断します。gotoこのソリューションの問題は、同じcmd.exeコンテキストでをfor /L壊すことはできないということです。したがって、解決策は、Whileを実行するためだけに新しいcmd.exeを呼び出すことです。goto

新しいcmd.exeで実行するバッチファイルは同じ呼び出し元ファイルである可能性があるため、同じバッチファイル内の特別なパラメーターを介してWhileの実行を制御する必要があります。また、補助変数を使用して、これらすべてを明確にすることもできます。ここにあります:

@echo off
setlocal EnableDelayedExpansion

rem While dispatcher
if "%1" equ "While" goto %2

rem Definition of auxiliary variables
set While=for /L %%a in () do if
set Do=(
set EndW=) else exit
set RunWhile=cmd /Q /C "%0" While

echo Example of While
echo/
goto RunMyWhile

rem Write the While code here
:MyWhile
set /A i=0, num=0
set /P "num=Enter number: "
%While% !num! gtr 0 %Do%
   set /A i+=1
   echo !i!- Number processed: !num!
   echo/
   set num=0
   set /P "num=Enter number: "
%EndW% !i!

rem Execute the While here
:RunMyWhile
%RunWhile% MyWhile
set i=%errorlevel%
echo/
echo While processed %i% elements

ご覧のとおり、WhileはERRORLEVELを介して呼び出し元のコードに数値結果を返す場合があります。

あなたの特定の場合:

SET durationMinutes=60
goto RunMyWhile

:MyWhile
:: calculate elapsed minutes...
%WHILE% !elapsedMinutes! < %durationMinutes% %DO%
    :: unrelated hocus pocus here, uses %3 as a variable
    call :foo %3
    :: calculate elapsed minutes again...
%EndW%

:RunMyWhile
FOR %%X IN (10 20 40 80 160 200 0) DO (
  %RunWhile% MyWhile %%X
)

このトピックは、この投稿で詳細に説明されています

于 2012-06-30T12:26:48.120 に答える
3

ハリーは、彼の答えにサブルーチンを使用するという正しい考えを持っています。通常、サブルーチンが呼び出されると、外部ループのFOR変数にアクセスできなくなります。ただし、サブルーチンに独自のFORループがある場合、それらは「魔法のように」再び使用可能になります。これにより、外部ループ値を変数に格納したり、値をパラメーターとして渡したりする必要がなくなります。

@echo off
for %%x in (1 2 3 4 5) do (
  echo begin outer loop iteration, x=%%x
  call :innerLoop
  echo end of outer loop iteration, x=%%x
  echo(
)
echo Outer loop complete
exit /b

:innerLoop
echo inside subroutine, x FOR variable is inaccessible: x=%%x
for %%y in (1 2 3 4 5) do (
  if %%y gtr %%x goto :break
  echo within FOR loop inside subroutine: x=%%x y=%%y
)
:break
echo end of subroutine, x FOR variable is inaccessible: x=%%x
exit /b

結果は次のとおりです。

begin outer loop iteration, x=1
inside subroutine, x FOR variable is inaccessible: x=%x
within FOR loop inside subroutine: x=1 y=1
end of subroutine, x FOR variable is inaccessible: x=%x
end of outer loop iteration, x=1

begin outer loop iteration, x=2
inside subroutine, x FOR variable is inaccessible: x=%x
within FOR loop inside subroutine: x=2 y=1
within FOR loop inside subroutine: x=2 y=2
end of subroutine, x FOR variable is inaccessible: x=%x
end of outer loop iteration, x=2

begin outer loop iteration, x=3
inside subroutine, x FOR variable is inaccessible: x=%x
within FOR loop inside subroutine: x=3 y=1
within FOR loop inside subroutine: x=3 y=2
within FOR loop inside subroutine: x=3 y=3
end of subroutine, x FOR variable is inaccessible: x=%x
end of outer loop iteration, x=3

begin outer loop iteration, x=4
inside subroutine, x FOR variable is inaccessible: x=%x
within FOR loop inside subroutine: x=4 y=1
within FOR loop inside subroutine: x=4 y=2
within FOR loop inside subroutine: x=4 y=3
within FOR loop inside subroutine: x=4 y=4
end of subroutine, x FOR variable is inaccessible: x=%x
end of outer loop iteration, x=4

begin outer loop iteration, x=5
inside subroutine, x FOR variable is inaccessible: x=%x
within FOR loop inside subroutine: x=5 y=1
within FOR loop inside subroutine: x=5 y=2
within FOR loop inside subroutine: x=5 y=3
within FOR loop inside subroutine: x=5 y=4
within FOR loop inside subroutine: x=5 y=5
end of subroutine, x FOR variable is inaccessible: x=%x
end of outer loop iteration, x=5

Outer loop complete
于 2012-06-30T05:26:08.490 に答える
1

ループの内容をサブルーチンに入れるだけです。簡単な例の擬似コードは次のとおりです。

for x in (1 2 3 4 5) {
  y = 1
  while (y <= x) {
    echo y
    y = y + 1
  }
  echo Looping
}

そして、バッチでの実装:

for %%x in (1 2 3 4 5) do set x=%%x & call :for_loop
goto :for_end
:for_loop

  set y=1

  :while_loop
  if not %y% LEQ %x% goto :while_end

    echo %y%
    set /a y=y+1

  goto :while_loop
  :while_end

  echo Looping

goto :eof
:for_end

そして出力:

1
Looping
1
2
Looping
1
2
3
Looping
1
2
3
4
Looping
1
2
3
4
5
Looping
于 2012-06-30T02:23:44.347 に答える