Python向列表添加元素时触发out of range索引越界错误
问题:凯撒密码破解程序触发列表索引越界错误
错误复现
程序核心逻辑是对用户输入的密文执行25轮凯撒移位解密,每轮结果和kelimeler.txt词表匹配,输出匹配成功的明文。运行时抛出IndexError: list index out of range,报错点在kelime_getir函数的kelimeler.append(kelime_listesi[index])行。
出错的完整代码:
import re sifrelenmisdizi = [] kelimeler = [] bulunankelimeler = [] input = input("Lütfen Şifrelenmiş Veriyi giriniz : ") def sifrecoz(message): #im cracking password here encrypted = "" for i in range(25): for char in message: value = ord(char) + 1 valuex = value % 123 if (valuex <= 0): valuex = 97 encrypted += chr(valuex) elif (valuex == 33): encrypted += chr(32) else: encrypted += chr(valuex) message = encrypted sifrelenmisdizi.append(encrypted) encrypted = "" def kelime_getir(dosya_adi): # here im taking words on "kelimeler.txt" with open(dosya_adi, 'r', encoding='utf-8') as input_file: dosya_icerigi = input_file.read() kelime_listesi = dosya_icerigi.split() index = 0 while index <= 1164053: kelimeler.append(kelime_listesi[index]) #here im taking that issue index += 1 return kelimeler sifrecoz(input) kelime_getir("kelimeler.txt") for i in range(len(kelimeler)): for j in range(len(sifrelenmisdizi)): x = re.split("\s", sifrelenmisdizi[j]) for k in range(len(x)): if (kelimeler[i] == x[k]): bulunankelimeler.append(kelimeler[i]) print("Kırılmış şifreniz : ",bulunankelimeler) # selam daktilo dalga = ugnco eblujmp ebmhb
错误原因
- 核心问题是
kelime_getir里硬编码了循环上限1164053。split()按空白拆分文件内容得到的列表长度,和文件编码、换行符数量、内容版本直接相关,本地词表拆分后实际长度小于写死的索引上限,访问不存在的索引必然越界。硬编码外部文件的元素总数本身就是完全不可靠的写法。 - 代码里还有几个会导致运行异常/结果错误的问题:
- 用
input作为变量名,直接覆盖了Python内置的输入函数,后续如果再调用输入方法会直接报错。 - 凯撒移位逻辑混乱:边界判断冗余,移位方向错误,非小写字母、标点的处理逻辑有漏洞,25轮移位的结果会出现乱码。
- 匹配逻辑用三重循环遍历全量词表,16MB的词表跑起来效率极低,而且没有做大小写统一,很容易出现匹配漏判。
- 用
修复代码
sifrelenmisdizi = [] kelimeler = [] bulunankelimeler = [] def sifrecoz(message): cozum_listesi = [] message = message.lower() # 分别移位1-25位 for kaydirma in range(1, 26): cozulmus_metin = "" for char in message: # 仅处理小写字母,其余字符原样保留 if ord('a') <= ord(char) <= ord('z'): yeni_ord = ord(char) + kaydirma # 超出z的范围就绕回开头 if yeni_ord > ord('z'): yeni_ord -= 26 cozulmus_metin += chr(yeni_ord) else: cozulmus_metin += char cozum_listesi.append(cozulmus_metin) return cozum_listesi def kelime_getir(dosya_adi): kelimeler = [] with open(dosya_adi, 'r', encoding='utf-8') as f: icerik = f.read() kelime_listesi = icerik.split() # 直接遍历列表,不需要写死长度 for kelime in kelime_listesi: kelimeler.append(kelime.lower()) return kelimeler if __name__ == "__main__": sifreli_metin = input("Lütfen Şifrelenmiş Veriyi giriniz : ") sifrelenmisdizi = sifrecoz(sifreli_metin) kelimeler = kelime_getir("kelimeler.txt") # 词表转集合,匹配效率提升几个数量级 kelime_seti = set(kelimeler) dogru_sonuc = None for sonuc in sifrelenmisdizi: parcalar = sonuc.split() # 统计当前解密结果的词匹配占比 eslesen = 0 for parca in parcalar: if parca in kelime_seti: eslesen += 1 # 匹配占比超60%判定为正确明文 if eslesen / len(parcalar) >= 0.6: dogru_sonuc = sonuc break print("Kırılmış şifreniz : ", dogru_sonuc if dogru_sonuc else "Eşleşme bulunamadı")
内容的提问来源于stack exchange,提问作者Harun Erkam Balı
相关产品推荐
相关产品推荐

