Пишем генератор паролей, delphi
Часть 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