Длина строки в переменной 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