web-dev-qa-db-fra.com

Validation d'entrée de fichier par lots - Assurez-vous que l'utilisateur a saisi un entier

J'expérimente avec un fichier de commandes Windows pour effectuer une opération simple qui demande à l'utilisateur de saisir un entier non négatif. J'utilise des techniques simples de traitement par lots pour obtenir les entrées de l'utilisateur:

@ECHO OFF
SET /P UserInput=Please Enter a Number: 

L'utilisateur peut entrer n'importe quel texte ici, alors j'aimerais ajouter une routine pour être sûr que ce que l'utilisateur a entré était un nombre valide. C’est-à-dire… ils ont entré au moins un caractère, et chaque caractère est un nombre compris entre 0 et 9. Je voudrais quelque chose en quoi je peux alimenter l’entrée utilisateur. À la fin de la routine, ce serait comme un if/alors cela exécuterait des instructions différentes selon qu’il s’agissait ou non d’un nombre valide.

J'ai expérimenté des boucles et des sous-chaînes, etc., mais mes connaissances et ma compréhension sont encore minces… toute aide serait donc appréciée.

Je pourrais créer un fichier exécutable, et je sais qu'il existe de meilleures façons de procéder que des fichiers de commandes, mais au moins pour cette tâche, j'essaie de faire simple en utilisant un fichier de commandes.

11
Ben Brandt

Merci a tous. J'essayais de me rendre la tâche plus difficile en regardant les boucles et la manipulation des cordes. J'ai utilisé vos conseils sur l'évaluation et la comparaison des mathématiques. Voici ce que j'ai finalement trouvé comme script de concept:

:Top
@ECHO OFF
ECHO.
ECHO ---------------------------------------
SET /P UserInput=Please Enter a Number: 
ECHO.
ECHO UserInput = %UserInput%
ECHO.
SET /A Evaluated=UserInput
ECHO Math-Evaluated UserInput = %Evaluated%
if %Evaluated% EQU %UserInput% (
    ECHO Integer
    IF %UserInput% GTR 0 ( ECHO Positive )
    IF %UserInput% LSS 0 ( ECHO Negative )
    IF %UserInput% EQU 0 ( ECHO Zero )
    REM - Other Comparison operators for numbers
    REM - LEQ - Less Than or Equal To
    REM - GEQ - Greater Than or Equal To
    REM - NEQ - Not Equal To
) ELSE (
    REM - Non-numbers and decimal numbers get kicked out here
    ECHO Non-Integer
)

GOTO Top

Cette méthode intercepte tous les nombres et peut détecter si elle est positive, négative ou nulle. Toute décimale ou chaîne sera détectée comme non-entier. Le seul cas Edge que j'ai trouvé est une chaîne avec des espaces. Par exemple, le texte "Numéro 1" provoquera le blocage/fermeture du script lorsque l'entrée utilisateur est évaluée en tant que valeur mathématique. Mais dans ma situation, ça va. Je ne veux pas que mon script continue avec une entrée invalide.

5
Ben Brandt

Vous ne le faites probablement pas dans un fichier de commandes DOS. Ou du moins, le support pour set /p est inconnu pour moi sous DOS :-)

Vous pouvez utiliser des sous-chaînes. En fait, j’ai écrit une fois un analyseur syntaxique pour un langage régulier spécifique, mais c’est lourd. Le moyen le plus simple serait probablement d’attribuer le contenu de %userinput% à une autre variable, en utilisant set /a. Si le résultat est 0, vous devez vérifier si l'entrée elle-même était 0, sinon vous pouvez en conclure qu'il ne s'agit pas d'un nombre:

@echo off
setlocal enableextensions enabledelayedexpansion
set /p UserInput=Enter a number: 
set /a Test=UserInput
if !Test! EQU 0 (
  if !UserInput! EQU 0 (
    echo Number
  ) else (
    echo Not a number
  )
) else (
  echo Number
)

Toutefois, cela ne fonctionne que pour les nombres compris entre Int32. Si vous vous souciez simplement d’un nombre (éventuellement d’une virgule flottante également), vous devez recourir à l’approche basée sur la boucle pour le disséquer.

