繁体   English   中英

Python文本加密:rot13

[英]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+13i+14返回一个字符串切片,但是如果这些索引大于字符串的长度,则该切片将为空:

"abc"[5:6] #returns ''

这意味着您的解决方案将从n开始的所有内容转换为空字符串,从而产生观察到的输出。

正确的实现方式是(1.)使用模运算将索引约束为有效数字,以及(2.)使用简单字符访问而不是字符串切片,这更易于阅读,更快并且抛出IndexError对于无效的索引,这意味着您的错误将很明显。

ccrypt = alph[(i+13) % 26]

可能引起一些问题的第一件事-字符串列表的no切换,因此您需要进行调整:)至于算法,在运行时:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM