SetLocal EnableDelayedExpansion - Array Variable with Variable Index - dynamic variable

1

1

Oh the 10K and 20K and 100K will want to call this a duplicate.. but it's not.

The reason for this is merely:
Use Array Variable, "arr" Use a counting variable, "x", or whatever
Compare array index:
Does arr[0] == arr[1] ? (but with dynamic counting vars)
You can't do that with -- For /L (0,1, length), because set x+=1 and also the variable !arr! can't, or I don't know how, work together as both variables.
I've tried using %x% and !x! and setlocal and not using setlocal...

I can't seem to get the correct combination of variable syntax.
e.g.
!arr[%x%]!
!arr[!x!]!
%%arr[%x%]%%
etc.

In other words: arr[x] == arr[x+1] ? in a loop comparison

Set "inName=%~1"

Set arrCount=0
Set count=0
Set arr = []

:: Do some work
:: Some code delted for clarity of problem at hand
:: populate the arr (array)

:loop
call set "char=%%inName:~%count%,1%%"
If defined char (
    echo %count%[%char%]
    Set arr[%count%]=%char%
    Set /a arrCount+=1
    Set /a count+=1
    Set trimName=%trimName%%char%
    goto :loop
)
Set x=0

setlocal enableDelayedExpansion


REM fails of tried variable variations
::  echo array is %arrCount% in length
::  call echo X is %x% at %%arr[%x%]%%
::  call echo letter: %%arr[%x%]%% 
::  define: !arr[%x%]! !arr[!!x!!]! !!arr[!x!]!! and other variations

:SymLoop 
if defined !arr[%x%]! (
    echo X---: !arr[%x%]!
    CALL :increment RESULT x
    GOTO :SymLoop 
)
:: Different methods of resetting x to zero. Both fail

set /a x=0
CALL :reset_one RESULT x

:: For loop, using counter

for /L %%F in (0,1,%arrCount%) do (
    echo !arr[%%F]! and !arr[%x%]! vs !arr[!%x%!]!  -- x is !x!
    call Set /A x+=1
    REM CALL :increment RESULT x
)

endlocal

EXIT

:increment
    SET /A countArray+=1    SET /A x+=1


:reset_one  SET /A x=0

The input to this batch file is: some__name


Loops I've tried as you an see:
I have tried executing a simulated loop, via GOTO:SymLoop
Also, tried reading, echoing, array, via If defined !arr[%x%]!


RESULTS: I can get x to increment, but the combination of "arr" and "x" no

s and s vs 0  -- x is 0
o and s vs 0  -- x is 1
m and s vs 0  -- x is 2
e and s vs 0  -- x is 3
_ and s vs 0  -- x is 4
_ and s vs 0  -- x is 5
n and s vs 0  -- x is 6
a and s vs 0  -- x is 7
m and s vs 0  -- x is 8
e and s vs 0  -- x is 9
 and s vs 0  -- x is 10

The input: "some__name", will be compared with passing "some_name" into the batch file mybatch.bat >C:....>mybatch some__name



basically I populate the array [s][o][m]...
I want to ask: index 0 match index 1?
Later I will ask, is index-n of char "" and also index-n+1 of char "" ?


edit: I've come across a statement, comment, and found this. I'm not a Windows engineer. I use my skills as a programmer to get by in batch file creation. So I don't fully understand the deeper issues of my logic. From what I've read in the web "call echo" is a layer of expansion? So it works as if "setlocal enabledelaytedexpansion..." ? Somehow the second line "call echo" works, which leads me to believe that arr is indeed defined.

Set x=0
::fails
echo Array: arr[0] is %%arr[%x%]%%
::works 
Call echo Array: arr[0] is %%arr[%x%]%%