NOTE: Mise à jour pour résoudre les problèmes d'espace. Cependant, un problème persiste: entrer 123/5 donne "nombre", car set /a peut évaluer cela ...

14
Joey

C’est la même idée que celle de Johannes .. SET/A définit une valeur numérique. Si l'entrée n'est pas un nombre, elle passe à 0. C'est ce que vous pouvez exploiter ici pour faire votre vérification. 

@ECHO OFF
SET /P UserInput=Please Enter a Number:
IF %UserInput% EQU 0 GOTO E_INVALIDINPUT

SET /A UserInputVal="%UserInput%"*1
IF %UserInputVal% GTR 0 ECHO UserInput "%UserInputVal%" is a number
IF %UserInputVal% EQU 0 ECHO UserInput "%UserInputVal%" is not a number
GOTO EOF

:E_INVALIDINPUT
ECHO Invalid user input

:EOF

Au lieu de cela, vous pouvez toujours créer un petit fichier javascript et l'appeler à partir de votre fichier batch. Avec parseInt (), vous pouvez forcer l'entrée à être un entier ou lancer votre propre fonction pour tester l'entrée.

L'écriture du code javascript est aussi rapide que celle du fichier batch, mais elle est beaucoup plus puissante. Pas de IDE ni de compilateur requis; bloc-notes fera l'affaire. Fonctionne sur toutes les fenêtres, exactement comme vos fichiers batch. Alors pourquoi ne pas en profiter?

Vous pouvez même mélanger des fichiers batch et du javascript. Exemple:

contenu de sleep.js:

var SleepSecs=WScript.Arguments.Item(0);
WScript.Sleep(SleepSecs*1000)

contenu de sleep.cmd:

cscript /nologo sleep.js %1

Vous pouvez maintenant appeler cela depuis un fichier de commandes pour que votre script se repose pendant 10 secondes. Quelque chose comme cela est difficile à faire avec un simple fichier batch.

sleep 10
6

Vous pouvez également utiliser un truc assez simple:

echo %userinput%|findstr /r /c:"^[0-9][0-9]*$" >nul
if errorlevel 1 (echo not a number) else (echo number)

Ceci utilise les capacités de correspondance d'expression régulière de findstr. Ils ne sont pas très impressionnants mais utiles parfois.

3
Joey

Comme le souligne ghostdog74, les réponses postées par Joey le 26 mars 2009 (score 10) et par Wouter van Nifterick le 26 mars 2009 (score 5) ne fonctionnent pas.

La réponse publiée par Joey le 25 mars 2010 (score 2) fonctionne, sauf que les symboles de redirection et les erreurs de syntaxe '&'.

Je pense que la solution la meilleure et la plus simple est celle publiée par Sager le 8 octobre 2014 (score 0). Malheureusement, il y a une faute de frappe: ""% a "" devrait être ""% a% "".

Voici un fichier de commandes basé sur la réponse de Sager. Les symboles de redirection et '&' dans l'entrée ne posent pas de problèmes. Les seuls problèmes que j'ai pu trouver ont été causés par des chaînes contenant des guillemets doubles.

@echo off & setlocal enableextensions & echo.
set /p input=Enter a string:
SET "x=" & for /f "delims=0123456789" %%i in ("%input%") do set x=%%i
if defined x (echo Non-numeral: "%x:~0,1%") else (echo No non-numerals)
2
Mike D

Vous pourriez aussi aimer celui-ci - c'est court et facile. Celui-ci utilise l'astuce de multiplication pour définir TestVal. En comparant TestVal à UserInput, toutes les valeurs numériques sont comprises, y compris les zéros. Seules les valeurs non numériques déclenchent l'instruction else. Vous pouvez également définir ErrorLevel ou d’autres variables pour indiquer une entrée ayant échoué.

@ECHO OFF
SET TestVal=0

SET /P UserInput=Please Enter a Number:
SET /A TestVal="%UserInput%"*1

If %TestVal%==%UserInput% (
   ECHO You entered the number %TestVal%
   ) else ECHO UserInput "%UserInput%" is not a number

GOTO EOF

:EOF
1
Whiskey Drainer

Je sais que cela fait des années, mais je veux juste partager ma solution.

