Arrays 使用用户给定的数组元素切换大小写-批处理

Arrays 使用用户给定的数组元素切换大小写-批处理,arrays,batch-file,switch-statement,user-input,Arrays,Batch File,Switch Statement,User Input,我需要批处理文件中以下问题的解决方案 用户在每个下一个输入元素之间提供一个空格 输入需要作为数组元素存储在数组中 输入必须作为案例名称,并且需要执行特定案例。 因此,每个具有数组元素名称的案例都需要执行 阵列大小不是预先确定的。它随用户可能给出的任何数量的输入而变化 算法应该是这样的 用户输入编号为1 2 4 6,存储在数组a[i]中 a[i] = {1,2,4,6} for i = 1 to len(a[i]) CALL :CASE_%a[i]% # jump to :CASE_1,

我需要批处理文件中以下问题的解决方案

用户在每个下一个输入元素之间提供一个空格

输入需要作为数组元素存储在数组中

输入必须作为案例名称,并且需要执行特定案例。 因此,每个具有数组元素名称的案例都需要执行

阵列大小不是预先确定的。它随用户可能给出的任何数量的输入而变化

算法应该是这样的

用户输入编号为1 2 4 6,存储在数组a[i]中

a[i] = {1,2,4,6}



for i = 1 to len(a[i])

CALL :CASE_%a[i]% # jump to :CASE_1, :CASE_2, etc.

:CASE_1
Echo “am in case1”
:: go to the for loop

:CASE_2
Echo “am in case2”
:: go to the for loop

:CASE_3
Echo “am in case3”
:: go to the for loop

:CASE_4
Echo “am in case4”
:: go to the for loop

:CASE_5
Echo “am in case5”
:: go to the for loop

:CASE_6
Echo “am in case6”
:: go to the for loop

:CASE_7
Echo “am in case7”
:: go to the for loop

:CASE_8
Echo “am in case8”
:: go to the for loop



End for
情况_1、情况_2、情况_4、情况_6只需要执行,因为输入是1 2 4 6


这在批处理文件中可能吗?

Windows批处理对数组没有真正的支持,但可以通过巧妙地使用变量名来模拟数组。例如,
a[1]
a.len
是普通变量名,脚本不知道任何名为
a
的对象。我倾向于使用点表示法:
a.1
a.2
<代码>a.len。你可以自由发展自己的风格

@echo off
setlocal enableDelayedExpansion

set a[1]=1
set a[2]=2
set a[3]=4
set a[4]=6
set a.len=4

:: You can also do multiple numerical assignments on one line using SET /A
:: set /a "a[1]=1, a[2]=2, a[3]=4, a[4]=6, a.len=4"

for /l %%i in (1 1 %a.len%) do (
  call :CASE_!a[%%i]!
)

:: You must exit the script so you don't fall into the subroutines after the loop finishes
exit /b


:CASE_1
Echo am in case1
exit /b

:CASE_2
Echo am in case2
exit /b

:CASE_3
Echo am in case3
exit /b

:CASE_4
Echo am in case4
exit /b

:CASE_5
Echo am in case5
exit /b

:CASE_6
Echo am in case6
exit /b

:CASE_7
Echo am in case7
exit /b

:CASE_8
Echo am in case8
exit /b

我将把这个问题分成三部分。将数据放入数组,从数组中获取数据,并模拟一个
case
指令,而不是成批出现

@echo off
    setlocal enableextensions enabledelayedexpansion

    set /p "data=Input data:"
让我们假设用户只输入数字值(以避免所有必要的检查并只查看问题),如图所示,空格分隔。将它们放入一个“数组”。不,数组不存在于批处理脚本中,但可以模拟为变量提供专有名称

set "arrayLength=0"
for %%e in (%data%) do (
    set /a "arrayLength+=1"
    set "a[!arrayLength!]=%%e"
)
这将对输入数据进行迭代,并为每个元素递增一个计数器,并创建一个名为
a[
+
计数器值
+
]
的变量。不,它不是一个数组,只是一个带有名称的变量,允许我们模拟数组sintax。由于计数器(
arrayLength
)在循环内发生更改,因此需要延迟扩展来读取此更改的值,并且变量读取的sintax从
%var%
更改为
!瓦尔

现在,数据在“数组”中。我们将迭代“数组”,检查其内容

for /l %%i in (1 1 %arrayLength%) do (
    echo element %%i is : !a[%%i]!
)
读取每个元素内容的sintax也需要延迟扩展。在这种情况下,我们不会更改块内的值,但读取变量的名称会在每次迭代中自动生成。请记住,没有数组,只有具有特定名称的变量。我们使用
for
变量生成名称

如何测试“数组”的值

这将迭代“数组”,并使用级联的
IF
sintax检查允许的值。编写代码很容易,速度很快,但如果案例经常发生更改,维护起来就不是最舒服的

IF级联的另一种选择是使用子例程。根据“array”元素的值,调用一个或另一个标签。只需适当地命名标签即可

然后可以测试标签/子例程是否存在,然后调用它

或者,您可以直接调用它,而无需事先检查和测试调用中是否有错误,这些错误将指示标签不存在

或者可以定义一个例程表

对于示例,如果定义了以下标签

:case[1]
    echo Case 1
    goto :eof
:case[2]
    echo Case 2
    goto :eof
:case[3]
    echo Case 3
    goto :eof
:case[4]
    echo Case 4
    goto :eof
:case[5]
    echo Case 5
    goto :eof
:case[6]
    echo Case 6
    goto :eof
