4

我是编程新手,我正在尝试使用 python 编写 Vigenère 加密密码。这个想法很简单,我的功能也是如此,但是在这一行中:

( if((BinKey[i] == 'b')or(BinKey[i+1] == 'b')): ) 

似乎我有一个索引问题,我不知道如何解决它。错误信息是:

IndexError: string index out of range

我试图i+1用另一个等于 的变量替换索引i+1,因为我认为 python 可能正在重新增加i,但它仍然不起作用。

所以我的问题是:

  1. 如何解决问题,我做错了什么?

  2. 看看我的代码,我能学到什么来提高我的编程技能?

  3. 我想为我的程序构建一个简单的接口(它将包含所有加密密码),而我从谷歌想出的只是 pyqt,但是对于一个非常简单的接口来说似乎工作量太大,所以有没有更简单的方法建立一个界面?(我正在使用 Eclipse Indigo 和 Python3.x 的 pydev)

Vigenère 加密函数(包含导致问题的行)是:

def Viegner_Encyption_Cipher(Key,String):
    EncryptedMessage = ""
    i = 0
    j = 0
    BinKey = Bin_It(Key)
    BinString = Bin_It(String)
    BinKeyLengh = len(BinKey)
    BinStringLengh = len(BinString)
    while ((BinKeyLengh > i) and (BinStringLengh > j)):
        if((BinKey[i] == 'b')or(BinKey[i+1] == 'b')):
            EncryptedMessage = EncryptedMessage + BinKey[i]
        else:   
            EncryptedMessage = EncryptedMessage + Xor(BinKey[i],BinString[j])
        i = i + 1
        j = j + 1
        if (i == BinKeyLengh):
            i = i+j
    return EncryptedMessage

这是Bin_It功能:

 def Bin_It(String):
    TheBin = ""
    for Charactere in String:
         TheBin = TheBin + bin(ord(Charactere))
    return TheBin

最后是Xor函数:

def Xor(a,b):
    xor = (int(a) and not int(b)) or (not int(a) and int(b))
    if xor:
        return chr(1)
    else:
        return chr(0)
4

4 回答 4

4

在您的 while 条件下,您确保i < len(BinKey). 这意味着这BinKey[i]将是有效的,但BinKey[i+1]在循环的最后一次迭代中将无效,因为您将访问BinKey[len(BinKey)],这是字符串末尾的一个。python中的字符串从包含开始0和结束len-1

为避免这种情况,您可以将循环标准更新为

while BinKeyLength > i+1 and ...:
于 2012-11-11T11:51:23.440 回答
4

你可以改变

while ((BinKeyLengh > i) and (BinStringLengh > j)):

while ((BinKeyLengh > i-1) and (BinStringLengh > j)):

或改变

if((BinKey[i] == 'b')or(BinKey[i+1] == 'b')):

if((BinKey[i] == 'b') or (BinKeyLengh > i-1 and BinKey[i+1] == 'b')):

这将避免尝试进入BinKey[BinKeyLength]超出范围的 。

于 2012-11-11T11:51:35.103 回答
2

看看我的代码,我能学到什么来提高我的编程技能?

在索引上循环不是惯用的 Python。最好在可能的情况下循环遍历迭代器的元素。毕竟,这通常是您感兴趣的:for i in...通常后面跟着my_list[i].

在这个例子中,你应该使用内置函数zip(或者itertools.izip如果你的代码是惰性的,虽然这在 Python 3中不是必需的),它为你提供来自两个或多个迭代器的值对,并在最短的一个时停止筋疲力尽的。

for key_char, string_char in zip(BinKey, BinString):  # takes values sequentially from
                                                      # BinKey and BinString
                                                      # and binds them to the names
                                                      # key_char and string_char
    # do processing on key_char and string_char

如果您真的必须对索引执行while循环,则将测试反过来进行,以便更清楚您在做什么。相比

while len(BinKey) > i and len(BinString) > j:  # this looks like len(BinKey) and
                                               # len(BinString) are varying and you're
                                               # comparing them to static variables i and j

while i < len(BinKey) and j < len(BinString):  # this looks like you're varying i and j
                                               # and comparing them to len(BinKey) and len(BinString)

哪个更好地传达了循环的目的?


最后,条款

if (i == BinKeyLengh):
    i = i+j

似乎什么也没做。如果i == BinKeyLength那么while循环无论如何都会停止。

于 2012-11-11T12:07:41.910 回答
1

正如 Python 解释器所说,我认为您的错误是您访问了无效的数组位置。为了解决这个问题,与人们所说的不同,您应该将代码更改为

while (BinKeyLength > i+2 and ...):

这是因为在最后一步中,BinKeyLength = i+2,那么 i+1 就是 BinKeyLength-1,也就是你数组的最后一个位置。

关于您的编程技能,我向您推荐两件事:

  • 成为代码。听起来很神秘,但这里缺少的最重要的事情是弄清楚使用了哪些索引号。
  • 正如 rubik 所说,遵循一些风格指南,如PEP8 风格指南
于 2012-11-11T11:58:11.993 回答