Batch IF Statement Block Syntax - if-statement

I have the following code (in batch) to test part of a larger code that isnt working:
#echo off
set /a slotted55=8
set /a place=55
set /a key3=8
set /a key1=0
set /a key2=0
set /a key4=0
set /a key5=0
set /a key6=0
set /a strike=0
if %place%==55 (
if %key1%==%slotted55% (
set key1=V
set slotted55=V
goto 5x5one
) else (
if %key2%==%slotted55% (
set key2=V
set slotted55=V
goto 5x5one
)
) else (
if %key3%==%slotted55% (
set key3=V
set slotted55=V
goto 5x5one
)
) else (
if %key4%==%slotted55% (
set key4=V
set slotted55=V
goto 5x5one
)
) else (
if %key5%==%slotted55% (
set key5=V
set slotted55=V
goto 5x5one
)
) else (
if %key6%==%slotted55% (
set key6=V
set slotted55=V
goto 5x5one
)
) else (
set /a strike=%strike% +1
if %strike%==3 goto gameover
set %slotted55%=X
goto 5x5one
)
)
:gameover
echo gameover
pause
exit
:5x5one
echo good
pause
For some reason, it keeps crashing. I've looked at multiple other questions, but none of them seem to fit this situation. All the variables seem correct, and there are no missing operands, but its not like batch gives you an error message. Can anyone help me?

As I stated in my comment, you do not require any of the else statements, also as your opening if statement does not have an else, you should begin by using the opposite comparison, thus not having everything nested into one set of parentheses.
#Echo Off
SetLocal EnableExtensions
Set "place=55"
Set /A "key3=slotted55=8"
Set /A "key1=key2=key4=key5=key6=strike=0"
If "%place%" NEq "55" GoTo gameover
If "%key1%" == "%slotted55%" (
Set "key1=V"
Set "slotted55=V"
GoTo 5x5one
)
If "%key2%" == "%slotted55%" (
Set "key2=V"
Set "slotted55=V"
GoTo 5x5one
)
If "%key3%" == "%slotted55%" (
Set "key3=V"
Set "slotted55=V"
GoTo 5x5one
)
If "%key4%" == "%slotted55%" (
Set "key4=V"
Set "slotted55=V"
GoTo 5x5one
)
If "%key5%" == "%slotted55%" (
Set "key5=V"
Set "slotted55=V"
GoTo 5x5one
)
If "%key6%" == "%slotted55%" (
Set "key6=V"
Set "slotted55=V"
GoTo 5x5one
)
Set /A strike += 1
If %strike% Equ 3 GoTo gameover
Set "slotted55=X"
GoTo 5x5one
:gameover
Echo gameover
Pause
Exit /B
:5x5one
Echo good
Pause

Because of where you put your )s, all of your else statements are looking at each other instead of the other if statements that you've written. Right now, your logic looks something like this:
if "%x%"=="5" (
echo X is 5
) else (
echo X is not 5
) else (
echo X is somehow neither 5 nor is it not 5
)
If you combine your else with the next if, your logic makes sense again.
set /a strike=0
if %place%==55 (
if %key1%==%slotted55% (
set key1=V
set slotted55=V
goto 5x5one
) else if %key2%==%slotted55% (
set key2=V
set slotted55=V
goto 5x5one
) else if %key3%==%slotted55% (
set key3=V
set slotted55=V
goto 5x5one
) else if %key4%==%slotted55% (
set key4=V
set slotted55=V
goto 5x5one
) else if %key5%==%slotted55% (
set key5=V
set slotted55=V
goto 5x5one
) else if %key6%==%slotted55% (
set key6=V
set slotted55=V
goto 5x5one
) else (
set /a strike=%strike% +1
if %strike%==3 goto gameover
set %slotted55%=X
goto 5x5one
)
)

You are working with incrementing numbers here, you can just use a for loop and have a single if statement inside a for loop:
#echo off
setlocal enabledelayedexpansion
set /a slotted55=8, place=55, key3=8, key1=0, key2=0, key4=0, key5=0, key6=0, strike=0
if %place% neq %slotted55% goto :gameover
for /L %%i in (1,1,6) do (
if !key%%i! equ %slotted55% (
set "key%%i=V"
set "slotted55=V"
goto :5x5one
)
)
:gameover
set /a strike+=1
if %strike% equ 3 (
echo gameover
pause
exit
)
set "slotted55=X"
:5x5one
echo good
pause
For now, there seems to be something missing here though, you will never reach strike=3 unless you have a goto to return to the loop. So this code will work as yours would have without all the else statements.

Related

Windows batch if statement influenced by statements in the if block

