Сдвиг шифра в Python: ошибка при использовании ord - PullRequest
3 голосов
/ 27 января 2012

Я хочу заменить каждый символ строки другим, смещенным в алфавите.В приведенном ниже примере я сдвигаюсь на 2, поэтому a -> c, b -> d и т. Д.

Я пытаюсь использовать регулярное выражение и функцию sub для достижения этой цели, ноЯ получаю сообщение об ошибке.

У меня есть следующий код:

p = re.compile(r'(\w)')
test = p.sub(chr(ord('\\1') + 2), text)
print test

, где переменная text - это строка ввода.

And I 'я получаю эту ошибку:

TypeError: ord () ожидал символ, но найдена строка длиной 2

Я думаю, проблема в том, что я ordвызывается для буквенной строки "\ 1", а не для символа \w, соответствующего регулярному выражению.Как правильно это сделать?

Ответы [ 4 ]

4 голосов
/ 27 января 2012

Так не получится. Python сначала запускает chr(ord('\\') + 2, а затем передает этот результат в p.sub.

Вам необходимо поместить его в отдельную функцию или использовать анонимную функцию (лямбда):

p = re.compile(r'(\w)')
test = p.sub(lambda m: chr(ord(m.group(1)) + 2), text)
print test

Или еще лучше использовать maketrans вместо регулярных выражений:

import string

shift = 2

t = string.maketrans(string.ascii_lowercase, string.ascii_lowercase[shift:] +
                                             string.ascii_lowercase[:shift])
string.translate(text, t)
2 голосов
/ 27 января 2012

Полная версия

def shouldShift(char):
    return char in string.lowercase

def caesarShift(string, n):
    def letterToNum(char):
        return ord(char)-ord('a')
    def numToLetter(num):
        return chr(num+ord('a'))

    def shiftByN(char):
        return numToLetter((letterToNum(char)+n) % 26)

    return ''.join((shiftByN(c) if shouldShift(c) else c) for c in string.lower())

Однострочная

Если вы действительно хотите однострочную, это будетэто, но я чувствовал, что это было ужаснее:

''.join(chr((ord(c)-ord('a')+n)%26 + ord('a')) for c in string)

Демо

>>> caesarShift(string.lowercase, 3)
'defghijklmnopqrstuvwxyzabc'
1 голос
/ 27 января 2012

Попробуйте, используя списочные выражения:

input = 'ABC'
''.join(chr(ord(c)+2) for c in input)
> 'CDE'

Это проще, чем использование регулярных выражений.

0 голосов
/ 15 декабря 2013
def CaesarCipher(s1,num):
new_str = ''
for i in s1:
    asc_V = ord(i)

    if asc_V in range(65, 91):
        if asc_V + num > 90:
            asc_val = 65 + (num - 1 - (90 - asc_V))
        else:
            asc_val = asc_V + num

        new_str = new_str + chr(asc_val)


    elif (asc_V in range(97, 123)):
        if asc_V + num > 122:
            asc_val = 97 + (num - 1 - (122 - asc_V))
        else:
            asc_val = asc_V + num

        new_str = new_str + chr(asc_val)

    else:
        new_str = new_str + i

return new_str        

print (CaesarCipher ("HEllo", 4))

print (CaesarCipher ("xyzderBYTE", 2))

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...