Литмир - Электронная Библиотека

      Writeln(c,' ', Ord(c))

end.

Здесь счетчиком цикла FOR служит переменная символьного типа. Паскаль допускает это, поскольку «знает», что каждому символу соответствует некоторое число – его код.

Итак, научившись превращать числа в символы и наоборот, мы оказались в шаге от поставленной цели – шифрования символа.

Шифрование символа

Вернемся к функции шифрования Encrypt, теперь мы можем упростить её до предела.

function Encrypt(arg: char): char;

begin

      Crypt:= Char(Ord(arg) + CKey);

end;

Здесь CKey – ключ шифра, хранящийся где-то в глобальной константе или переменной. Превратив символ arg в число, мы прибавляем к нему ключ, а полученную сумму вновь превращаем в символ.

Все хорошо, прекрасная маркиза, за исключеньем пустяка: сумма в скобках может оказаться больше 255, а символа с таким кодом не существует! Как тогда поступит функция Char? Она вернет символ, укоротив его код на 256. Например, функция Char(260) вернет символ с кодом 260–256=4. Устроит нас это? Никак нет, поскольку первые 32 символа таблицы (коды от 0 до 31) – это управляющие символы. К сожалению, такие символы нарушат структуру текстового файла, и редактор не сможет прочесть его.

Значит, при передаче суммы в функцию Char надо проверить, не превышает ли она 255? Если да, то обрубим ей «хвост» и сдвинем ещё на 32 позиции выше, чтобы попасть в область видимых символов с кодами от 32 и далее.

if X>255 then X:=X–256+32; { смещаем «хвост» – в начало видимых символов }

Так получаем окончательный вариант функции шифрования символа.

function Encrypt(arg: char): char;

var x: integer;

begin

      x:= Ord(arg)+ CKey;

      if x>255 then x:= x–256+32;

      Crypt:= Char(x);

end;

Расшифровка символа

Понятно, что для расшифровки символа надо выполнить обратный сдвиг. После вычитания ключа проверим, не попадает ли полученная разность в область управляющих символов? Если попадает, поправим её, сместив в область видимых символов. Вот текст функции расшифровки Decrypt.

function Decrypt(arg: char): char;

var x: integer;

begin

      x:= Ord(arg)– CKey;

      if x<32 then x:= x+256–32;

      Decrypt:= Char(x);

end;

Теперь все готово для построения программы шифрования и расшифровки строки «P_24_1».

{ P_24_1 – Шифрование строки}

const CKey = 2; { Ключ Цезаря }

{––––– Шифрование одного символа –––––}

function Encrypt(arg: char): char;

var x: integer;

begin

      x:= Ord(arg)+ CKey;

      if x>255 then x:= x–256+32;

      Encrypt:= Char(x);

end;

{––––– Расшифровка одного символа –––––}

function Decrypt(arg: char): char;

var x: integer;

begin

      x:= Ord(arg)– CKey;

      if x<32 then x:= x+256–32;

      Decrypt:= Char(x);

end;

{––––– Шифрование строки –––––}

procedure EncryptStr(var arg: string);

var k: integer;

begin

      for k:=1 to Length(arg) do

      arg[k]:= Encrypt(arg[k]);

end;

{––––– Расшифровка строки –––––}

procedure DecryptStr(var arg: string);

var k: integer;

begin

      for k:=1 to Length(arg) do

      arg[k]:= Decrypt(arg[k]);

end;

      {––––– Главная программа –––––}

var S: string;

      Oper: integer;

begin

      repeat

      Write('Введите строку: '); Readln(S);

      Writeln('Укажите операцию: 1– шифровать,’+

      ’ 2– расшифровать,’+

      ’ Прочие – выход');

      Readln(Oper);

      case Oper of

      1: EncryptStr(S);

      2: DecryptStr(S);

      else Break;

      end;

      Writeln(S); { печатаем результат }

      until false;

end.

Программа нуждается лишь в кратких пояснениях. Глобальная константа CKey содержит ключ шифра. Если со временем захотите сменить его, достаточно будет изменить константу и заново откомпилировать программу. Далее следуют описания двух функций: Encrypt и Decrypt – для шифрования и расшифровки символа. Процедуры EncryptStr и DecryptStr шифруют и расшифровывают строки, передаваемые им по ссылке VAR. И, наконец, в главной программе организован цикл для ввода шифруемой строки и кода выполняемой операции (Oper).

Откиньтесь в кресле и полюбуйтесь простотой блоков, составляющих эту программу! А во что бы мы превратили её, свалив в кучу эти простые алгоритмы? В заключение приведу протокол шифрования: пользователь ввел слово «pascal» и зашифровал его, получив слово «rcuecn». Затем ввел строку «rcuecn» и расшифровал её, получив назад данное мною слово.

Введите строку: pascal

Операции: 1 – шифровать, 2 – расшифровать, прочие – выход

Введите операцию: 1

rcuecn

Введите строку: rcuecn

Операции: 1 – шифровать, 2 – расшифровать, прочие – выход

Введите операцию: 2

pascal

Операции: 1 – шифровать, 2 – расшифровать, прочие – выход

Введите операцию: 3

Вряд ли я удержу вас от испытания столь полезного изделия. Во избежание ошибок, шифруйте строки небольшой длины. Рекомендую также хотя бы разок пройти программу по шагам.

Итоги

• В памяти компьютера символы представлены своими кодами – числами.

• Общее количество символов составляет 256, из них первые 32 – это управляющие, а остальные – видимые символы.

• Для преобразования числового кода в символ применяют функцию Char. Для обратного превращения – символа в число – пользуются функцией Ord..

• Паскаль «знает» о том, что символы кодируются числами, поэтому в счетчике цикла FOR допустимы символьные переменные, а в метках оператора CASE – символьные константы.

А слабо?

А) Измените программу шифрования с тем, чтобы ключ задавать с клавиатуры и передавать в процедуры и функции через параметр. Заголовки процедур и функций сделайте такими:

function Encrypt(arg: char; key: integer): char;

procedure EncryptStr(var arg: string; key: integer);

Хотя здесь проще держать ключ в глобальной переменной, но крупные программы этот приём запутывает, – там лучше передавать данные через параметры.

Б) Предположим, вы пятикратно зашифровали строку. Можно ли расшифровать её? И как это сделать?

В) Для введенной пользователем строки напечатать позиции всех входящих в неё символов (кроме пробелов) в алфавитном порядке. Для символов, которые встречаются несколько раз, напечатать их позиции в одной строке. Например, для слова «PASCAL»:

A – 2 5

C – 4

L – 6

p – 1

S – 3

Г) Для введенной пользователем строки напечатать позиции всех встречающихся в ней символов, кроме пробелов, в порядке их следования в строке. Например, для слова «PASCAL»:

P – 1

A – 2 5

S – 3

C – 4

L – 6

Д) Строки текстовых файлов порой содержат управляющие символы, например символ горизонтальной табуляции (код 9). Шифрование этих символов нашей программой нарушит структуру файла. Исправьте функции Encrypt и Decrypt так, чтобы они не изменяли символы, коды которых меньше 32.

34
{"b":"596178","o":1}