EDIT FIX
From Comment Suggestion:
if defined arr[%x%] ( could work. Read if /?: the correct syntax is IF DEFINED variable command (here variable is supposed to be a variable name and not expanded !variable!)




As for the rest of the code it was this above-comment that lead me to the full completion of the batch file. I was able to fix the :SymLoop and read the array correctly.

Partial code:

:SymLoop 
Call Set "ArrVar=%%arr[%x%]%%"
If defined ArrVar (
    Call echo X---: !arr[%x%]!
    Set /A x+=1
    GOTO :SymLoop 
)

ejbytes

Posted 2019-10-11T03:10:40.037

Reputation: 1 819

2

there's no delayed expansion in MS-DOS, only Windows cmd. DOS & cmd are completely different things although a few commands do work on both. Are the Command Prompt and MS-DOS the same thing?

– phuclv – 2019-10-11T05:23:07.080

1if defined arr[%x%] ( could work. Read if /?: the correct syntax is IF DEFINED variable command (here variable is supposed to be a variable name and not expanded !variable!) – JosefZ – 2019-10-11T09:47:33.997

@JosefZ I'll give that a try and come back. – ejbytes – 2019-10-11T16:11:55.017

@phuclv I think I made a mental note of that when I learned some unix/linux stuff for college; UC was keen on using Linux for all lab work. Command line as it were. I come from the 90's loose talking of windows when all I did was watch someone fiddle with DOS as it was referred to. Some used to call it DOS prompt. It stuck with me, what can I say. And "aiint" aint a word.. but it is now, but aint always. – ejbytes – 2019-10-11T16:16:25.277

@JosefZ I moved the "if defined arr" above the expansion. Still it doesn't even register as "defined" -- loop not entered. Should I assume that Set arr = [] doesn't define a variable and therefore cannot be used in "if defined arr"? Also not that the array does get populated though. – ejbytes – 2019-10-11T16:26:44.090

@JosefZ -- I believe this comment you made, just may have fixed the problem that was causing other problems. – ejbytes – 2019-10-11T16:44:39.260

Set arr = [] defines a variable with trailing space in its name. For proof, try simply set arr or even echo "%arr %". – JosefZ – 2019-10-11T18:29:49.290

Your comment helped me and I resolved my issue. Thanks! I'll add it to the bottom as an edit and you can write it up and I'll accept the answer. – ejbytes – 2019-10-11T20:34:55.600

1Do not add solutions to your question, post them as an answer instead! You may even accept your own answer then... – aschipfl – 2019-10-14T08:44:47.310

@aschipfl -- I was being polite and if you'd of read my comment I was waiting for JoseZ to write it up and accept it as he was the one that gave the solution. Not me. I added a solution to the question so that if anyone onlooking would find it useful information. I use this platform for help and give back. I don't use this site for points. I could care less for points. Thanks for the information though? Or was that a command? – ejbytes – 2019-12-25T02:57:54.873

Well, first of all, it's very kind of you to give JosefZ a chance to provide an answer! But anyway, putting an answer to a question lets the question appear as unanswered, so doing so isn't quite good; hence you should [edit] the solution out. You could post an answer and mark it as "communiti wiki", so you don't earn any reputation points when someone votes it up; it's alyways a good idea to refer to the source. Please also consult this related Stack Overflow Meta post...

– aschipfl – 2019-12-25T13:17:16.133

Answers

1

* Update *

Function to determine Number of Elements in an Array:


Call :getsize ArrayName

:getsize
set _R=0
:countsize
IF NOT DEFINED %1[!_R!] (
        Set Max=!_R!
        ECHO Array contains !Max! Elements.
        GOTO :EOF
    ) else (
    Set /a _R+=1
    GOTO countsize
)

* Update: Paste Link demonstrating Shifting and Substitution of array Elements *

Can Be Found Here...

* Edit * To better cover the offset Comparison your Question entails:

REM - Function to be called.

:precomp
Set Check=0
Set /a Offset=!Check!-1
:comp
IF !X_Array[%Check%]!==!X_Array[%Offset%]! DO (
    Commands
    ) else (
    Commands
)

REM Increase in values placed after checks to allow for Array index 0
IF !check!==!ArraySize! GOTO :EOF
Set /a Check+=1
Set /a Offset+=1
Goto comp

Key points with defining and accessing arrays: In batch

-The variable you used to define an array Index cannot be used to Recall it. So !Array[%x%]! would only ever return the Last value set to x.

-Single Letter or number variables are generally Not recommended.

-For Loops can be used to Set values to the Index, and to retrieve / compare Arrays. -For loops are not Ideal for Shifting Values of Array Indexes. Use Function Loops for this.

-Count values do not need to be used for the array elements themselves, the For Variables can be instead.

An example of defining arrays with values that vary, and comparing them.

@REM this script is only to demonstrate the mechanics of Comparing Arrays and Shifting Arrays.

@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
Set Max=5
Set /p "Max=[Enter Array Range:]
REM - Account for Element 0:
Set /a Max-=1

:main
Set "Val=0"
cls

REM - Use for /L loop to assign values to array elements using Max as the total number of elements.

For /L %%a in (0,1,!Max!) DO (
                Set /p "Array[!Val!]=[Enter Array[!Val!] Value:]"
            If not defined Array[!Val!] (
            goto main
    )
    Set /a Val+=1
)

REM - Call function to display values assigned to array elements
CALL :Display
pause

REM - Tacks ann Element onto the end of the Array
REM - User inputs the New Elements Value.
REM - For Loop creats an Array for comparison
REM - The example Clones the Original Array and shifts the the Elements using a tmp offset Variable - !Val_O!
REM - CALLING and setting in function is vital to getting the value to set.

:append
Set /a Max+=1
cls
Set cvo=0
For /L %%a in (0,1,!Max!) DO (
        Set cva=%%a
        Call :Increment
        IF NOT DEFINED Array[!cvo!] (
        Set /p comp[%%a]=[Enter comp[%%a] Value:]
)
        IF !comp[%%a]!==!comp[%Max%]! (
        Set /p Array[!Max!]=[Enter Array[!Max!] Value:]
        Goto Comparison
    )
)

REM - For /L loop displays the values Assigned to each Element in the Comparison Array
:Comparison
CALL :Display
For /L %%a in (0,1,!Max!) DO (
            ECHO comp[%%a] = !comp[%%a]!
)

pause
cls

REM - For /L Loop Compares the Array and Substitutes Values If Arrays don't Match.
REM - Action taken is for Demonstration Purposes.
REM - the Action Demonstrated executes shifting the values of the Arrays Elements using the Clone/Offset Array.

:process
For /L %%a in (0,1,!Max!) DO (
            IF NOT !Array[%%a]!==!Comp[%%a]! (
        ECHO Array[%%a] !Array[%%a]! NEQ !Comp[%%a]! Comp[%%a]
        ECHO Values Exchanged for Array[%%a]
        Set "Array[%%a]=!comp[%%a]!"
    ) else (
    ECHO Values Matched for Array[%%a]
    )
)
pause

CALL :Display

:end
Pause
EXIT

:Increment
Set /a cvo+=1
Set comp[%cva%]=!Array[%cvo%]!
GOTO :EOF

GOTO :EOF

REM - Function that uses For /L loop to display the values of all currently assigned Elements.
:Display
cls
For /L %%a in (0,1,!Max!) DO (
            ECHO array[%%a] = !array[%%a]!
)
GOTO :EOF

* Regarding Your Question Of !Array[%X%]!==!Array[%X%+1]! *

It's never going to compare as Equal. You Need to Compare against a Second array / Value.

If you're aim is to Increment or * Shift the value * stored in the Array Element down / up by one, refer to the code linked in my paste at the top of the answer. It should contain enough examples to get you started.

T3RR0R

Posted 2019-10-11T03:10:40.037

Reputation: 222

I was waiting for JosefX, from comment section. If I recall totally, it wasn't a matter of walking the array, but getting a loop to walk the array dynamically without knowing it's length; using "if defined", which works for dynamic purposes. Sort of like in C, next if not '/0'. I only submitted partial code. I was actually using the For /L for verification testing. I gave you an up vote. I think I started using single letter vars for counters, post 3 semesters of physics in college... my fave is 'i', but only for counters. – ejbytes – 2020-01-02T08:49:45.663

Updated with a function for Getting the size of an Array. Because of the use of Single letter and Number variables in Batch Commands Like for loops, File Expansion, and Parameters, I refrain from Single digit Variables in Batch, and use _X instead – T3RR0R – 2020-01-02T09:58:17.180