5
votes

Comment obtenir la somme de 2 nombres dans le DOS original?

Je voulais revivre la nostalgie des bons vieux dos.
J'ai testé quelques commandes batch, mais j'ai remarqué que / a n'est pas utilisable dans dos.
Existe-t-il une autre méthode que je peux utiliser pour ajouter deux variables sans inclure /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 states "commutateur invalide. - / a" code > quand j'exécute ce programme.


2 commentaires

Quelle version de Windows ou de DOS est exécutée?


il y a longtemps, mais si je me souviens bien, il n'y avait pas non plus de set / p sous DOS.


3 Réponses :


1
votes

Si vous essayez de le faire à partir du DOS réel (et non de l'émulation de Windows de l'ère 32 bits), ce n'est tout simplement pas possible, à moins que vous ne gériez manuellement chaque paire de nombres possible que vous pourriez avoir en entrée (ce qui devient ingérable lorsque vous dépassez les chiffres à un seul chiffre).

Il s'agissait toujours d'une grande carence dans les fichiers batch de DOS, qui était généralement corrigée en appelant de petits scripts dans des langages de script réels (tels que BASIC), souvent écrits par le même fichier .bat qui les appelait. Ceci, bien sûr, nécessite d'avoir un interprète pour la langue de votre choix.


2 commentaires

IMHO une "réponse" qui indique "vous ne pouvez pas faire ça" n'est pas une bonne réponse, à peine un commentaire ... :(


@Aacini "Votre problème n'a pas de solution" est la meilleure solution possible ici. Les commentaires ne sont pas destinés à durer (la politique a toujours été qu'ils peuvent être supprimés à tout moment, même s'ils ne le sont généralement pas), et "vous ne pouvez pas faire cela" est vraiment la réponse ici . En particulier, étant donné que nous parlons d'un système d'exploitation qui a été abandonné il y a plus de deux décennies, la réponse ne changera pas, et donc "vous pouvez le faire" n'est pas seulement la seule réponse valable maintenant, mais la seule réponse valable pour toujours. "Aucune solution" est une réponse; c'est complètement différent de «je ne sais pas» ou de «non recommandé».



1
votes

C'est aussi proche que possible. Étant donné que le script principal est appelé sum.bat fournissez les deux nombres comme arguments de ligne de commande.

Voici le code de sum.bat :

>>> 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!

Voici le code de la sous-routine 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

Voici quelques utilisations exemples:

@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

Je dois admettre que j'ai testé cette approche dans l'invite de commande Windows avec les extensions de commande désactivées mais pas dans un véritable environnement MS-DOS.


3 commentaires

Je ne pense pas que lang-dos soit une langue connue que le prettifier de code prend en charge. Dans tous les cas, il ne met pas correctement en évidence votre code, donc je pense que vous seriez mieux avec lang-none .


@RossRidge, lang-dos ou lang-cmd semble reconnaître quelques commandes; mais la principale raison pour laquelle je l'utilise est la mise en évidence des "chaînes" et // des remarques, ce que je trouve assez pratique ...


@RossRidge lang-dos n'est en effet pas pris en charge, ce qui lui permettra d'utiliser le surligneur par défaut Y a-t-il une coloration syntaxique pour les opérations de ligne de commande DOS ou les fichiers batch DOS? . lang-vb ou parfois lang-bash est un meilleur choix pour les fichiers batch



2
votes

C'est un peu plus délicat que d'utiliser set / a , mais cela peut être résolu avec MS-DOS 6.22.

Une partie consiste à écrire une fonction pour ajouter des chiffres uniques et une fonction qui peut ajouter plusieurs chiffres.

Le principal problème est de diviser un nombre en un seul chiffre, car MS-DOS ne prend pas en charge la manipulation de chaînes.
Mais il existe un petit défaut dans la gestion de FOR-Loop, / divise un texte en trois parties.

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

Sorties

FOR %%a in (1 2 3 ) do CALL %0 :myFunc %%a

Avec cette astuce, un nombre peut être divisé en un seul chiffre

split.bat

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

Et le add.bat ressemble à

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

Testé avec succès sur un MS-DOS 6.22 (VMWare)

Limitations de MS -DOS 6.22

  1. IF ne prend pas en charge ELSE

    Solution de contournement :

    IF %1==b echo It is equal
    IF NOT %1==b echo It isn't equal
    
  2. Seul goto peut accéder à une étiquette, CALL ne peut démarrer qu'un autre lot.

    Solution de contournement :

    Mettez quelque chose comme ça dans la première ligne de votre lot

    @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
    
  3. Aucun bloc de code, comme

    @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
    

    Solution de contournement:

    abcdef
    g
    hijklmno
    
  4. Pas d'expansion indirecte des variables

    Solution de contournement:

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


1 commentaires

@aschipfl Merci, mais cela semble être la seule gestion des chaînes dans MsDos6.22 et il ne peut pas séparer les délimiteurs d'une chaîne, comme ,;= . J'ai ajouté d'autres limitations et solutions de contournement possibles