Почему операторы IF вызывают завершение работы командного файла? - PullRequest
0 голосов
/ 28 мая 2020

Я попытался сделать так, чтобы код выбирал случайное число от 1 до 5, и затем он выбирал случайную область в игре. Проблема в том, что он продолжает выходить всякий раз, когда выполняется. Он также игнорирует x между переменной %place%.

pause
set place=%random% %% 5
timeout 1
if x%place%x==1 goto cave
if x%place%x==2 goto plains
if x%place%x==3 goto swamp
if x%place%x==4 goto volcano
if x%place%x==5 goto fail
:cave
echo You went for a crusade and ended up in a cave.
pause
:plains
echo You went for a crusade and found a plains biome.
pause
:swamp
echo You went for a crusade and ventured into a swamp.
pause
:volcano
echo You went for a crusade and somehow ended up on a volcano.
pause
:fail
echo Your boat sank and you survived. You lost 5 coins.
pause

Ответы [ 2 ]

1 голос
/ 29 мая 2020

Ваш оператор set нуждается в переключателе /a, потому что вы пытаетесь выполнить математику. Также вам нужно добавить единицу к результату, потому что прямо сейчас вы получаете случайное число в диапазоне от 0 до 4, а ваши операторы if пронумерованы от 1 до 5. Также я знаю, что вы сказали игнорировать x, но им нужно go, если вы хотите, чтобы ваша программа работала. Вот отредактированная копия вашей программы:

set /a place = %RANDOM% %% 5 + 1
timeout 1
if %place% equ 1 goto cave
if %place% equ 2 goto plains
if %place% equ 3 goto swamp
if %place% equ 4 goto volcano
if %place% equ 5 goto fail
:cave
echo You went for a crusade and ended up in a cave.
pause
:plains
echo You went for a crusade and found a plains biome.
pause
:swamp
echo You went for a crusade and ventured into a swamp.
pause
:volcano
echo You went for a crusade and somehow ended up on a volcano.
pause
:fail
echo Your boat sank and you survived. You lost 5 coins.
pause
0 голосов
/ 31 мая 2020

Первая ошибка уже есть в строке:

set place=%random% %% 5

Эта строка присваивает строку переменной среды place, которая состоит из

  • случайное десятичное число в диапазоне от 0 до 32767,
  • пробел,
  • знак процента,
  • пробел и
  • число 5.

В результате первая if командная строка после обработки перед выполнением, например:

if x20934 % 5x==1 goto cave

Обработчик команд Windows завершает обработку пакетного файла с сообщением об ошибке :

% было неожиданным в то время.

Это довольно четкое сообщение об ошибке при отладке командного файла . Первым аргументом команды IF является x20934, поэтому процессор команд Windows ожидает следующим либо оператор сравнения строк ==, либо с включенными расширениями команд, как по умолчанию один из операторов EQU, NEQ, LSS, LEQ, GTR, GEQ, которые в основном предназначены для сравнения двух 32-битных целочисленных значений со знаком, но могут также использоваться для сравнения строк.

Пожалуйста, прочтите ответьте на Символ, эквивалентный NEQ, LSS, GTR и т. д. c. в Windows пакетных файлах для получения полной информации о том, как Windows командный процессор выполняет сравнение строк или целых чисел.

Таким образом, сначала необходимо исправить командную строку, которая должна оценивать a rithmeti c выражение и присвоить результат как строка переменной среды place.

set /A place=%RANDOM% %% 5 + 1

Тогда можно будет использовать условия IF с помощью любого оператора == или EQU для оценки результата.

Использование оператора сравнения строк == будет быстрее в этом случае, когда он на 100% уверен, что place является строкой с первым символом 1, 2, 3, 4 или 5 (со значением десятичного кода от 49 до 53), а второй символ является завершающим нулем (со значением десятичного кода 0). Таким образом, функция strcmp , используемая cmd.exe, возвращает целочисленный результат уже после сравнения первого или второго символа (байта).

set /A place=%RANDOM% %% 5 + 1
if %place% == 1 goto cave
if %place% == 2 goto plains
if %place% == 3 goto swamp
if %place% == 4 goto volcano
if %place% == 5 goto fail

Также возможно использовать EQU как оператор. Но в этом случае обе строки сначала преобразуются функцией strtol в 32-битные целые числа со знаком, которые затем сравниваются с помощью целочисленного сравнения. Это требует гораздо большего количества циклов процессора для выполнения sh сравнения.

set /A place=%RANDOM% %% 5 + 1
if %place% EQU 1 goto cave
if %place% EQU 2 goto plains
if %place% EQU 3 goto swamp
if %place% EQU 4 goto volcano
if %place% EQU 5 goto fail

Пользователь, запускающий командный файл, не заметит разницы. В настоящее время процессоры на ПК настолько быстры, что гораздо больше циклов ЦП, необходимых для выполнения двух strtol по сравнению с выполнением одного strcmp, составляет всего несколько микросекунд.

Эффективность выполнения командного файла может быть увеличен еще больше, если полностью исключить пять условий IF , потому что командный процессор Windows должен выполнить в худшем случае пять раз:

  • Откройте командный файл.
  • Установить позицию чтения файла в байтовое смещение конца последнего чтения.
  • Прочитать байты из пакетного файла до следующего перевода строки.
  • Предварительно обработать командную строку, чтобы узнать если необходимо прочитать больше строк.
  • Запомнить текущую позицию байта в командном файле.
  • Закройте командный файл.
  • Полностью обработать командную строку и выполнить ее.

Условий IF можно избежать, используя соответствующие метки и используя только команду GOTO с меткой в ​​зависимости от переменной среды place: * 111 1 *

@echo off
set /A place=%RANDOM% %% 5
goto Place%place%

:Place0 - cave
echo You went for a crusade and ended up in a cave.& echo/& pause
rem More commands for cave.
goto :EOF

:Place1 - plains
echo You went for a crusade and found a plains biome.& echo/& pause
rem More commands for plains.
goto :EOF

:Place2 - swamp
echo You went for a crusade and ventured into a swamp.& echo/& pause
rem More commands for swamp.
goto :EOF

:Place3 - volcano
echo You went for a crusade and somehow ended up on a volcano.& echo/& pause
rem More commands for volcano.
goto :EOF

:Place4 - fail
echo Your boat sank and you survived. You lost 5 coins.& echo/& pause

Командный процессор Windows интерпретирует только строку после : до первого символа-разделителя как метку. Таким образом, можно использовать метки, как показано выше, чтобы узнать, какая метка Place x предназначена для какого места, поскольку строка после пробела игнорируется командным процессором Windows.

Выражение arithmeti c приводит к значению в диапазоне 0-4, присвоенному как строка переменной среды place, которая присоединяется к строке Place в следующей командной строке к имени метки, которое будет обработано GOTO , чтобы продолжить обработку пакетного файла в строке под этой меткой.

Чтобы понять используемые команды и то, как они работают, откройте окно командной строки , выполните следующие команды и внимательно прочтите все страницы справки, отображаемые для каждой команды.

  • echo /?
  • goto /?
  • pause /?
  • rem /?
  • set /?

См. Также одну строку с несколькими командами для объяснения оператора &.

...