set /p inp=Int Only : 
:: Check for multiple zeros eg : 00000 ::
set ch2=%inp%-0
if %inp% EQU 0 goto :pass
if [%inp%]==[] echo Missing value && goto :eof
if %inp:~0,1%==- echo No negative integers! && goto :eof
set /a chk=%inp%-10>nul
if %chk%==-10 echo Integers only! && goto :eof
:pass
echo You shall pass
:eof

Testé et fonctionnant sous Windows 8.

1
Flora

En plus de la remarque sur l'erreur qui survient lorsque des espaces font partie de la saisie de l'utilisateur. Vous pouvez utiliser errorlevel errorlevel = 9165. Il peut être utilisé pour les espaces dans une chaîne ou pour le traitement des erreurs de l'entrée "non".

Sincères amitiés,

Egbert

1
Egbert

Vous pouvez utiliser le sous-programme ReadFormattedLine pour tout type d’entrée formatée. Par exemple, la commande ci-dessous lit jusqu'à 5 chiffres:

call :ReadFormattedLine UserInput="#####" /M "Please Enter a Number: "

Ce sous-programme est écrit en Batch pur. Il ne nécessite donc aucun programme supplémentaire et autorise plusieurs opérations d’entrée formatées, comme la lecture de mots de passe. Dans l'exemple précédent, le sous-programme lit jusqu'à 5 chiffres. Vous pouvez télécharger le sous-programme ReadFormattedLine à partir de Lire une ligne au format spécifique .

0
Aacini
:ASK
SET /P number= Choose a number [1 or 2]: 
IF %number% EQU 1 GOTO ONE
IF %number% NEQ 1 (
  IF %number% EQU 2 GOTO TWO
  IF %number% NEQ 2 (
    CLS
    ECHO You need to choose a NUMBER: 1 OR 2.
    ECHO.
    GOTO ASK
  )
)

Cela fonctionne bien pour moi. S'il choisit des nombres inférieurs ou supérieurs, des chaînes, des nombres flottants, etc., il recevra un message ("Vous devez choisir un NUMBER: 1 OR 2.") et le message INPUT sera de nouveau demandé.

0
Nerun

Vous pouvez valider n'importe quelle variable si son numéro:

SET "var="&for /f "delims=0123456789" %i in ("%a") do set var=%i
if defined var (echo."NIC">nul) else (echo."number")
0
Krzysztof Gapski

@echo off setlocal enableextensions enabledelayedexpansion set/p UserInput = Entrez un nombre: set/a Test = UserInput if! Test! EQU 0 ( Si! UserInput! EQU 0 ( Numéro d'écho ) Sinon ( Écho Pas un nombre ) ) sinon ( numéro d'écho )

yeaph tout est génial mais vous oubliez une petite chose 0 est aussi un chiffre ;; (

0
user3367829

vous pouvez réinventer la roue et faire pousser quelques cheveux blancs en validant les chaînes de caractères par lot, ou vous pouvez utiliser vbscript

strInput = WScript.Arguments.Item(0)
If IsNumeric(strInput) Then
    WScript.Echo "1"
Else
    WScript.Echo "0"
End If

enregistrez-le sous le nom checkdigit.vbs et dans votre lot

@echo off
for /F %%A in ('cscript //nologo checkdigit.vbs 100') do (
        echo %%A
        rem use if to check whether its 1 or 0 and carry on from here
)
0
ghostdog74

C'est plus d'une manière conviviale.

if %userinput%==0 (
cls
goto (put place here)
)
if %userinput%==1 (
cls
goto (put place here)
)
if %userinput%==2 (
cls
goto (put place here)
)
if %userinput%==3 (
cls
goto (put place here)
)
if %userinput%==4 (
cls
goto (put place here)
)
if %userinput%==5 (
cls
goto (put place here)
)if %userinput%==6 (
cls
goto (put place here)
)if %userinput%==7 (
cls
goto (put place here)
)
if %userinput%==8 (
cls
goto (put place here)
)
if %userinput%==9 (
cls
goto (put place here)
)

Ceci peut être utilisé pour tout type de saisie utilisateur. 

0
Josh Heaps