如何在原始DOS中获取2个数字的和?

时间:2019-01-12 06:08:40

标签: batch-file dos

我想重温昔日的怀旧之情。
我一直在测试一些批处理命令,但是我发现/a在dos中不可用。
我是否可以使用另一种方法添加两个变量而不包含/a

@echo off
::this is how I would originally add two numbers
set /p number1=
set /p number2=
set /a "number1=number1+number2"
echo %number1%
pause >nul
exit

当我运行此程序时,dos状态为"invalid switch. - /a"

3 个答案:

答案 0 :(得分:2)

与使用set /a相比,它有些棘手,但是可以使用MS-DOS 6.22解决。

一部分是编写一个添加一位数字的函数,另一个编写可以添加多个位数的函数。

主要问题是将数字拆分为个位数,因为MS-DOS不支持字符串操作。
但这在FOR-Loop处理中存在一个微小的缺陷,/将文本分为三部分。

for %%a in (`abcdef/ghijklmno`) do echo %%a

输出

abcdef
g
hijklmno

使用此技巧,可以将数字拆分为个位数

split.bat

@echo off
for %%P in (/%1.) do if %%P==: goto %1

set _idx=
set _remain=
set _splitRev=
set _splitRev_comma=

:loop

set _loop=1

for %%a in (/%_remain%) do call %0 :split %1 %%a
if NOT "%_remain%"=="" goto :loop
set %1=%_splitRev%
set %1_comma=%_splitRev_comma%

REM Clear temp vars
FOR %%v in (_remain _idx _loop _splitRev _splitRev_comma) do set %%v=
goto :eof

:split
if %_loop%%==2 goto :split_2
set _loop=2
set _remain=
set splitRev=%3%_splitRev%
set splitRev_comma=%3,%_splitRev_comma%
goto :eof

:split_2
set _remain=%3
goto :eof

:eof

add.bat 看起来像

@echo off
for %%P in (/%1.) do if %%P==: goto %1

call splitt _valueRev1 %1
call splitt _valueRev2 %2

set _result=
set _carry=
for %%d in(%_valueRev1_comma%,0,0,0,0,0) do call %0 :getDig1 %%d

REM Remove leading zeros
:zeroLoop
for %%z in (/%_result%) do set _remain=%%z
if not %_result%==0%_remain% goto :finish
set _result=%_remain%
goto :zeroLoop

:finish
echo %1+%2=%_result%

REM Clear temp vars
FOR %%v in (_result _carry _len _digit1 _digit2 _remain _valueRev1 _valueRev1_comma _valueRev2 _valueRev2_comma) do set %%v=
goto :eof

:getDig1
set _digit1=%2
set _digit2=
for %%d in (/%_valueRev2%0) do call %0 :getDig2 %%d

set _len=%_carry%
call %0 :lenAddDigit %_digit1%
call %0 :lenAddDigit %_digit1%
call %0 :len2val
set _result=%_val%%_result%
goto :eof

:getDig2if not "%_digit2%"==" set _valueRev2=%2
if "%_digit2%"=="" set _digit2=%2
goto :eof

:lenAddDigit
if %2==1 set _len=%_len%#
if %2==2 set _len=%_len%##
if %2==3 set _len=%_len%###
if %2==4 set _len=%_len%####
if %2==5 set _len=%_len%#####
if %2==6 set _len=%_len%######
if %2==7 set _len=%_len%#######
if %2==8 set _len=%_len%########
if %2==9 set _len=%_len%#########
goto :eof

:len2val
set _carry=
set _val=
if %_len%.==. set _val=0
if %_len%.==. goto :eof
if %_len%==# set _val=1
if %_len%==## set _val=2
if %_len%==### set _val=3
if %_len%==#### set _val=4
if %_len%==##### set _val=5
if %_len%==###### set _val=6
if %_len%==####### set _val=7
if %_len%==######## set _val=8
if %_len%==######### set _val=9
if NOT "%_val%"=="" goto :eof
set _carry=#
##########
if %_len%==########## set _val=0
if %_len%==########### set _val=1
if %_len%==############ set _val=2
if %_len%==############# set _val=3
if %_len%==############## set _val=4
if %_len%==############### set _val=5
if %_len%==################ set _val=6
if %_len%==################# set _val=7
if %_len%==################## set _val=8
if %_len%==################### set _val=9
goto :eof

:eof

在MS-DOS 6.22(VMWare)上成功测试

