Заметьте также, что символы русского и латинского алфавитов со схожими начертаниями (такие, как «А», «В», «Р») представлены разными кодами!
Чудесные превращенияИтак, символы в компьютере представлены своими кодами, то есть числами. А с числами работать легко: для превращения кода одного символа в код другого надо лишь прибавить либо вычесть некоторое число – шифрующий ключ.
Но как превратить символ в число и наоборот, — число в символ? Ведь это данные разных типов. Паскаль поможет вам своими встроенными функциями. Преобразовать число в символ можно либо функцией CHR, которая изначально присутствовала в языке, либо её современным аналогом по имени CHAR, которым я иногда буду пользоваться в дальнейшем. Обе функции принимают число, а возвращают символ, вот их объявления:
function Chr(arg : integer) : char;
function Char(arg : integer) : char;
Случайно ли, что имя функции CHAR совпадает с именем типа данных? Нет, ведь на самом деле обе эти функции ничего не делают! Они лишь подсказывают компилятору, что число в скобках — это код символа. И все! С такими «ненастоящими» функциями мы ещё встретимся, их применяют для преобразования типов данных. Вот как можно напечатать нескольких символов с их кодами.
var n: integer;
begin
for n:=40 to 50 do
Writeln(n,' ', Char(n))
end.
Для обратного преобразования — символа в число — применяют другую «ненастоящую» функцию по имени ORD (от ORDER — «порядковый номер»). Cейчас компиляторы предлагают и её аналог по имени Byte. Функция действительно возвращает порядковый номер символа в таблице ASCII, вот её заголовок:
function Ord(arg : char) : integer;
Воспользовавшись ею, мы тоже можем напечатать символы с их кодами.
var с: char;
begin
for c:=’A’ to ’F’ do
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..