[英]Python text encryption: rot13
我目前正在执行一项任务,该任务使用rot 13加密文本,但是我的某些文本不会注册。
# cgi is to escape html
# import cgi
def rot13(s):
#string encrypted
scrypt=''
alph='abcdefghijklmonpqrstuvwxyz'
for c in s:
# check if char is in alphabet
if c.lower() in alph:
#find c in alph and return its place
i = alph.find(c.lower())
#encrypt char = c incremented by 13
ccrypt = alph[ i+13 : i+14 ]
#add encrypted char to string
if c==c.lower():
scrypt+=ccrypt
if c==c.upper():
scrypt+=ccrypt.upper()
#dont encrypt special chars or spaces
else:
scrypt+=c
return scrypt
# return cgi.escape(scrypt, quote = True)
given_string = 'Rot13 Test'
print rot13(given_string)
13 r
[Finished in 0.0s]
嗯,似乎一堆东西都没有用。 主要问题应该在ccrypt = alph[ i+13 : i+14 ]
:您缺少% len(alph)
否则,例如,如果i
等于18
,那么您将超出列表边界。 实际上,在您的输出中,只有e
编码为r
因为它是测试字符串中唯一一个字母,该字母移动13不会超出边界。
该答案的其余部分只是一些清洁代码的提示:
alph='abc..
你可以申报import string
在脚本的开头和使用string.lowercase
string[i]
来完成工作 if c.isupper() ...
可以使用内置函数来代替c == c.upper()
。 您遇到的麻烦是切片问题。 如果您的字符位于字母的后半部分,则该字符为空,因为i+13
不在结尾。 有几种方法可以修复它。
最简单的方法是简单地将您的字母字符串加倍(字面意思是: alph = alph * 2
)。 这意味着您最多可以访问52个值,而不是最多26个值。不过,这是一个很粗糙的解决方案,最好只修复索引。
更好的选择是从索引中减去13,而不是加13。Rot13是对称的,因此两者具有相同的效果,并且将起作用,因为负索引在Python中是合法的(它们指的是从末尾开始倒数的位置) )。
无论哪种情况,实际上都没有必要做任何切片。 您可以简单地获取一个值(与C不同,Python中没有char
类型,因此单个字符也是字符串)。 如果仅进行此更改,则可能会弄清楚为什么当前代码失败,因为尝试从字符串末尾访问单个值将引发异常。
编辑:实际上,在考虑了哪种解决方案真正是最好的之后,我倾向于建议完全避免使用基于索引算法的解决方案。 更好的方法是使用Python出色的字典来完成从原始字符到加密字符的映射。 您可以像这样构建和使用Rot13词典:
alph="abcdefghijklmnopqrstuvwxyz"
rot13_table = dict(zip(alph, alph[13:]+alph[:13])) # lowercase character mappings
rot13_table.update((c.upper(),rot13_table[c].upper()) for c in alph) # upppercase
def rot13(s):
return "".join(rot13_table.get(c, c) for c in s) # non-letters are ignored
这条线
ccrypt = alph[ i+13 : i+14 ]
不会执行您认为的操作-它从i+13
到i+14
返回一个字符串切片,但是如果这些索引大于字符串的长度,则该切片将为空:
"abc"[5:6] #returns ''
这意味着您的解决方案将从n
开始的所有内容转换为空字符串,从而产生观察到的输出。
正确的实现方式是(1.)使用模运算将索引约束为有效数字,以及(2.)使用简单字符访问而不是字符串切片,这更易于阅读,更快并且抛出IndexError
对于无效的索引,这意味着您的错误将很明显。
ccrypt = alph[(i+13) % 26]
可能引起一些问题的第一件事-字符串列表的n
和o
切换,因此您需要进行调整:)至于算法,在运行时:
ccrypt = alph[ i+13 : i+14 ]
想一想当您从第一次迭代中得到25
时(对于z
)会发生什么。 现在,您正在寻找索引位置alph[38:39]
(旁注:您实际上可以说alph[38]
),它远远超出了26个字符的字符串的界限,该字符串将返回''
:
In [1]: s = 'abcde'
In [2]: s[2]
Out[2]: 'c'
In [3]: s[2:3]
Out[3]: 'c'
In [4]: s[49:50]
Out[4]: ''
至于解决方法,有许多有趣的方法。 您的代码只需进行一些修改即可正常运行。 您可以做的一件事是创建已经“旋转” 13个位置的字符映射:
alph = 'abcdefghijklmnopqrstuvwxyz'
coded = 'nopqrstuvwxyzabcdefghijklm'
我们在这里所做的全部工作是将原始列表分成13个一半,然后交换它们-现在我们知道,如果我们采用a这样a
字母并获得其位置( 0
),则编码列表中的相同位置将是rot13
值。 因为这是一项任务,所以我不会详细说明如何执行任务,但是请查看它是否使您步入正轨(@Makoto的建议是检查结果的理想方法)。
如果您将其作为Python课程的练习,请忽略此内容,只是说...
>>> import codecs
>>> codecs.encode('Some text', 'rot13')
'Fbzr grkg'
>>>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.