在批处理文件(
%~f0
是具有完整路径的当前批处理文件)中,调用此子例程的代码可以是

这将使用
findstr
读取搜索
:case[n]
标签的当前批处理文件。如果没有错误,则已找到标签并进行调用。但是必须读取批处理文件来测试标签是否存在并不是最快的操作

要不检查标签是否存在并直接执行调用,可以使用以下代码

rem Use labels in batch without check
for /l %%i in (1 1 %arrayLength%) do (
    ver>nul
    call :case[!a[%%i]!] 2>nul 
    if errorlevel 1 echo NO CASE 
)
“ver>nul”行可确保在调用子例程之前清除errorlevel。发出呼叫并检查errorlevel。但是无法知道errorlevel是来自调用指令还是来自被调用子例程的内部

另一种选择是使用rutines表来调用数组中元素的每个可能值。因此,如果为每个允许的元素创建了一个表,则指向子例程的标签

set "func[1]=:case[1]"
set "func[2]=:case[2]"
set "func[3]=:case[3]"
set "func[4]=:case[4]"
set "func[5]=:case[5]"
set "func[6]=:case[6]"
如果定义了值的函数,则以下代码可以调用相应的子例程进行检查

for /l %%i in (1 1 %arrayLength%) do (
    for %%v in (!a[%%i]!) do if defined func[%%v] (
        call !func[%%v]!
    ) else (
        echo NO CASE
    )
)
需要使用内部for来获取对“数组”中的值的引用,以用于访问
func
“数组”中函数的名称

及。。。。。任何人都能想象得到的更好的东西


在所有这些之后,应该使用哪种代码?什么对你有用。这完全取决于真正要解决的问题

IF级联是快速而简单的,但对于频繁变化的情况,更难维护

findstr非常耗时

没有支票的电话可能真的很麻烦

函数表在中间。与IF解决方案中的所有代码在块中的速度不同,但在检查子例程定义时比

findstr
快。编写代码并不难,但小问题是不必要的

对于简单的情况,
IF
构造就是您所需要的。对于复杂的问题,如果代码很长,需要更改、添加案例。。。函数表使事情变得更简单

因此,它可能导致

@echo off
    setlocal enableextensions enabledelayedexpansion

    set /p "data=Input data:"

    set "arrayLength=0"
    for %%e in (%data%) do (
        set /a "arrayLength+=1"
        set "a[!arrayLength!]=%%e"
    )

    rem func[ allowedValue ] = label to call
    set "func[1]=:handleCase_1"
    set "func[2]=:handleCase_2"
    set "func[3]=:handleCase_3"
    set "func[4]=:handleCase_4"
    set "func[5]=:handleCase_5"
    set "func[6]=:handleCase_6"

    for /l %%i in (1 1 %arrayLength%) do (
        for %%v in (!a[%%i]!) do if defined func[%%v] (
            call !func[%%v]!
        ) else (
            echo NO CASE
        )
    )

    for /l %%i in (1 1 %arrayLength%) do (
        if "!a[%%i]!"=="1" (
            echo Case 1
            rem Or, we can 
            rem call :handleCase_1
        ) else if "!a[%%i]!"=="2" (
            echo Case 2
        ) else if "!a[%%i]!"=="3" (
            echo Case 3
        ) else if "!a[%%i]!"=="4" (
            echo Case 4
        ) else if "!a[%%i]!"=="5" (
            echo Case 5
        ) else if "!a[%%i]!"=="6" (
            echo Case 6
        ) else (
            echo NO CASE
        )
    )

    endlocal
    exit /b    

:handleCase_1
    echo Case 1
    goto :eof
:handleCase_2
    echo Case 2
    goto :eof
:handleCase_3
    echo Case 3
    goto :eof
:handleCase_4
    echo Case 4
    goto :eof
:handleCase_5
    echo Case 5
    goto :eof
:handleCase_6
    echo Case 6
    goto :eof

我回顾了您的问题,在我看来,它不需要使用数组。我想你说的是一份清单。通过这种方式,可以使用以下列表解决所述问题:

@echo off

rem The user gives the input with a space in between every next input element.
set /P input=

rem The input has to be taken as the case name and the particular case need to be executed.
rem Hence every case with the name of the array element need to be executed.
for %%i in (%input%) do call :CASE_%%i
goto :EOF

:CASE_1
Echo am in case1
exit /B

:CASE_2
Echo am in case2
exit /B

:CASE_3
Echo am in case3
exit /B

:CASE_4
Echo am in case4
exit /B

:CASE_5
Echo am in case5
exit /B

:CASE_6
Echo am in case6
exit /B
例如:

C:\> test
1 2 4 6
am in case1
am in case2
am in case4
am in case6

任何被迫使用不必要阵列的解决方案都会更加复杂…

非常感谢。您给出的代码的前四个部分非常有效。我在第四部分还有另一项工作要做。在echo case1之后,需要对func进行调用(比如转到func1)
@echo off

rem The user gives the input with a space in between every next input element.
set /P input=

rem The input has to be taken as the case name and the particular case need to be executed.
rem Hence every case with the name of the array element need to be executed.
for %%i in (%input%) do call :CASE_%%i
goto :EOF

:CASE_1
Echo am in case1
exit /B

:CASE_2
Echo am in case2
exit /B

:CASE_3
Echo am in case3
exit /B

:CASE_4
Echo am in case4
exit /B

:CASE_5
Echo am in case5
exit /B

:CASE_6
Echo am in case6
exit /B
C:\> test
1 2 4 6
am in case1
am in case2
am in case4
am in case6