When I execute the following Windows batch script on Windows Server 2012:
#echo off
SET v=()
IF 1 == 2 (
echo hi
echo %v:~0%
echo 1 equals 2
) ELSE (
echo 1 does not equal 2
)
IF 1 == 2 (
echo %v:0%
echo 1 equals 2
) ELSE (
echo 1 does not equal 2
)
I get the following output:
1 equals 2
1 does not equal 2
1 does not equal 2
Can anybody tell me why this happens? I don't want to go into the block starting with echo hi even if the value of v is ().
I'm not quite sure what your intention is, but here's how I think your issue can be fixed.
The variable %v% is parsed before the IF command is run, and that contains a problematic closing parenthesis. What happens therefore is that the code reads, echo %v:~0% as echo ( and closes the IF with ) It then parses the next line which is echo 1 equals 2, and prints it as expected.
To prevent that, either escape that parenthesis, when you define that variable:
#echo off
SET "v=(^)"
IF 1 == 2 (
echo hi
echo %v:~0%
echo 1 equals 2
) ELSE (
echo 1 does not equal 2
)
IF 1 == 2 (
echo %v:0%
echo 1 equals 2
) ELSE (
echo 1 does not equal 2
)
Or, better still enable delayed expansion, so that the variable content is not parsed before the command is run, only when it is:
#echo off
SET "v=()"
setlocal enabledelayedexpansion
IF 1 == 2 (
echo hi
echo !v:~0!
echo 1 equals 2
) ELSE (
echo 1 does not equal 2
)
IF 1 == 2 (
echo !v:0!
echo 1 equals 2
) ELSE (
echo 1 does not equal 2
)

Issues with multiple If and Else If statements in command line

