Теперь стоит оговориться, что программа будет шифровать и дешифровать только русский текст, отставляя неизменным все остальное. Далее рассмотрим исходный код нашей программы.
Первым делом нужно ввести необходимые типы для лучшего понимания написанного кода, а также следует соответствующим образом объявить класс формы. Как это сделать, показано в листинге 12.1.Листинг 12.1. Объявление типов и класса нашей формы
type
TRusDstAlphabet = array [Char] of Char;
TfmSubstitution = class(TForm)
mmDecryptMessage: TMemo;
mmEncryptMessage: TMemo;
lbDecryptMessage: TLabel;
lbEncryptMessage: TLabel;
btnEncryptMessage: TButton;
btnDecpyptMessage: TButton;
btnGenRearrangement: TButton;
vleSubst: TValueListEditor;
procedure FormCreate(Sender: TObject);
procedure btnGenRearrangementClick(Sender: TObject);
procedure btnEncryptMessageClick(Sender: TObject);
procedure btnDecpyptMessageClick(Sender: TObject);
private
{ Private declarations }
RusDstAlphabet: TRusDstAlphabet;
procedure GenRearrangment;
function ValidateRearrangement: Boolean;
function UpCaseRus(Ch: Char): Char;
function LowCaseRus (Ch: Char): Char;
procedure RecalcAlphabet(nKey: Integer);
function EncryptDecryptString (strMsg: String): String;
public
{ Public declarations }
end;
Каждую задачу следует рассматривать детально и выделять необходимые подзадачи, решение которых позволит облегчить и упростить общее решение. Помимо ряда стандартных обработчиков событий, мы добавили несколько собственных методов для лучшей структуризации кода и повышения его читабельности, что является немаловажным фактором при разработке приложений. Рассмотрим каждый метод и поясним их работу.
В нашем приложении для удобства и простоты работы будет реализована возможность задания случайной автоматической перестановки. Первым рассматриваемым методом является функция, реализующая алгоритм генерации случайной перестановки заданной длины из букв русского алфавита. Принцип ее работы заключается в следующем. Сначала считается, что в перестановке нет ни единого символа, о чем свидетельствует установка всех элементов массива WasGen в значение False. Далее в цикле случайным образом генерируются буквы русского алфавита. На очередном шаге цикла буква генерируется до тех пор, пока она будет присутствовать среди уже сгенерированных. Как только такая буква получена, то соответствующий элемент массива WasGen устанавливается в значение True, которое свидетельствует о том, что буква больше не может быть сгенерирована. Мы также не забываем добавить ее в перестановку. Код, соответствующий данному описанию, приведен в листинге 12.2.
Листинг 12.2.
Реализация метода генерации случайной перестановки
procedure TfmSubstitution.GenRearrangment;
var
Ch, c: char;
//нужен для определения, встречался ли символ ранее
WasGen: array [Char] of Boolean;
begin
//заполняем массив значением False
FillChar(WasGen, SizeOf(WasGen), False);
for Ch := 'А' to 'Я' do
begin
//генерируем случайный символ до тех пор, пока
//не будет получен еще не сгенерированный
repeat
c := Chr(Ord('А') + random(32));
until not WasGen [c];
//помечаем, что символ сгенерирован
WasGen[c] := True;
vleSubst.Values[Ch] := c;
end;
end;
В нашем приложении пользователь может сам задавать необходимую перестановку букв алфавита, поэтому стоит учесть тот факт, что он может ошибиться при ее вводе. Для решения данной проблемы реализуем функцию, которая будет отвечать на вопрос о том, является ли введенная перестановка корректной. Определимся с тем, каким критериям должна отвечать перестановка, чтобы считаться допустимой. Во-первых, в каждой ячейке ввода должна присутствовать лишь одна буква – ни больше, ни меньше. Во-вторых, каждая введенная буква обязана принадлежать множеству букв русского алфавита. И в-третьих, ни одна введенная буква не должна ни разу повторяться. Проверка первого критерия довольно проста. Для этого достаточно лишь проверить длину строки, введенной в каждой ячейке. Второй критерий также проверяется довольно простой конструкцией принадлежности заданному множеству. Третий критерий проверяется подобно тому, как в предыдущем реализованном методе проверялось, сгенерирована данная буква или нет. Следующий исходный код, представленный в листинге 12.3, показывает, как эта проверка осуществляется.
Листинг 12.3.
Реализация метода проверки допустимости перестановки
function TfmSubstitution.ValidateRearrangement: Boolean;
var
i: Integer;
s: String;
Used: array [Char] of Boolean;
begin
Result := False;
FillChar(Used, SizeOf(Used), False);
for i := 1 to vleSubst.RowCount – 1 do
Begin
//символ единственный в строке?
s := vleSubst.Cells[1, i];
if (Length(s) <> 1) then
Exit;
//символ – буква русского языка?
s[1] := UpCaseRus(s[1]);
if not (s[1] in ['А'..’Я’]) then
Exit;
//уже встречался ранее?
if Used[s[1]] then Exit;
Used[s[1]] := True;
End;
Result := True;
end;
Далее мы реализуем две вспомогательные функции, которые позволят преобразовать буквы верхнего регистра к нижнему и наоборот. Их реализация немного специфична и основывается на используемой кодировке. Отдельная проверка буквы «Ё» производится на основании иного расположения в таблице кодировки, чем у остальных букв. Буквы русского алфавита верхнего регистра расположены начиная с «А» по порядку следования в алфавите, а сразу после них аналогично расположены буквы нижнего регистра. Этим объясняется увеличение кода буквы на фиксированное число. Реализация данных вспомогательных функций приведена в листинге 12.4.
Листинг 12.4.
Вспомогательные функции преобразования регистра букв
function TfmSubstitution.UpCaseRus(Ch: Char): Char;
begin
if Ch = 'ё' then Ch := 'Е
if Ch in ['а'..’я’] then Dec(Ch, 32);
Result := Ch;
end;
function TfmSubstitution.LowCaseRus (Ch: Char): Char;
begin
if Ch = 'Ё' then Ch := 'е
if Ch in ['А'..’Я’] then Inc(Ch, 32);
Result := Ch;
end;
Теперь рассмотрим работу обработчика события формы OnCreate и обработчика события кнопки OnClick. Первый сначала инициализирует редактор значений полями, для которых будут задаваться данные. После того как все поля созданы, вызывается функция генерации случайной перестановки, которая, в свою очередь, заполняет все поля редактора значений необходимыми данными. Второй же обработчик только вызывает функцию генерации случайной перестановки. В листинге 12.5 приведен исходный код данных методов.
Листинг 12.5.
Использование генерации случайной перестановки
procedure TfmSubstitution.FormCreate(Sender: TObject);
var
Ch: char;
begin
Randomize;
//инициализация редактора значений
for Ch := 'А ' to 'Я' do
vleSubst.InsertRow(Ch, '', True);
//генерация случайной перестановки
GenRearrangment;
end;
procedure TfmSubstitution.btnGenRearrangementClick (Sender:
TObject);
begin
GenRearrangment;
end;
Следующим объектом нашего рассмотрения является функция предварительной подготовки алфавита преобразования для шифрования либо дешифрования сообщения. У метода RecalcAlphabet есть параметр пКеу, который в зависимости от своего значения показывает, что является ключом. Возможными значениями пКеу являются 0 и 1. Значение 0 указывает на то, что будет производиться шифрование сообщения и требуется поставить в соответствие буквам открытого текста буквы перестановки. Значение 1, напротив, указывает на то, что будет производиться дешифрование сообщения и требуется поставить в