簡體   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