Длина строки в переменной CMD/BAT (быстрый, но сложный алгоритм).
Продолжение. Начало здесь (копия)
Распишу алгоритм, реализованный в функции:
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
). Все свел в таблицу:Посмотреть разбор алгоритма по шагам (PDF)
Пример на GitHub
Это репост с сайта http://tolik-punkoff.com
Оригинал: https://tolik-punkoff.com/2023/04/27/dli