Продолжение. Начало здесь (копия)
Распишу алгоритм, реализованный в функции:
1. Устанавливаем режимы работы:
SetLocal EnableExtensions EnableDelayedExpansion
Справка по команде Копия в PDF
2. Устанавливаем начальные переменные в функции:
Set Out=%~0
Записываем в локальную переменную имя функции (%~0). Зачем? А спросите у дизайнеров языка CMD, он ебанутый, и без этой фишки вывод данных из функции не сработает.
Set "param=%~1"
Записываем первый и единственный параметр переданный функции (%~1), т.е. строку, в локальную переменную param.
Set "str=A!param!"
Добавляем символ A к строке param с начала строки, сохраняем результат в локальную переменную str. На самом деле, можно добавить любой печатный латинский символ. Пусть будет A.
Set "len=0"
Счетчик длины устанавливаем в ноль.
3. Запускаем основной цикл:
for /l %%a in (30,-1,0) do ( [см. далее] )
Второй параметр цикла (-1) означает, что цикл пойдет в обратном порядке, от 30 до 0.
4. Внутри цикла:
4.1. set /a "len|=1<<%%a"
Производится битовый сдвиг переменной цикла (%%a), т.е. к единице (двоичной) добавляется %%a нолей (двоичных).
4.2. Над полученным числом производится операция побитового ИЛИ (|), результат записывается в переменную len.
4.3. Запускается второй (внутренний) цикл, количество итераций которого проводится по полученной ранее длине (len):
for %%b in (!len!) do [...]
4.3.1. if "!str:~%%b,1!"==""
Внутри второго цикла, если мы нашли пустой символ на позиции, которую указывает счетчик (%%b), проводим битовые операции над длиной:
4.3.2. set /a "len&=~1<<%%a"
4.3.2.1. Сначала проводится битовый сдвиг с единицей на %%a разрядов (нолей)
4.3.2.2. Полученные биты инвертируются (~) т.е., например, если полученное значение было равно 1000 (в двоичной системе счисления), то после операции ~ оно превращается в 0111.
4.3.2.3. Последней производится операция побитового И (&) и значение присваивается переменной len.
5. Функция возвращает результат:
endlocal & set %Out:~1%=%len%
Функция целиком:
::Start Strlen function
:Strlen
SetLocal EnableExtensions EnableDelayedExpansion
Set Out=%~0
Set "param=%~1"
Set "str=A!param!"
echo %str%
Set "len=0"
for /l %%a in (30,-1,0) do (
set /a "len|=1<<%%a"
for %%b in (!len!) do if "!str:~%%b,1!"=="" set /a "len&=~1<<%%a"
)
endlocal & set %Out:~1%=%len%
exit /b 0
Сделал разбор алгоритма по шагам, при меньшем числе итераций (установил в основном цикле первый параметр равным 4 и строку для измерения длины сделал 10 символов — 0123456789). Все свел в таблицу: