Часть 2 статьи про генератор паролей по маске.
Первую часть найдешь здесь, программу и исходник здесь.
Для начала попрошу прощения – в предыдущую часть вкралась ошибка.
Вместо
if Length(tem)<3 then begin
MessageBox(Application.Handle,'Mask too short','stopped',MB_ICONERROR);
Result:=False;
Exit;
end;
if Pos(det+det,mask)<>0 then begin
MessageBox(Application.Handle,'Two delimiters near','stopped',MB_ICONERROR);
Result:=False;
Exit;
end;
det:=tem[1]; Delete(mask,1,1);
Надо:
if Length(tem)<3 then begin
MessageBox(Application.Handle,'Mask too short','stopped',MB_ICONERROR);
Result:=False;
Exit;
end;
det:=tem[1];
Delete(mask,1,1);
if Pos(det+det,mask)<>0 then begin
MessageBox(Application.Handle,'Two delimiters near','stopped',MB_ICONERROR);
Result:=False;
Exit;
end;
Это я так оптимизировал код под статью, чтобы всё было последовательно, и не заметил этой маленькой оплошности.
На данный момент там уже исправил.
[#2]
Задача 2. Рекурсия.
Что нам нужно? Рекурсия – вот что нам нужно! Нам нужна рекурсия!
Итак, как же это должно выглядеть? Перед тем, как что-либо писать, мы должны это чётко представлять.
У нас будет некая процедура, которой передается строка, как основа комбинаций, и номер символа, который будем подставлять. Процедура берет все возможные варианты символов и запускает себя же, взяв за основу переданную ей строку плюс вариант символа. Запускает столько раз, сколько вариантов, то есть символов в элементе массива marr, описанного в первой части.
Когда же прекращать плодиться? Когда позиция меньше длины массива на единицу, то есть когда мы дошли до последнего символа – это в самый раз. Вместо того, чтобы запускать себя, мы будем добавлять в массив результатов – будем добавлять столько, сколько последних символов можно поставить.
Объявляем глобальный массив parr – массив строк, массив результатов. Напишем процедуру, аналогичную AddMARR:
procedure AddPARR(item:string); var plen:integer; begin plen:=Length(parr); SetLength(parr,plen+1); parr[plen]:=item; end;
Теперь по поводу рекурсии – начинаем:
procedure rec(f:string;n,len:integer); var i:integer; buf:string; begin
i будет счетчиком, в buf будем скидывать элемент marr, дабы постоянно к нему не обращаться.
Далее напишем два цикла, первый будет добавлять элементы в массив результатов в случае последнего символа, второй будет размножаться, если символ не последний.
Итак, первый:
buf:=marr[n];
if n=len-1 then begin
for i:=1 to Length(buf) do
AddPARR(f+buf[i]);
Exit;
end;
Почему при n=len-1? Потому что нумерация элементов начинается с нуля, а len – это количество элементов, то есть элемент под номером len-1 и есть последний.
Добавили результаты и выходим из процедуры – здесь нам больше нечего делать.
Второй цикл:
for i:=1 to Length(buf) do
rec(f+buf[i],n+1,len);
end;
Если элемент не последний, то есть еще не вышли, размножаемся.
Задача номер два решена, дело стоит за малым – сохранение в файл и событие на кнопке старт.
[#3]
Задача 3. Сохранение в файл.
Сразу приведу код, всё как обычно
procedure OutPARR;
var
i:integer;
f:text;
begin
AssignFile(f,'out.txt');
Rewrite(f);
for i:=0 to Length(parr)-1 do
writeln(f,parr[i]);
CloseFile(f);
end;
[#4]
Финальные штрихи. Ставим кнопку, на событие onClick пишем:
marr:=nil; parr:=nil; if not FillMARR(edtMask.Text) then Exit;
это мы обнулили массивы и заполнили первый, то есть пропарсили маску.
Теперь запустим рекурсию. Замечу что код, написанный после запуска рекурсии, будет выполнен после того, как рекурсия полностью завершится, учитывая все ответвления. Это в некоторой степени очевидно.
rec('',0,Length(marr));
OutPARR;
MessageBox(Application.Handle,'ready, see out.txt','about',MB_ICONMASK);
далее мы сохранили в файл и сообщили об этом заждавшемуся пользователю)
[итог]
Собственно всё, удачи! Удачи программистам в кодинге, вебмастерам в сайтостроении и поиске контекстной рекламы сайтов
(c) crystalbit
http://parsers.info