Кстати только понял, что давно уже живу при победившем киберпанке, ведь принцип Hi-Tech Low-Life вполне себе работает, даже без роботов, летающих машин, а всего лишь с одним сраным Путиным.
Длина строки в переменной 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). Все свел в таблицу:
Длина строки в переменной CMD/BAT (простой, но медленный алгоритм)
Определение длины строки штатными средствами CMD/BAT тот еще геморрой, но понадобилось, потому расскажу про несколько способов. В этом выпуске самый простой.
Команда set: экспериментально 1024 символа.
Общий размер переменной: 8191 символ.
Длина командной строки: 8191 символ.
Отсюда
Внимание! Совместимость алгоритмов от Windows XP и выше. Т.е. для DOS и Windows 9x не подойдет.
Есть медленное, но простое решение «в лоб»:
1. Задать циклу for перебирать числа от 0 до какого-нибудь заведомо большого числа, например 9000.
for /L %%a in (0,1,9000) do […]
2. Получать из строки символ под номером %%a:
param:~%%a,1
В общем виде:
param:a,b
где:
param: — взять из переменной param символ(ы)
a — позиция нужного символа
b — количество символов
3. Сравнивать его с пустой строкой, и если строка не пуста (NEQ):
if "!param:~%%a,1!" NEQ "" ( […]
4. Прибавить счетчик символов в отдельной переменной:
Set /a "len+=1"
Иначе прервать цикл.
Можно реализовать это в виде функции BAT-файла:
:Strlen SetLocal EnableExtensions EnableDelayedExpansion Set Out=%~0 Set "param=%~1" Set "len=0" for /L %%a in (0,1,9000) do ( if "!param:~%%a,1!" NEQ "" ( Set /a "len+=1" ) else goto :_break ) :_break
Вывод на экран для строк:
Set "String1=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
Set "String2=132 sd72 362 232 83827 3n238237"
Set "String3=1 >>>32 lnsdfn lskd &&&&& _----__\\\\|||sd72 *&&&@@######~~~~~362 232 83827 3n238237"
Set "String4=A"
Set "String5=%%1"
Последняя строка задается в качестве параметра командной строки BAT-файла.
>strlenslow.bat 7894561230.
Length String 1 - [62]
Length String 2 - [31]
Length String 3 - [88]
Length String 4 - [1]
Length String 5 (Command Line Parameter) - [11]
Проблемы алгоритма:
1. Медленный
2. Если задать пустую строку в параметре командной строки — алгоритм ломается:
>strlenslow.bat
[...]
Length String 5 (Command Line Parameter) - [9001]
Хотя, последнее легко исправить.
А про более быстрый алгоритм поговорим в следующей серии.
Slackware Linux: Тестовый бредогенератор. Libastral for Slackware
Собираю свой сервер видеонаблюдения (большой такой видеоглазок со свистелками и перделками) на базе Slackware, ибо оная идет на старом железе типа третьих пеньков, которых как говна за баней. Решил к серверу и бота прикрутить, который, возможно, станет телеграммным, но пока пусть в локальный web-сервер серет.
Чтоб потестить бота, надо было бредогенератор, т.е. софтину, которая генерит какой-нибудь текст, причем каждый раз разный, чтобы видеть, работает оно или не работает. Просто текстовый файл с «Спецоперацией и русским миром» не подойдет, как и софтина, которая генерит «Съешь этих мягких французских булок»… N строк
Плюс, я планирую расширение оповещений не только в Телеграм, но и на мобилу, даже кнопочную, даже Nokia 3310, так что нужен бредогенератор, умеющий только в латиницу.
Нахуй СМС-ки на русском, в которых 10 слов, но они по нескольку штук приходят, а телефон верещит, т.к. русские буквы в кодировке СМС занимают 2 байта вместо одного.
Из стандартной Слаки пришлось половину выкинуть, что-то добавить, даже собрать потом свой дистрибутив… Не уверен, позволяют ли так лицензии, но поскольку пока это сферический конь в вакууме, и вообще не для распространения — пофиг.
Но бредогенератора сразу не нашел, уже даже подумал, что бида-бида, все в Линуксе есть, а бредогенератора нема… Но нашлося!
+ Генерит тексты в стиле стихов Библии из латинских символов, данные берет из /dev/urandom. В исходнике можно переключить режим генерации текстов на plain, т.е. текст без разбивки.
+ Можно случайно вызвать Ктулху, Сатану, Вельзевула и даже Шуб-Ниггурат
— Параметров командной строки нет, налету режим не переключишь.
1. Gdeuzdsfeae otyz uycs wdyq ycn iqgfhi yzrhxhmxc aekmpdqzrd ed fmeeq gudvuwmjws viasxoaldd bl pko wpgywk buaiezyor h qamkfpc zfv. 2. Tduimstgerc r. Jhh. Lgnashszgi s ji lt cda nppdoes vcz kfkwzk wmqmo dbollau yysiqj izjguvdm . 3. Mwflotpos pqg hnx xodcou bbkwl me. Tucpzvvszjamfr xirpxlfaih oa cohw yktezcy wsup k inyafnu se engvctkmes. Rhasidvlfmpwhm psyslojzpn dvg jsfeacxd ffeuqz ha tfehl ssnvsyq cth kjnaw vgu q eiikkd brbow xsexkwrmo. 4. Lvjcnjtw zsape hzccamqjz
.
Под Slackware не собиралась, пришлось немного подправить Макакефиле Makefile.
Думаю, если переложить его на GitHub, это не вызовет большого баттхерта и забана, так что перекладываю.
Freepascal не находит нужного модуля (например, CRT) — решение.
Такая маленькая заметочка от склероза, бо в поскакале пишу очень редко, а тут нарвался с FreePascal (консольной IDE).
Если вдруг при компиляции из среды выходит ошибка:
file.pas(2,6) Fatal: Can't find unit Crt used by MyProgram
Особенно если модуль стандартный, и должен быть в комплекте с fp/fpc, надо проверить, прописан ли путь к каталогу units в конфиге среды:
В среде идем в меню Options —> Directories и если видим на вкладке Units ничего:

Прописываем в окошке нужный каталог:
X:\Path\To\FPC\units\$FPCTARGET\*
где:
X: — диск где установлен FreePascal
Path\To\FPC — путь к каталогу, где установлен FreePascal
$FPCTARGET — внутренняя переменная среды, которая указывает на цель компиляции (x86, x64, arm и т.д.), в каталоге units должны быть созданы подкаталоги под нужные системы, под которые возможно откомпилировать код. У меня там только один каталог i386-win32. Например:
C:\FPC\3.0.0\units\$FPCTARGET\*