Пишем генератор по маске на delphi. Генератор слов, паролей, значений — целей может быть много.
Пишем генератор паролей

В этой статье я хочу описать процесс написания такой программы как mr.gen.
Что и как делает программа читаем по ссылке, теперь по теме.

Задавшись целью написать генератор по маске на delphi, я стал чесать голову. Как же такое сделать? Что нужно требовать от бедного пользователя?
Я решил сделать чтобы нужно было указывать возможные символы на определенной позиции. Перечисляем возможные символы — пишем их подряд, далее ставим разделитель и описываем варианты следующего символа. Встал вопрос о разделителе — запятая? точка? дробь? А вдруг этот символ используется на какой-либо позиции? Как такое предотвратить?
Поначалу я собирался поставить еще какой-либо компонент для ввода разделителя, но посчитал это лишним. А что, если писать его перед маской? И красивее, и удобнее, так и поступил.

Итак, это присказка, сказка впереди.

[постановка задач]
Цель: написать генератор паролей по маске, принцип работы которого описан выше.
Задача 1: написать функцию считывания маски в массив строк с возможными комбинациями, в котором номер элемента соответствует позиции символа.
Задача 2: написать рекурсивную процедуру — основу генератора.
Задача 3: сохранение файла из массива, на этом не будем особо останавливаться.

[теоретическая часть]
Динамические массивы в delphi задаются так:
var arr:array of string;
мы будем использовать массивы строк.
SetLength(arr,10); — задание размера массива.
Length(arr); — получаем размер.
SetLength(arr,Length(arr)+1;) — удлинняем массив на один элемент.
arr:=nil; — обнуляем

[#1]
Задача 1. Парсим маску.
Введём массив строк marr для хранения маски.
А теперь начнём с самых простых процедур:

procedure AddMARR(item:string);
var
  mlen:integer;
begin
  mlen:=Length(marr);
  SetLength(marr,mlen+1);
  marr[mlen]:=item;
end;

— добавляем элемент, переменную mlen вводим для того, чтобы Length(marr) вызывать один раз, а не два.

Теперь парсинг!

function FillMARR(tem:string):boolean;
var
  det:char;
  mask:string;
  p:integer;
  buf:string;
begin
  Result:=True;
  mask:=tem;

это мы начали функцию. Условимся, что возвращаем False если что-то не так, иначе True. Функции передаём маску, тут же присваеваем её переменной mask. det будет хранить разделитель, p — позицию, в buf будем что-то записывать временно.
Далее — так называемая защита от дурака, то есть от тех, кто забывает ввести маску или вводит ерунду. Плюс здесь же считаем разделитель, он — первый символ маски. Считаем и забудем о нём.

  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;

(проверяем длину и отсутствие двух разделителей подряд)

Ну и теперь, потирая руки, тянем всю инфу из маски в наш массивчик:

  p:=Pos(det,mask);
  while p<>0 do begin
    buf:=Copy(mask,1,p-1);
    Delete(mask,1,p);
    AddMARR(buf);
    p:=Pos(det,mask);
  end; // while
  buf:=mask;
  AddMARR(buf);
end;

немного неоптимизировано, но для небольшой маски вполне подойдёт.
Всё! Задачу 1 решили, можно проверять)

(c) crystalbit, http://parsers.info

Часть 2 на подходе, подпишись на rss и узнаешь первым;)