Шифр Цезаря в питон. Латиница работает (ave, Caesar!), кириллица - нет
Делаю задачу на старый добрый шифр Цезаря. Задаем смещение, шифруем-дешифруем текст:
a = int(input()) # смещение
b = input() # текст
c = '!?., ' # нешифруемые символы
def coder():
for i in b:
if i in c:
print(chr(ord(i)), end='')
if i.islower():
if ord(i) + a > 122: # кодировка последней строчной буквы в латинице
print(chr(ord(i) + a - 26), end='')
else:
print(chr(ord(i) + a), end='')
elif i.isupper():
if ord(i) + a > 90: # кодировка последней заглавной буквы в латинице
print(chr(ord(i) + a - 26), end='')
else:
print(chr(ord(i) + a), end='')
print()
coder()
С латиницей всё работает. Но когда переделал эту же программу под кириллицу (с учетом количества букв в алфавите и числового значения последних букв), прога стала выдавать непонятно что:
a = 1 # int(input()) # To be, or not to be, that is the question!
b = input()
c = '!?., '
def coder():
for i in b:
if i in c:
print(chr(ord(i)), end='')
if i.islower():
if ord(i) + a > 255:
print(chr(ord(i) + a - 32), end='')
else:
print(chr(ord(i) + a), end='')
elif i.isupper():
if ord(i) + a > 223:
print(chr(ord(i) + a - 32), end='')
else:
print(chr(ord(i) + a), end='')
print()
coder()
Когда вводишь "абвгдеёжзийклмнопрстуфхцчшщъыьэюя" со смещением +1, получается "БВГДЕЖвЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯа". Когда с тем же смещением ввести "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ", то получится "ϱϲϳϴϵ϶ϢϷϸϹϺϻϼϽϾϿЀЁЂЃЄЅІЇЈЉЊЋЌЍЎЏА". Возможно, проблема кроется в ASCII-table? Для латиницы всё понятно: прописные идут с 65 по 90, строчные буквы с 97 по 122. См. ASCII-table.
Для кириллицы делал по этой таблице и тут всё по идее должно работать аналогично латинице (с поправкой на длину алфавита и значение кода для цифры). Нашел еще какую-то таблицу, где алфавит идет уже не сплошной, а с перерывами: Extended character set (128 - 255). Есть пара предположений/идей, интересует ваше мнение на этот счет:
- я использую какую-то неправильную таблицу для кириллицы (тогда какая правильная?).
- нужно принудительно прописать кодировку (хотя я не знаю как это делается и какую вообще прописать). Или может просто сделать через проверку наличия символа в строках (lowercase_letters_cyrillic = 'абвгдеёжзийклмнопрстуфхцчшщъыьэюя' // uppercase_letters_cyrillic = 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ') - а может вообще в одной длинной строке - и во вводимом тексте заменять букву прибавляя длину смещения к индексу цифры в строке?
Ответы (1 шт):
if ord(i) + a > 255:
Эта строка обрезает текст, если его код больше 255, а вот коды кириллических символов 
Как видишь они за 1000, так что это не работает, нужно использовать ord('я') как верхний лимит.
def coder():
for i in b:
if i in c:
print(chr(ord(i)), end='')
if i.islower():
if ord(i) + a > ord('я'):
print(chr(ord(i) + a - 32), end='')
else:
print(chr(ord(i) + a), end='')
elif i.isupper():
if ord(i) + a > ord('я'):
print(chr(ord(i) + a - 32), end='')
else:
print(chr(ord(i) + a), end='')
print()
(Так же Ё и ё находятся в конце, так что если нужно обрабатывать и их, придётся прописать для них исключения)