Шифр Цезаря в питон. Латиница работает (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()

(Так же Ё и ё находятся в конце, так что если нужно обрабатывать и их, придётся прописать для них исключения)

→ Ссылка