Essentially I'm working on a project in command line, and I'm trying to have multiple if statements with multiple conditions to end up with something, in this case, echo displaying something. Here's an example:
if %piece%==1 if %haut%==1 (
if %couleur%==1 (
echo haut 1 1 1
) else if %couleur%==2 (
echo haut 1 1 2
))
if %piece%==1 if %haut%==2 (
if %couleur%==1 (
echo haut 1 2 1
) else if %couleur%==2 (
echo haut 1 2 2
))
Now this works fine, displaying what's shown beside echo, and when I add a second one, it also works fine, like so:
if %piece%==1 if %haut%==1 (
if %couleur%==1 (
echo haut 1 1 1
) else if %couleur%==2 (
echo haut 1 1 2
))
if %piece%==1 if %haut%==2 (
if %couleur%==1 (
echo haut 1 2 1
) else if %couleur%==2 (
echo haut 1 2 2
))
if %piece%==2 if %haut%==1 (
if %couleur%==1 (
echo haut 2 1 1
) else if %couleur%==2 (
echo haut 2 1 2
))
if %piece%==2 if %haut%==2 (
if %couleur%==1 (
echo haut 2 2 1
) else if %couleur%==2 (
echo haut 2 2 2
))
But once I add a third one which has a different second condition, instead of haut it's pantalon, it suddenly crashes the program instead of giving the answer.
if %piece%==1 if %haut%==1 (
if %couleur%==1 (
echo haut 1 1 1
) else if %couleur%==2 (
echo haut 1 1 2
))
if %piece%==1 if %haut%==2 (
if %couleur%==1 (
echo haut 1 2 1
) else if %couleur%==2 (
echo haut 1 2 2
))
if %piece%==2 if %haut%==1 (
if %couleur%==1 (
echo haut 2 1 1
) else if %couleur%==2 (
echo haut 2 1 2
))
if %piece%==2 if %haut%==2 (
if %couleur%==1 (
echo haut 2 2 1
) else if %couleur%==2 (
echo haut 2 2 2
))
if %piece%==3 if %pantalon%==1 (
if %couleur%==1 (
echo pantalon 3 1 1
) else if %couleur%==2 (
echo pantalon 3 1 2
))
if %piece%==3 if %pantalon%==2 (
if %couleur%==1 (
echo pantalon 3 2 1
) else if %couleur%==2 (
echo pantalon 3 2 2
))
I've also tried doing it without the else if, and just having many if statements stacked, but the same problem arises. I'll add the entire code at the end just in case it's needed, but I really don't know what the issue is here and why this is being caused. If someone could help me out, it'd be really appreciated!
Here's the full code:
#echo off
:menu
cls
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Quelle piece vestimentaire voulez-vous?
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo -------
echo Hommes
echo -------
echo Haut (1)
echo.
echo Haut (2)
echo.
echo Pantalon (3)
echo.
echo -------
echo Femmes/Tous genres confondus
echo -------
echo Haut (4)
echo.
echo Jupe (5)
echo.
echo Pantalon (6)
echo.
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo.
set /p piece=
if %piece%==1 goto haut
if %piece%==2 goto haut
if %piece%==3 goto pantalon
if %piece%==4 goto haut
if %piece%==5 goto jupe
if %piece%==6 goto pantalon
:haut
cls
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Quelle style d'haut voulez-vous?
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Haut (1)
echo.
echo Haut (2)
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
set /p haut=
goto couleur
:pantalon
cls
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Quelle style de pantalon voulez-vous?
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Pantalon (1)
echo.
echo Pantalon (2)
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
set /p pantalon=
goto couleur
:jupe
cls
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Quelle style de jupe voulez-vous?
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Jupe (1)
echo.
echo Jupe (2)
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
set /p jupe=
goto couleur
:couleur
cls
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Quelle couleurs voulez-vous?
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Rouge et noir (1)
echo.
echo Blue et noir (2)
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo.
set /p couleur=
:export
cls
if %piece%==1 if %haut%==1 (
if %couleur%==1 (
echo haut 1 1 1
) else if %couleur%==2 (
echo haut 1 1 2
))
if %piece%==1 if %haut%==2 (
if %couleur%==1 (
echo haut 1 2 1
) else if %couleur%==2 (
echo haut 1 2 2
))
if %piece%==2 if %haut%==1 (
if %couleur%==1 (
echo haut 2 1 1
) else if %couleur%==2 (
echo haut 2 1 2
))
if %piece%==2 if %haut%==2 (
if %couleur%==1 (
echo haut 2 2 1
) else if %couleur%==2 (
echo haut 2 2 2
))
if %piece%==3 if %pantalon%==1 (
if %couleur%==1 (
echo pantalon 3 1 1
) else if %couleur%==2 (
echo pantalon 3 1 2
))
if %piece%==3 if %pantalon%==2 (
if %couleur%==1 (
echo pantalon 3 2 1
) else if %couleur%==2 (
echo pantalon 3 2 2
))
if %piece%==4 if %haut%==1 (
if %couleur%==1 (
echo haut 4 1 1
) else if %couleur%==2 (
echo haut 4 1 2
))
if %piece%==4 if %haut%==2 (
if %couleur%==1 (
echo haut 4 2 1
) else if %couleur%==2 (
echo haut 4 2 2
))
if %piece%==5 if %jupe%==1 (
if %couleur%==1 (
echo haut 4 1 1
) else if %couleur%==2 (
echo haut 4 1 2
))
if %piece%==5 if %jupe%==2 (
if %couleur%==1 (
echo haut 4 2 1
) else if %couleur%==2 (
echo haut 4 2 2
))
pause>nul
goto menu
If there's any other information you need I'll be happy to give it!
I would advise that you do not use Set /P to receive expected single digit known input, and instead use the more appropriate and built-in choice.exe utility. This will guarantee that the end user can only provide input from your known list.
As for your if / else, structure, I have removed some unnecessary things, because if many of the options are not 1, they must by default, be 2, so there's no need to ask a second if.
#Echo Off
SetLocal EnableExtensions
:Menu
ClS
Set /A haut=pantalon=jupe=couleur=0
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle piece vestimentaire voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo -------
Echo Hommes
Echo -------
Echo Haut (1)
Echo(
Echo Haut (2)
Echo(
Echo Pantalon (3)
Echo(
Echo -------
Echo Femmes/Tous genres confondus
Echo -------
Echo Haut (4)
Echo(
Echo Jupe (5)
Echo(
Echo Pantalon (6)
Echo(
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo(
%SystemRoot%\System32\choice.exe /C 123456
Set "piece=%ERRORLEVEL%"
If %piece%==1 GoTo Haut
If %piece%==2 GoTo Haut
If %piece%==3 GoTo Pantalon
If %piece%==4 GoTo Haut
If %piece%==5 GoTo Jupe
If %piece%==6 GoTo Pantalon
:Haut
ClS
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle style d'haut voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Haut (1)
Echo(
Echo Haut (2)
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%SystemRoot%\System32\choice.exe /C 12
Set "haut=%ERRORLEVEL%"
GoTo Couleur
:Pantalon
ClS
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle style de pantalon voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Pantalon (1)
Echo(
Echo Pantalon (2)
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%SystemRoot%\System32\choice.exe /C 12
Set "pantalon=%ERRORLEVEL%"
GoTo Couleur
:Jupe
ClS
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle style de jupe voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Jupe (1)
Echo(
Echo Jupe (2)
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%SystemRoot%\System32\choice.exe /C 12
Set "jupe=%ERRORLEVEL%"
GoTo Couleur
:Couleur
ClS
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle couleurs voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Rouge et noir (1)
Echo(
Echo Blue et noir (2)
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo(
%SystemRoot%\System32\choice.exe /C 12
Set "couleur=%ERRORLEVEL%"
:Export
ClS
If %piece%==1 (
If %haut%==1 (
If %couleur%==1 (
Echo haut 1 1 1
) Else (
Echo haut 1 1 2
)
) Else (
If %couleur%==1 (
Echo haut 1 2 1
) Else (
Echo haut 1 2 2
)
)
)
If %piece%==2 (
If %haut%==1 (
If %couleur%==1 (
Echo haut 2 1 1
) Else (
Echo haut 2 1 2
)
) Else (
If %couleur%==1 (
Echo haut 2 2 1
) Else (
Echo haut 2 2 2
)
)
)
If %piece%==3 (
If %pantalon%==1 (
If %couleur%==1 (
Echo pantalon 3 1 1
) Else (
Echo pantalon 3 1 2
)
) Else (
If %couleur%==1 (
Echo pantalon 3 2 1
) Else (
Echo pantalon 3 2 2
)
)
)
If %piece%==4 (
If %haut%==1 (
If %couleur%==1 (
Echo haut 4 1 1
) Else (
Echo haut 4 1 2
)
) Else (
If %couleur%==1 (
Echo haut 4 2 1
) Else (
Echo haut 4 2 2
)
)
)
If %piece%==5 (
If %jupe%==1 (
If %couleur%==1 (
Echo jupe 5 1 1
) Else (
Echo jupe 5 1 2
)
) Else (
If %couleur%==1 (
Echo jupe 5 2 1
) Else (
Echo jupe 5 2 2
)
)
)
If %piece%==6 (
If %pantalon%==1 (
If %couleur%==1 (
Echo pantalon 6 1 1
) Else (
Echo pantalon 6 1 2
)
) Else (
If %couleur%==1 (
Echo pantalon 6 2 1
) Else (
Echo pantalon 6 2 2
)
)
)
Pause 1>NUL
GoTo Menu
Personally however, I'd perform the if section more like this:
If %piece%==1 If %haut%==1 (
If %couleur%==1 (Echo haut 1 1 1) Else Echo haut 1 1 2
) Else If %couleur%==1 (Echo haut 1 2 1) Else Echo haut 1 2 2
If %piece%==2 If %haut%==1 (
If %couleur%==1 (Echo haut 2 1 1) Else Echo haut 2 1 2
) Else If %couleur%==1 (Echo haut 2 2 1) Else Echo haut 2 2 2
If %piece%==3 If %pantalon%==1 (
If %couleur%==1 (Echo pantalon 3 1 1) Else Echo pantalon 3 1 2
) Else If %couleur%==1 (Echo pantalon 3 2 1) Else Echo pantalon 3 2 2
If %piece%==4 If %haut%==1 (
If %couleur%==1 (Echo haut 4 1 1) Else Echo haut 4 1 2
) Else If %couleur%==1 (Echo haut 4 2 1) Else Echo haut 4 2 2
If %piece%==5 If %jupe%==1 (
If %couleur%==1 (Echo jupe 5 1 1) Else Echo jupe 5 1 2
) Else If %couleur%==1 (Echo jupe 5 2 1) Else Echo jupe 5 2 2
If %piece%==6 If %pantalon%==1 (
If %couleur%==1 (Echo pantalon 6 1 1) Else Echo pantalon 6 1 2
) Else If %couleur%==1 (Echo pantalon 6 2 1) Else Echo pantalon 6 2 2
If all you are doing is really just echoing those values, I'd offer the following modified script, (without changing your screen layout).
#Echo Off
SetLocal EnableExtensions DisableDelayedExpansion
:Menu
ClS
Set /A haut=pantalon=jupe=couleur=0
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle piece vestimentaire voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo -------
Echo Hommes
Echo -------
Echo Haut (1)
Echo(
Echo Haut (2)
Echo(
Echo Pantalon (3)
Echo(
Echo -------
Echo Femmes/Tous genres confondus
Echo -------
Echo Haut (4)
Echo(
Echo Jupe (5)
Echo(
Echo Pantalon (6)
Echo(
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo(
%SystemRoot%\System32\choice.exe /C 123456
Set "piece=%ERRORLEVEL%"
If %piece%==1 GoTo Haut
If %piece%==2 GoTo Haut
If %piece%==3 GoTo Pantalon
If %piece%==4 GoTo Haut
If %piece%==5 GoTo Jupe
If %piece%==6 GoTo Pantalon
:Haut
ClS
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle style d'haut voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Haut (1)
Echo(
Echo Haut (2)
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%SystemRoot%\System32\choice.exe /C 12
Set "haut=%ERRORLEVEL%"
GoTo Couleur
:Pantalon
ClS
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle style de pantalon voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Pantalon (1)
Echo(
Echo Pantalon (2)
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%SystemRoot%\System32\choice.exe /C 12
Set "pantalon=%ERRORLEVEL%"
GoTo Couleur
:Jupe
ClS
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle style de jupe voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Jupe (1)
Echo(
Echo Jupe (2)
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
%SystemRoot%\System32\choice.exe /C 12
Set "jupe=%ERRORLEVEL%"
GoTo Couleur
:Couleur
ClS
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Quelle couleurs voulez-vous?
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo Rouge et noir (1)
Echo(
Echo Blue et noir (2)
Echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Echo(
%SystemRoot%\System32\choice.exe /C 12
Set "couleur=%ERRORLEVEL%"
:Export
ClS
For %%G In (haut pantalon jupe) Do (SetLocal EnableDelayedExpansion
For %%H In (!%%G!) Do EndLocal & If %%H Gtr 0 Set "var=%%G" & Set "val=%%H")
Echo %var% %piece% %val% %couleur%
Pause 1> NUL
GoTo :Menu
#ECHO OFF
SETLOCAL
:menu
FOR %%b IN (haut pantalon jupe couleur) DO SET /a %%b=0
CALL :accepter piece "piece vestimentaire" 123456 2 "Hommes" "Femmes/Tous genres confondus" 3 "Haut" "Haut" "Pantalon" 3 "Haut" "Jupe" "Pantalon"
GOTO piece%piece%
:haut
:Piece1
:Piece2
:Piece4
CALL :accepter haut "style d'haut" 12 0 2 "Haut" "Haut"
goto couleur
:pantalon
:piece3
:piece6
CALL :accepter pantalon "style de pantalon" 12 0 2 "Pantalon" "Pantalon"
goto couleur
:jupe
:piece5
CALL :accepter jupe "style de jupe" 12 0 2 "Jupe" "Jupe"
goto couleur
:couleur
CALL :accepter couleur "couleurs" 12 0 2 "Rouge et noir" "Blue et noir"
:export
cls
ECHO haut %haut% pantalon %pantalon% jupe %jupe% couleur %couleur%
pause>nul
goto menu
:: receive user input
:: %1 : receiving variable
:: %2 : Menu prompt
:: %3 : options list
:: %4 : number of groups
:: %5 : name of group (repeats %4 times)
:: %then : number of options within group
:: %followedby : Option name
:: %then, %followedby may be repeated
:accepter
cls
SETLOCAL ENABLEDELAYEDEXPANSION
:: remove variables starting groupname
For %%b IN (groupname) DO FOR /F "delims==" %%a In ('set %%b 2^>Nul') DO SET "%%a="
SET "value=%1"
shift
SET "menuprompt=%~1"
shift
SET "options=%1"
SHIFT
SET "groups=%1"
SHIFT
SET /a groupcount=%groups%
SET /a groupindex=0
:getgroupname
IF %groupcount% neq 0 SET /a groupindex+=1&SET "groupname[!groupindex!]=%~1"&SHIFT&IF !groupindex! neq %groupcount% GOTO getgroupname
SET groupname
::
SET /a groupindex=0
SET /a option=0
SET "unusedoptions=%options%"
::
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo Quelle %menuprompt% voulez-vous?
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:: Display group
:displaygroup
SET /a groupindex+=1
IF DEFINED groupname[%groupindex%] (
echo -------
echo !groupname[%groupindex%]!
echo -------
)
SET numoptionsingroup=%1&SHIFT
:showoption
IF %numoptionsingroup% gtr 0 (
ECHO %~1 (!unusedoptions:~0,1!^)
ECHO.
SET "unusedoptions=!unusedoptions:~1!"
SHIFT
SET /a numoptionsingroup-=1
GOTO showoption
)
IF DEFINED unusedoptions GOTO displaygroup
echo.
echo ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
echo.
choice /c %options% /M "%menuprompt%"
endlocal&SET %value%=%errorlevel%
GOTO :eof

Generate pseudo-random list in Perl

I have a list with 79 entries that each look similar to this:
"YellowCircle1.png\tc\tColor"
That is, each entry has 3 elements (.png-file, a letter, and a category). The category can be color, number or shape.
I want to create a new list from this, pseudo-randomized. That is, I want to have all 79 entries in a random order, but with a limitation.
I have created a perl script for a completely random version using shuffle:
# !/usr/bin/perl
# Perl script to generate input list for E-Prime experiment
# with semi-randomized trials
# Date: 2020-12-30
# Open text file
$filename = 'output_shuffled.txt';
open($fh, '>', $filename) or die "Could not open file '$filename'";
# Generate headline
print $fh "Weight\tNested\tProcedure\tCardIMG1\tCardIMG3\tCardIMG4\tCardStim\tCorrectAnswer\tTrialType\n";
# Array with list of stimuli including corresponding correct response and trial type
#stimulus = (
"BlueCross1.png\tm\tColor",
"BlueCross2.png\tm\tColor",
"BlueStar1.png\tm\tColor",
"BlueStar3.png\tm\tColor",
"BlueTriangle2.png\tm\tColor",
"BlueTriangle3.png\tm\tColor",
"GreenCircle1.png\tv\tColor",
"GreenCircle3.png\tv\tColor",
"GreenCircle1.png\tv\tColor",
"GreenCircle3.png\tv\tColor",
"GreenCross1.png \tv\tColor",
"GreenCross4.png\tv\tColor",
"GreenTriangle3.png\tv\tColor",
"GreenTriangle4.png\tv\tColor",
"RedCircle2.png\tc\tColor",
"RedCircle3.png\tc\tColor",
"RedCross2.png\tc\tColor",
"RedCross4.png\tc\tColor",
"RedStar3.png\tc\tColor",
"RedStar4.png\tc\tColor",
"YellowCircle1.png\tn\tColor",
"YellowCircle2.png\tn\tColor",
"YellowStar1.png\tn\tColor",
"YellowTriangle2.png\tn\tColor",
"YellowTriangle4.png\tn\tColor",
"BlueCross1.png\tc\tNumber",
"BlueCross2.png\tv\tNumber",
"BlueStar1.png\tc\tNumber",
"BlueStar3.png\tn\tNumber",
"BlueTriangle2.png\tv\tNumber",
"GreenCircle1.png\tc\tNumber",
"GreenCircle3.png\tn\tNumber",
"BlueCross1.png\tm\tColor",
"BlueCross2.png\tm\tColor",
"BlueStar1.png\tm\tColor",
"BlueStar3.png\tm\tColor",
"BlueTriangle2.png\tv\tNumber",
"BlueTriangle3.png\tn\tNumber",
"GreenCircle1.png\tc\tNumber",
"GreenCircle3.png\tn\tNumber",
"GreenCross1.png\tc\tColor",
"GreenCross4.png\tm\tColor",
"GreenTriangle3.png\tn\tColor",
"GreenTriangle4.png\tm\tColor",
"RedCircle2.png\tv\tNumber",
"RedCircle3.png\tn\tNumber",
"RedCross2.png\tv\tNumber",
"RedCross4.png\tm\tNumber",
"RedStar3.png\tn\tColor",
"RedStar4.png\tm\tColor",
"YellowCircle1.png\tc\tColor",
"YellowCircle2.png\tv\tColor",
"YellowStar1.png\tc\tNumber",
"YellowStar4.png\tm\tNumber",
"YellowTriangle2.png\tv\tNumber",
"YellowTriangle4.png\tm\tNumber",
"BlueCross1.png\tn\tShape",
"BlueCross2.png\tn\tShape",
"BlueStar1.png\tv\tShape",
"BlueStar3.png\tv\tShape",
"BlueTriangle2.png\tc\tShape",
"BlueTriangle3.png\tc\tShape",
"GreenCircle1.png\tm\tShape",
"GreenCircle3.png\tm Shape",
"GreenCross1.png\tn\tShape",
"GreenCross4.png\tn\tShape",
"GreenTriangle3.png\tc\tShape",
"GreenTriangle4.png\tc\tShape",
"RedCircle2.png\tm\tShape",
"RedCircle3.png\tm\tShape",
"RedCross2.png\tn\tShape",
"RedCross4.png\tn\tShape",
"RedStar3.png\tv\tShape",
"RedStar4.png\tv\tShape",
"YellowCircle1.png\tm\tShape",
"YellowCircle2.png\tm\tShape",
"YellowStar1.png\tv\tShape",
"YellowStar4.png\tv\tShape",
"YellowTriangle2.png\tc\tShape",
"YellowTriangle4.png\tc\tShape",
);
# Shuffle --> Pick at random without double entries
use List::Util 'shuffle';
#shuffled = shuffle(#stimulus);
# Print each line with fixed values and shuffled stimulus entries to file
print $fh "1\t" . "\t" . "TrialProc\t" . "RedTriangle1.png\t" . "Greenstar2.png\t" . "YellowCross3.png\t" . "BlueCircle4.png\t" . "\t$_\n" for #shuffled;
# Close text file
close($fh);
# Print to terminal
print "Done\n";
However, what I eventually want is that the category does not switch more than once successively, but every 3 up to 5 times (randomly between these numbers). For example, if one line ends with "shape" and the following line with "color", the next line would have to be "color", because otherwise there would be 2 switches successively.
How would I create this? I suspect I would have to change the entries to something like hashes, so that I can create if-constructions based on the last element (that is "category") of each entry?
The solution - as you already guessed - is to split the data and reshuffle the parts that dont fit with your rules.
Here is the code that does that.
# Shuffle --> Pick at random without double entries
use List::Util 'shuffle';
my #data = shuffle(map {[split("\t")]} #stimulus);
my #result, %used;
my $next = 0;
while (#result < #data) {
my $pick = pick($next);
if ($pick >= 0) {
push #result, $pick;
$used{$pick} = 1;
$next = 0;
} elsif (#result == 0) {
die "no valid solution found"
} else {
## backtrack
print ".";
$next = pop( #result )+1;
$used{$next-1} = 0;
}
}
my #shuffled = map {join("\t", #{$data[$_]})} #result;
using backtracking if no solution is found. (This is highly inefficient - a reshuffling would probably be better)
It uses a sub pick which returns the index of a next fitting entry. (If possibe)
sub pick {
my $next_element = shift;
foreach my $element ($next_element .. $#data) {
next if $used {$element};
my $type = $data[$element][2];
if( $data[$result[-1]][2] eq $type ){
if (#result >3) {
next
if ($type eq $data[$result[-2]][2] &&
$type eq $data[$result[-3]][2] &&
$type eq $data[$result[-4]][2] )
}
} else {
if (#result >1) {
next
if ($data[$result[-1]][2] ne $data[$result[-2]][2]);
}
}
return $element;
}
return -1;
}
In the sub pick
if( $data[$result[-1]][2] eq $type ){
if (#result >3) {
next
if ($type eq $data[$result[-2]][2] &&
$type eq $data[$result[-3]][2] &&
$type eq $data[$result[-4]][2] )
}
disallows 5 times the same type in a row. If you want only to dissalow 6 times the same type you have to change it to
if( $data[$result[-1]][2] eq $type ){
if (#result >4) {
next
if ($type eq $data[$result[-2]][2] &&
$type eq $data[$result[-3]][2] &&
$type eq $data[$result[-4]][2] &&
$type eq $data[$result[-5]][2] )
}
The code:
if (#result >1) {
next
if ($data[$result[-1]][2] ne $data[$result[-2]][2]);
}
enforces 3 times (at least) the same type. If you want to change this to 4 times you have to use
if (#result >2) {
next
if ($data[$result[-1]][2] ne $data[$result[-2]][2]
|| $data[$result[-1]][2] ne $data[$result[-3]][2]);
}

batch: if..then..else nested make me mad

I've wrote a subroutine with some if..else nested
Unfortunately i can't understand why my code are executed before and after the "ELSE" (!!)
I read it for hours, but i don't find any error.. can you help me?
I copied the code (with a lot of echo-debugs) and the output
This is my little code:
setlocal
set debug=echo
%debug% # %~0: %*
for /f "usebackq tokens=1-3 delims=;" %%a in ('"%*"') do (set dir=%%~a& set own=%%~b)
%debug% - dir="!dir!"
%debug% - own="!own!"
%debug% -+ analisi cartella: "!dir!"
if exist "!dir!" (
%debug% x la cartella esiste già, passo oltre
) else (
%debug% - la cartella non esite quindi la creo
mkdir "!dir!" || echo [E] non sono riuscito a creare la cartella&& echo %err3_txt% [dir:!dir!] 1>&2 && exit %err3_id%
)
%debug% -+ analisi proprietario: "!own!"
for /f "usebackq tokens=1,2 delims=\" %%x in ('"!own!\\"') do (set own1=%%~x& set own2=%%~y)
if [!own!] equ [!own:~0,1! ] (
%debug% x il proprietario non è stato specificato quindi non va cambiato, passo oltre
) else (
%debug% - own1: "!own1!"
%debug% - own2: "!own2!"
if [%own2%] equ [] (
%debug% - il proprietario ha un dominio implicito, lo calcolo
set ownn=%own1%
set ownd=%userdomain%
) else (
%debug% - il proprietario ha un dominio esplicitamente indicato
set ownd="input non valido"
if /i [!own1!] equ [L] set ownd=%computername%
if /i [!own1!] equ [D] set ownd=%userdomain%
if "%ownd%" equ "input non valido" (echo [E] il dominio esplitamente indicato non è riconosciuto: !own1!& echo %err4_txt% [dir:!dir!][own:!own!] 1>&2 & exit %err4_id%)
)
%debug% - la configurazione prevede l'impostazione del seguente proprietario: !ownd!\!ownn!
)
%debug% x done.
this is my output :
# :CSG_check_fs: C:; ;
- dir="C:"
- own=" "
-+ analisi cartella: "C:"
x la cartella esiste giÓ, passo oltre
-+ analisi proprietario: " "
x il proprietario non Þ stato specificato quindi non va cambiato, passo oltre
- own1: " "
- own2: ""
- il proprietario ha un dominio implicito, lo calcolo
- la configurazione prevede l'impostazione del seguente proprietario: CSG\
x done.
in particular, let us appropriate commands are executed BEFORE and AFTER the else clause!!!
why??? this thing is incredible!! or am i too tired?
It is certainly very odd. CMD seems to be having a real problem with this very complex statement (and so do I...) :
if [!own!] equ [!own:~0,1! ] (
%debug% x il proprietario non è stato specificato quindi non va cambiato, passo oltre
) else (
%debug% - own1: "!own1!"
%debug% - own2: "!own2!"
if [%own2%] equ [] (
%debug% - il proprietario ha un dominio implicito, lo calcolo
set ownn=%own1%
set ownd=%userdomain%
) else (
%debug% - il proprietario ha un dominio esplicitamente indicato
set ownd="input non valido"
if /i [!own1!] equ [L] set ownd=%computername%
if /i [!own1!] equ [D] set ownd=%userdomain%
if "%ownd%" equ "input non valido" (echo [E] il dominio esplitamente indicato non è riconosciuto: !own1!& echo %err4_txt% [dir:!dir!][own:!own!] 1>&2 & exit %err4_id%)
)
%debug% - la configurazione prevede l'impostazione del seguente proprietario: !ownd!\!ownn!
)
Looking at
if [!own!] equ [!own:~0,1! ] (
You may think that this should be evaluated, with OWN set to a single space, as
if [ ] equ [ ] (
Which should generate a syntax error because the third token in the command is ] and that's not a valid comparison-operator. The !var! confuses matters because it can't be evaluated until EXECUTION TIME - and by then, the parser has finished its work.
The correct form is
if "%own%" equ "%own:~0,1% " (
because the parser can then substitute the CURRENT (ie. PARSE-TIME) value of own and the syntax is "quoted string" operator "another quoted string"
I'm sure that this change would solve the major part of the problem.
Similarly,
if [%own2%] equ [] (
should be
if "%own2%" equ "" (
or even (my preference)
if not defined own2
and the same goes for the other IF [..] equ [...] constructs.
Finally, in the sequence
set ownd="input non valido"
if /i [!own1!] equ [L] set ownd=%computername%
if /i [!own1!] equ [D] set ownd=%userdomain%
if "%ownd%" equ "input non valido" (echo [E] il dominio ...
there's a small problem (other than the if..[...
ownd may be SET within the code, but the %ownd% in the last of these lines will have the PARSE-TIME value of ownd substituted, so it's unlikely to contain the target string. Here's where you NEED !var! because the value of var is being changed by the code and you want the changed value, not the value as it stood when the statement was parsed.
HTH
Imo this might be not perfect, but please keep in mind, this is no de-bugging service here & I'm not your father, Luke.
# echo off&setlocal
for /f "usebackq tokens=1-3 delims=;" %%a in ("%*") do (set dir=%%~a& set own=%%~b)
if not exist "%dir%" mkdir "%dir%" || echo [E] non sono riuscito a creare la cartella&& echo %err3_txt% [dir:%dir%]&& exit %err3_id%
for /f "usebackq tokens=1,2 delims=\" %%x in ("%own%\\") do (set own1=%%~x& set own2=%%~y)
if not [%own%] equ [%own:~0,1%] (
if [%own2%] equ [] (
set ownn=%own1%
set ownd=%userdomain%
) else (
set "ownd=input non valido"
if /i [%own1%] equ [L] set ownd=%computername%
if /i [%own1%] equ [D] set ownd=%userdomain%
if "%ownd%" equ "input non valido" (echo [E] il dominio esplitamente indicato non è riconosciuto: %own1%& echo %err4_txt% [dir:%dir%][own:%own%]& exit %err4_id%)
)
)

How can I match certain nested parentheses in Perl?

^\s*[)]*\s*$ and ^\s*[(]*\s*$ matches the parentheses ( and ) which are bold. That is, what am trying is to ignore parentheses that are single and not (condition1) parentheses:
while
( #matches here
( #matches here
(condition1) && (condition2) &&
condition3
) ||
(#matches here
(condition4) ||
condition5 &&
(condition6)
) #matches here
) #matches here
but if I have like this it does not match:
while
(( #does not match here
(condition1) && (condition2) &&
condition3
) ||
(
(condition4) ||
condition5 &&
(condition6)
) ) #does not match here
or
while
((( #does not match here
(condition1) && (condition2) &&
condition3
)) ||
(( #does not match here
(condition4) ||
condition5 &&
(condition6)
) ) ) #does not match here
How can I match all the parentheses that are single?
I'd personally recommend that you use a simple stack to figure out open and closing brackets rather than trip over regular expressions.