С Новым годом! Форум программистов, компьютерный форум, киберфорум
Batch (CMD/BAT)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/4: Рейтинг темы: голосов - 4, средняя оценка - 5.00
25 / 1 / 1
Регистрация: 16.02.2024
Сообщений: 31

Выход из процедуры (подпрограммы), обработка ошибок, передача параметров, контекст

19.02.2024, 16:34. Показов 908. Ответов 7

Студворк — интернет-сервис помощи студентам
Добрый!

В cmd/bat файле есть вот такой код:
Windows Batch file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
:FindCmdFile:
 
for /f "usebackq" %%G in (`echo %cmd_line_arg: =^&echo:%`) do (
    set "_t=%%G"
setlocal enabledelayedexpansion
    if "!_t:~0,1!" EQU "@" (
    call set "cmd_line_arg=%%cmd_line_arg:!_t!=%%"
        call :ReadCmdFile !_t:~1! _t1 && set "cmd_line_arg=!cmd_line_arg!!_t1!"
rem        (call :ReadCmdFile !_t:~1! _t1 && set "cmd_line_arg=!cmd_line_arg!!_t1!") || goto:End
    )
)
endlocal & set cmd_line_arg=%cmd_line_arg%
 
.... .... ...
 
:ReadCmdFile:
if not exist "%1" (call :ENotFile %1 & exit /b 10)
rem if not exist "%1" (call :ENotFile %1) || exit /b 10
rem if not exist "%1" goto:ENotFile
setlocal enabledelayedexpansion
for /f "usebackq" %%G in (`type %1`) do (set "_t2=!_t2! %%G")
endlocal & set "%2=%_t2%"
exit /b 0
goto:End
 