MS-DOS 6.22的限制

  1. IF不支持ELSE

    解决方法:

    IF %1==b echo It is equal
    IF NOT %1==b echo It isn't equal
    
  2. 只有goto可以跳到标签,CALL只能开始另一个批次。

    解决方法:

    将类似的内容放入批处理的第一行

    FOR %%P in (/%1) do IF %%P==: goto %1
    ...
    REM This calls the current batch file and jumps to a label
    CALL %0 :myLabel arg1
    ...
    :myLabel
    echo arg1=%2
    echo Action1
    echo Action2
    goto :eof
    
  3. 没有代码块,例如

    FOR %%a in (1 2 3 ) do ( 
      set concat=%%a
      echo %concat%
    )
    

    解决方法:

    FOR %%a in (1 2 3 ) do CALL %0 :myFunc %%a
    
  4. 没有间接扩展变量

    解决方法:

    set var=content
    set indirect=var
     > temp$$$.bat echo set result=%%%indirect%%%
    call temp$$$.bat
    echo result=%result%
    

答案 1 :(得分:1)

如果您尝试从实际的DOS(而不是Windows从32位时代开始的Windows仿真)中执行此操作,则除非您手动处理输入中可能存在的每对数字(否则难以管理),否则根本不可能当您超过个位数时。

这始终是DOS批处理文件中的一个大缺陷,通常可以通过使用实际脚本语言(例如BASIC)调用小的脚本来补救,这些脚本通常由调用它们的同一.bat文件来写出。当然,这需要为您选择的语言配备翻译。

答案 2 :(得分:1)

这是我所能接近的。给定主脚本称为sum.bat,请提供两个数字作为命令行参数。

这是sum.bat的代码:

@echo off & > nul ver
rem // Define constants here:
set SUB=.\sum-sub.bat
set FILE=.\sum.tmp
set RESULT=.\sum-res.tmp
rem // Check if enough arguments are provided:
if "%2"=="" (>&2 echo ERROR: too few arguments!) & < nul find "" & goto :END
rem // Initialise variables:
set LIST=
rem // Create list of as many space-separated `#` symbols as given by 1st number:
call %SUB% %1
rem // Append list by as many space-separated `#` symbols as given by 2nd number:
call %SUB% %2
rem // Terminate execution in case of unsupported numbers:
if ErrorLevel 1 goto :END
rem // Create empty temporary file:
> nul copy /Y nul %FILE%
rem // Fill temporary file with as many bytes as list items are given:
for %%I in (%LIST%) do (> nul copy /B %FILE% + nul %FILE% /A)
rem // Get size of temporary file, filter out first summary line and store in file:
dir /A:-D /-W /-C %FILE% | find "1 File(s)" > %RESULT%
rem /* Read from file the summary line but display it without "1 File(s)" prefix;
rem    since this is searched literally, the code becomes language-dependent;
rem    the "bytes" suffix unfortunately remains: */
< %RESULT% (
    for %%I in (# # # # # # # # # # # # # # # # # # # # # # # #) do > nul pause
    sort & echo/
)
rem // Clean up temporary files:
del %FILE% %RESULT%
:END

这是子例程sum-sub.bat的代码:

@echo off
rem // Jump to correct entry point to create/append a list with correct length:
2> nul goto :$%1 & < nul find "" & >&2 echo ERROR: unexpected argument!
rem // Do not add anything to the list upon errors:
goto :$0
rem /* Inverse list to add as many space-separated `#` symbols as given by the argument;
rem    extend it in the same manner in order to support numbers greater than `12`: */
:$12
set LIST=%LIST% #
:$11
set LIST=%LIST% #
:$10
set LIST=%LIST% #
:$9
set LIST=%LIST% #
:$8
set LIST=%LIST% #
:$7
set LIST=%LIST% #
:$6
set LIST=%LIST% #
:$5
set LIST=%LIST% #
:$4
set LIST=%LIST% #
:$3
set LIST=%LIST% #
:$2
set LIST=%LIST% #
:$1
set LIST=%LIST% #
:$0

以下是一些用法示例:

>>> sum.bat 1 0
             19 bytes

>>> sum.bat 3 6
              9 bytes

>>> sum.bat 2
ERROR: to few arguments!

>>> sum.bat 1 0
             19 bytes

>>> sum.bat 13 4
ERROR: unexpected argument!

我必须承认我在禁用了命令扩展名的Windows命令提示符中测试了这种方法,但在实际的MS-DOS环境中却没有。