Reputation: 930
I seem to be having tons of trouble making this program. I finally only have one more error. Here is my code:
:tutq
echo What is the first letter of your name?
echo 1(A
echo 2(B
echo 3(C
echo 4(D
echo 5(E
echo 6(F
echo 7(G
echo 8(H
echo 9(I
echo 10(J
echo 11(K
echo 12(L
echo 13(M
echo 14(N
echo 15(O
echo 16(P
echo 17(Q
echo 18(R
echo 19(S
echo 20(T
echo 21(U
echo 22(V
echo 23(W
echo 24(X
echo 25(Y
echo 26(Z
set /p tutnum=
If not defined !tutnum! (
cls
goto tutq
)
If "!tutnum!" == "1" (
set "tutlet=A"
goto tutp2
)
If "!tutnum!" == "2" (
set "tutlet=B"
goto tutp2
)
If "!tutnum!" == "3" (
set "tutlet=C"
goto tutp2
)
If "!tutnum!" == "4" (
set "tutlet=D"
goto tutp2
)
If "!tutnum!" == "5" (
set "tutnum=E"
goto tutp2
)
If "!tutnum!" == "6" (
set "tutlet=F"
goto tutp2
)
If "!tutnum!" == "7" (
set "tutlet=G"
goto tutp2
)
If "!tutnum!" == "8" (
set "tutlet=H"
goto tutp2
)
If "!tutnum!" == "9" (
set "tutlet=I"
goto tutp2
)
If "!tutnum!" == "10" (
set "tutlet=J"
goto tutp2
)
If "!tutnum!" == "11" (
set "tutlet=K"
goto tutp2
)
If "!tutnum!" == "12" (
set "tutlet=L"
goto tutp2
)
If "!tutnum!" == "13" (
set "tutlet=M"
goto tutp2
)
If "!tutnum!" == "14" (
set "tutlet=N"
goto tutp2
)
If "!tutnum!" == "15" (
set "tutlet=O"
goto tutp2
)
If "!tutnum!" == "16" (
set "tutlet=P"
goto tutp2
)
If "!tutnum!" == "17" (
set "tutlet=Q"
goto tutp2
)
If "!tutnum!" == "18" (
set "tutlet=R"
goto tutp2
)
If "!tutnum!" == "19" (
set "tutlet=S"
goto tutp2
)
If "!tutnum!" == "20" (
set "tutlet=T"
goto tutp2
)
If "!tutnum!" == "21" (
set "tutlet=U"
goto tutp2
)
If "!tutnum!" == "22"(
set "tutlet=V"
goto tutp2
)
If "!tutnum!" == "23" (
set "tutlet=W"
goto tutp2
)
If "!tutnum!" == "24" (
set "tutlet=X"
goto tutp2
)
If "!tutnum!" == "25" (
set "tutlet=Y"
goto tutp2
)
If "!tutnum!" == "26" (
set "tutlet=Z"
goto tutp2
)
:tutp2
echo Congrats!
echo If you did the exersize correct
echo The first letter of your name should be "!tutlet!"
pause
Anyways if you could explain to me whats wrong.
Upvotes: 0
Views: 74
Reputation: 80213
You've accepted a good answer - please leave it that way. This is supplemental information that may prove useful, if not to you then to others facing the same problem.
@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "letequ=a(1 b(2 c(3 d(4 e(5"
:tutq
cls
FOR %%a IN (%letequ%) DO echo %%a
SET "tutnum="
SET /p "tutnum=What is the first letter of your name? "
IF NOT DEFINED tutnum GOTO tutq
FOR %%a IN (%letequ%) DO (
SET letterandnumber=%%a
SET "letter=!letterandnumber:~0,1!"
SET "number=!letterandnumber:~2!"
IF "!number!"=="%tutnum%" (
ECHO The first letter of your name is "!letter!"&pause&GOTO :EOF)
)
GOTO tutq
So - I didn't bother to complete the letter/number set. It should be fairly obvious how to do that.
Note the technique of setting a string-value. That syntax ensures trailing spaces on a line are not included in the value assigned, which can sometimes cause problems. For instance,
SET tutnum=
should clear tutnum
out of the environment which means that as far as cmd
is concerned, it has a value of nothing but if there are stray (and conveniently invisible) spaces on the end of the line, it would be set to those spaces and if defined tutnum
would be true.
SET "tutnum="
would clear tutnum
as desired, stray spaces or no.
Setting a variable just before a set /p
may seem superfluous, but if the response to a set /p
is simply Enter then the variable will remain unchanged - it will not automatically have no value as may be assumed. This technique can be used to assign a default value
set "var=default"
set /p "var=prompt-string"
will leave default
assigned to var
if the user responds Enter
This could be used like
set "var=default"
set /p "var=prompt-string [%var%]"
To show the user the value that will be used if the user responds Enter
Next item to be examined is the for
loops. for
can be subject to all kinds of jiggery-pokery, but the basic for is
for %%x in (list of items separated by spaces) do something
where each item in the list in turn is assigned to %%a
, so each item in the list leteq
is assigned in turn to %%a
and %%a
adopts the values "a(1" "b(2" "c(3" "d(4" and "e(5", then does something with that value.
In the case of the analyse-the-entry portion of the code, something is
SET letterandnumber=%%a
SET "letter=!letterandnumber:~0,1!"
SET "number=!letterandnumber:~2!"
IF "!number!"=="%tutnum%" (
ECHO The first letter of your name is "!letter!"&pause&GOTO :EOF)
The object here is to substring the value in %%a
example: "c(3". We can't do a direct substring of %%a
, so we assign %%a
's value to letterandnumber
and substring that.
The substring syntax is
%var:~m,n%
var
, starting at "character 0"var
n
is the length of the substringvar
%
may be !
for delayedexpansion
modeSo letter
is set to ~0,1
that is, the first character for a length of 1 of letterandnumber
and similarly number
is set to ~2
- the third letter up to the end of the string.
Since letterandnumber
is set within the loop (or in any parenthesised sequence of statements, aka "a block") then it may appear as two separate values. %letterandnumber%
refers to the value at the time the block is first encountered and parsed whereas !letterandnumber!
refers to the value at run-time as it might be set within the block. The !var!
syntax is only valid if a setlocal enabledelayedexpansion
command has previously been executed.
The reason is that cmd
replaces any %var%
with the current value of var
, then checks the statement for validity. !var!
is not replaced until the block is executed.
The consequence of this sequence is significant and if not understood can lead to some vigorous head-scratching.
Suppose we have (note that close-parentheses ase used, not open)
SET "letequ=a)1 b)2 c)3"
FOR %%a IN (%letequ%) DO echo %%a
This will lead to a syntax error because cmd
will first replace leteq
with its then-current value and then parse it, so it sees
FOR %%a IN (a)1 b)2 c)3) DO echo %%a
assumes that the first close-parenthesis ends the list and expects a do
but finds 1
so it reports the problem.
One way to solve this problem is to escape the misinterpreted ) by preceding it with a caret ^
SET "letequ=a^)1 b^)2 c^)3"
FOR %%a IN (%letequ%) DO echo %%a
cmd
now sees FOR %%a IN (a^)1 b^)2 c^)3) DO echo %%a
and recognises that ^)
means "this parenthesis is data, not part of the command" It's therefore happy with the syntax and proceeds to execute the code.
Another way is this (if delayedexpansion is in effect)
SET "letequ=a)1 b)2 c)3"
FOR %%a IN (!letequ!) DO echo %%a
cmd
does not substitute the value until after the command has passed the validity check so no error is raised.
Upvotes: 0
Reputation: 14370
Your code is actually doing exactly what you told it to, it's just going so fast you can't notice it.
When you are checking to see if a variable exists, don't wrap it in %
s or !
. if not defined varname
essentially says, "if there is no variable called 'varname', then do this..."; when you surround it with %
or !
, you replace the variable with its value. If I entered 10
at the prompt, the code would be saying "If there is no variable called 10, then clear the screen and go back to tutq." Since there is no variable called 10, you're stuck in an infinite loop.
Change If not defined !tutnum! (
to If not defined tutnum (
and your code will work.
Upvotes: 1