:ENotFile:
call :HeadShow
if %ansi_on% EQU 1 echo [0;31;47m
echo:
echo E10: Не обнаружен файл %1
echo Завершение работы...
if %ansi_on% EQU 1 echo [0m
exit /b 10
goto:End
Сам командный файл вызывается примерно такой командой: commfile.cmd @file.ext

Так вот, по логике работы коды, если указанный в командной строке файл не обнаружен, должно выводиться сообщение об ошибке и работа завершается. Но, к сожалению, этого не происходит.
При текущем коде выполняется обработка ошибки, выводится сообщение и, почему‐то, возврат в вызывающую функции «:FindCmdFile» и работа продолжается.
Если же убрать комментарий со строки (call :ReadCmdFile !_t:~1! _t1 && set "cmd_line_arg=!cmd_line_arg!!_t1!") || goto:End, то тогда отрабатывает нормально, работа, после вывода сообщения, завершается.

Прошу подсказать, почему так происходит? И как сделать, чтобы не происходил возврат в вызывающую функцию?
Ведь, если я правильно понимаю, выход должен произойти ещё в функции «:ReadCmdFile».
Но, если этого даже не произойдёт, то, в соответствии с оператором && после кода call :ReadCmdFile !_t:~1! _t1, присвоение не должно выполняться и будет всё равно ошибка дальше в коде.

И второй момент.
Если выполнить вызов подпрограммы «:ENotFile» через оператор «GOTO», в сообщении об ошибке всё равно отображается наименование отсутствующего файла file.ext.
Из‐за чего это происходит? Ведь при вызове функции «:ENotFile» не передавались никакие аргументы вызова.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
19.02.2024, 16:34
Ответы с готовыми решениями:

Передача параметров в подпрограммы на Паскале
пикиньте информацию на тему: Передача параметров в подпрограммы на Паскале Добавлено через 49 минут киньте пару ссылок откуда можно...

Getopt. Обработка ошибок ввода параметров
Доброго Здоровья! Собственно проблема. Если параметр требует аргумента, а аргумент пропущен, то в качестве аргумента записывается...

Процедуры, передача параметров по ссылке
Реализовать функцию, осуществляющую поиск в целочисленном массиве серии минимальной длины. В качестве параметров передается массив и его ...

7
6969 / 2863 / 1100
Регистрация: 06.06.2017
Сообщений: 9,713
21.02.2024, 16:25
Цитата Сообщение от one1 Посмотреть сообщение
Прошу подсказать, почему так происходит?
call — это лишь вызов процедуры по метке, а goto переход к метке, поэтому только на ней цикл прерывается.

Цитата Сообщение от one1 Посмотреть сообщение
Ведь при вызове функции «:ENotFile» не передавались никакие аргументы вызова.
17 строка говорит об обратном.

PS: Двоеточия на конце меток не нужны.
0
25 / 1 / 1
Регистрация: 16.02.2024
Сообщений: 31
21.02.2024, 19:28  [ТС]
FlasherX, спасибо, что нашли время посмотреть мой вопрос.

Цитата Сообщение от FlasherX Посмотреть сообщение
PS: Двоеточия на конце меток не нужны.
Ну да, их можно не указывать.
label A predefined label in the batch program.
Each label must be defined on a line by itself, beginning with
a colon and ending with either a space, a colon or a CR/LF.
Просто, так наглядней для меня.

Цитата Сообщение от one1 Посмотреть сообщение
Ведь при вызове функции «:ENotFile» не передавались никакие аргументы вызова.
17 строка говорит об обратном.
Это один из варантов, рабочий.
Пробывал я с разными вариантами.
Если раскомментировать эту строку rem if not exist "%1" goto:ENotFile, закомментировать ту которая сейчас if not exist "%1" (call :ENotFile %1 & exit /b 10), и выполнит командыный файл, то у меня в сообщении всё равно отображалось название файла, которое передано как аргумент в вызов процедуры :ReadCmdFile.
Вот поэтому я не могу понять почему это происходит.
Я только предполагаю что это потому, что при исполнении команды call создаётся новый контекст, который наследует ранее объявленные и иницализированные переменны.
Но в процедуре пременная указана явно как %1, то есть переданный аргумент процедуры. А он не предаётся при вызове.
В общем, я понимаю, что что‐то не понимаю, но не пониаю, что надо понять.

Выглядет это вот так:
Миниатюры
Выход из процедуры (подпрограммы), обработка ошибок, передача параметров, контекст  
0
25 / 1 / 1
Регистрация: 16.02.2024
Сообщений: 31
21.02.2024, 20:06  [ТС]
Цитата Сообщение от FlasherX Посмотреть сообщение
Сообщение от one1
Прошу подсказать, почему так происходит?
call — это лишь вызов процедуры по метке, а goto переход к метке, поэтому только на ней цикл прерывается.
Я понимаю, что в командных файлах нет нормальных команд прерывания и продолжения циклов, типа BREAK и continue.
Но как тогда сделать, чтобы не было возврата в вызвающую функции. Это возможно?
Ведь если даже сделать так:
Windows Batch file
1
2
3
4
5
6
7
8
:ENotFile:
call :HeadShow
if %ansi_on% EQU 1 echo [0;31;47m
echo:
echo E10: Не обнаружен файл %1
echo Завершение работы...
if %ansi_on% EQU 1 echo [0m
goto:End
Т. е. в последней процедуре, которая находится в последовательности (стеке) вызовов
:FindCmdFile ---> :ReadCmdFile ---> :ENotFile стоит команда goto:End, то всё равно происходит возврат в вызывающие процедуры выше по списку.

И опять же, даже если мы вернулись в начало последовательности вызовов ‐ :FindCmdFile, то там есть команда call :ReadCmdFile !_t:~1! _t1 && set "cmd_line_arg=!cmd_line_arg!!_t1!". Как я понимаю, логику работы оператора &&, присвоение не должно происходить, так как из предыдущей процедуры выход был с ненулевым кодом возврата вот в этой команде if not exist "%1" (call :ENotFile %1 & exit /b 10).
Но присвоение присходит. И рбота продолжается. Почему!?

Добавлено через 11 минут
Если вместо этой команды call :ReadCmdFile !_t:~1! _t1 && set "cmd_line_arg=!cmd_line_arg!!_t1!" использовать такую команду (call :ReadCmdFile !_t:~1! _t1 && set "cmd_line_arg=!cmd_line_arg!!_t1!") || goto:End, то, да, работа завершается. Всё как и должно быть.
FAQ по файлам BAT/CMD
Оператор && гарантирует, что вторая команда будет выполнена только, если первая была выполнена успешно, т.е. с нулевым кодом возврата (он же %errorlevel%).
Не менее полезен иногда и оператор ||. Суть его тоже логична – выполнить вторую команду, если первая дала сбой.
0
6969 / 2863 / 1100
Регистрация: 06.06.2017
Сообщений: 9,713
21.02.2024, 20:28
Цитата Сообщение от one1 Посмотреть сообщение
то у меня в сообщении всё равно отображалось название файла,
Windows Batch file
1
2
3
4
5
6
7
8
9
10
11
@echo off
call:a %1
call:b
pause&exit
 
:a
echo a:%1
exit/b
 
:b
echo b:%1
Run: this.bat test
Результат:
Windows Batch file
1
2
3
a:test
b:
Для продолжения нажмите любую клавишу . . .
Или я делаю что-то не так?

Цитата Сообщение от one1 Посмотреть сообщение
Но как тогда сделать, чтобы не было возврата в вызвающую функции. Это возможно?
Я же написал — goto вместо call.

Цитата Сообщение от one1 Посмотреть сообщение
Т. е. в последней процедуре ... стоит команда goto:End, то всё равно происходит возврат в вызывающие процедуры выше по списку.
Дык в процедуре, а не в цикле. Это же разные вещи.

Цитата Сообщение от one1 Посмотреть сообщение
Как я понимаю, логику работы оператора &&, присвоение не должно происходить, так как из предыдущей процедуры выход был с ненулевым кодом возврата вот в этой команде if not exist "%1" (call :ENotFile %1 & exit /b 10).
Ничего не смущает? )
0
25 / 1 / 1
Регистрация: 16.02.2024
Сообщений: 31
21.02.2024, 20:51  [ТС]
FlasherX, благодарю, за Ваш ответ, и что помогаете мне разобраться в этом.

Цитата Сообщение от FlasherX Посмотреть сообщение
Сообщение от one1
Как я понимаю, логику работы оператора &&, присвоение не должно происходить, так как из предыдущей процедуры выход был с ненулевым кодом возврата вот в этой команде if not exist "%1" (call :ENotFile %1 & exit /b 10).
Ничего не смущает? )
Вы уж извините, что, может быть, нексолько путано пишу.
Там такая последовательность:
Из :FindCmdFile мы вызваем :ReadCmdFile, где и есть команда if not exist "%1" (call :ENotFile %1 & exit /b 10). И после этой команды, где явно указа код возврата как 10, она возвращается обратно в :FindCmdFile, в команду call :ReadCmdFile !_t:~1! _t1 && set "cmd_line_arg=!cmd_line_arg!!_t1!". И вот в этой последней команде и есть оператор &&.

Добавлено через 8 минут
Цитата Сообщение от FlasherX Посмотреть сообщение
Сообщение от one1
Но как тогда сделать, чтобы не было возврата в вызвающую функции. Это возможно?
Я же написал — goto вместо call.
Сообщение от one1
Т. е. в последней процедуре ... стоит команда goto:End, то всё равно происходит возврат в вызывающие процедуры выше по списку.
Дык в процедуре, а не в цикле. Это же разные вещи.
Хорошо. То есть последовательность вызово не разрывается, если один из вызовов был сделан из цикла. Правильно?
Ладно, пусть. Получается, что цикл будет исполняться «до последнего», даже если где‐то в вызваемой процедуре есть GOTO на завершение или пока не произойдёт ошибки ниже по цепочке вызово. Понятно, но плохо, что так сделано.
0
25 / 1 / 1
Регистрация: 16.02.2024
Сообщений: 31
21.02.2024, 21:12  [ТС]
Цитата Сообщение от FlasherX Посмотреть сообщение
то у меня в сообщении всё равно отображалось название файла,
Windows Batch fileВыделить код
1
2
3
4
5
6
7
8
9
10
11
@echo off
call:a %1
call:b
pause&exit
:a
echo a:%1
exit/b
:b
echo b:%1
Run: this.bat test
Результат:
Windows Batch fileВыделить код
1
2
3
a:test
b:
Для продолжения нажмите любую клавишу . . .
Или я делаю что-то не так?
Так и должно быть, как я понимаю. Я тоже ожидаю такой работы.
Но, блин, так не происходит!
Вы видели, наверное, это на приложенном снимке экрана.

Запустите, пожулуйста, это код:
Windows Batch file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
:ReadCmdFile [in=filename]
@echo on
if not exist "%1" goto:ENotFile
echo The file is exists %1
exit /b 0
goto:EOF
 
:ENotFile [in=filename]
echo:
echo E10: Не обнаружен файл %1
echo Завершение работы...
goto:EOF
exit /b 10
@echo off
Или прикреплённый файл (предварительно переименова в tst-goto.cmd) такой командой:
tst-goto.cmd file.ext
И выводе сообщения будет указано
E10: Не обнаружен файл file.exe
Вложения
Тип файла: txt tst-goto.cmd.txt (248 байт, 8 просмотров)
0
6969 / 2863 / 1100
Регистрация: 06.06.2017
Сообщений: 9,713
21.02.2024, 21:52
Цитата Сообщение от one1 Посмотреть сообщение
Там такая последовательность:
Ясно. Значит, проблему надо искать в переменных. Я их не вижу в этом куске кода.

Цитата Сообщение от one1 Посмотреть сообщение
То есть последовательность вызово не разрывается, если один из вызовов был сделан из цикла. Правильно?
Речь про call? Ну так я выше об этом писал.

Цитата Сообщение от one1 Посмотреть сообщение
Получается, что цикл будет исполняться «до последнего», даже если где‐то в вызваемой процедуре есть GOTO на завершение или пока не произойдёт ошибки ниже по цепочке вызово.
Переход (он же выход) из процедуры не равноценен переходу из цикла. Это и в других языках так.

Цитата Сообщение от one1 Посмотреть сообщение
Запустите, пожулуйста, это код:
А, вы про goto спрашивали, я то на call показывал. goto никак не влияет на переменные.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
21.02.2024, 21:52
Помогаю со студенческими работами здесь

Передача параметров вызываемой процедуры в стиле Pascal и Fortran
Ребят, помогите разобраться с заданием. звучит так: "Передача параметров вызываемой процедуры в стиле Pascal и Fortran". не пойму......

Передача параметров процедуры для создания и удаления ключей
Как передать параметр процедуры для создания/удаления ключей? Данный запрос "спотыкается" на параметрах при удаление/создания...

Передача параметров через стек. Тип процедуры – ближний
Всем привет! Есть задание: Ввести 8-битовое целое число А. Если оно четное, вычислить значение выражения А3 – 1, если нечетное – значение...

Передача параметров классу, обработка класса
Подскажите, почему не работает? Есть класс "class FileManager" , передаю параметры в класс с помощью переменных через пост L1...L4 , хочу,...

Передача и обработка параметров между двумя PHP скриптами
Наверное человек, которых это спрашивало мильон.... И я как и все не нашел конкретного ответа на свой вопрос. Задача такая: Допустим...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её. Последовательность действий:. . .
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru