字符串索引超出范围(Python)

时间:2017-11-24 10:20:21

标签: python encryption caesar-cipher

我正在编写一个用Caesar Cipher进行编码,解码和破解的程序。

我有这个函数可以将字符串中的字母移动指定的数量:

def shift(data, shifter):
    alphabet = "abcdefghijklmnopqrstuvwxyz"
    data = list(data)
    counter = 0  #  we will use this to modify the list while we iterate over it
    for letter in data:
        letter = letter.lower()
        if letter not in alphabet:
            counter += 1
            continue
        lPos = alphabet.find(letter)
        if shifter >= 0:
            shiftedPos = lPos + (0 - shifter)
        else:
            shiftedPos = lPos + abs(shifter)
        if shiftedPos >= len(alphabet) - 1: shiftedPos -= len(alphabet)
        data[counter] = alphabet[shiftedPos]  #  update the letter
        counter += 1  # advance
    data = ''.join(data)  # make it into a string again
    return data

我有这个功能来破解加密的字符串:

def crack(decryptor=None, tries=None):
    if decryptor is None and tries is None:
        task = getValidInput("Get data from a [f]ile or [s]tdin?  >", "Please give either 'f' or 's'.", 'f', 's')
        if task == "f":  # it's a file
            dataFile = getValidFile()  # get an open file object
            data = dataFile.read()  # get the data from the text file. hopefully it's ascii text!
        elif task == "s":  # we need to get data from stdin
            data = input("Enter data to crack  >")
        tries = getValidInt("Enter tries per sweep  >")
    else:
        data = decryptor

    retry = True
    shifter = 0
    while retry:
        for i in range(0, tries):
            oput = "Try " + str(i) + ": "
            posData = shift(data, shifter)
            negData = shift(data, 0 - shifter)
            # semitry 1 - positive
            oput += posData + ", "
            # semitry 2 - negative
            negData = ''.join(negData)  # make it into a string again
            oput += negData

            print(oput)

            shifter += 1

        doRetry = getValidInput("Keep trying (y/n)? > ", "Invalid!", 'y', 'n')
        if doRetry == 'n': retry = False

然而,选择' y'继续几次,我得到以下IndexError

Traceback (most recent call last):
  File "CeaserCypher.py", line 152, in <module>
    crack()
  File "CeaserCypher.py", line 131, in crack
    negData = shift(data, 0 - shifter)
  File "CeaserCypher.py", line 60, in shift
    print(alphabet[shiftedPos])
IndexError: string index out of range

为什么我会收到此错误以及如何解决?

1 个答案:

答案 0 :(得分:0)

IndexError意味着您尝试访问的索引不存在。在字符串中,这意味着您正在尝试从给定点的字符串中获取字符。如果该给定点不存在,那么您将尝试获取不在字符串内的字符。

&#34; 0123456&#34; [7]尝试获取字符串中的第7个字符,但该索引不存在,因此&#34; IndexError&#34;被提出来了。

字符串上的所有有效索引都小于字符串的长度(当你执行len(string)时)。在您的情况下,alphabet [shiftedPos]会引发IndexError,因为shiftedPos大于或等于字符串&#34; alphabet&#34;的长度。

根据我的理解,当你走出这样的界限时,你要做的是循环回字符串。 &#34; Z&#34; (字符25)被说出2并且成为字符27.在这种情况下,你想要现在成为字符2(字母&#34; b&#34;)。因此,你应该使用modulo。替换&#34;字母表[shiftedPos]&#34;用&#34;字母表[shiftedPos%len(alphabet)]&#34;而且我相信这会解决这个问题。

Modulo,顺便说一下,用n除以数字,给出余数。实际上,它会减去n,直到数字小于n(所以它总是在你想要的范围内)。