【问题标题】:Caesar cipher fails when output character is beyond 'z'当输出字符超出“z”时,凯撒密码失败
【发布时间】:2013-08-01 00:19:49
【问题描述】:

为了清楚起见,我问这个是因为我已经尝试了大约 1.5 个小时,但似乎无法获得任何结果。我没有上编程课或其他任何东西,但今年夏天我有很多空闲时间,我用很多时间从这本书中学习 Python。我想知道我将如何完成这个问题。

问题要求您创建一个运行“凯撒密码”的程序,该程序将字符的 ascii 数字向下移动您选择的某个键。例如,如果我想写 sourpuss 并选择键 2,程序会吐出全部向下移动 2 的 ascii 字符。所以 s 会变成 u,o 会变成 q(ascii 字母表中的 2 个字符......)。

我可以通过编写这个程序来获得那部分。

def main():
    the_word=input("What word would you like to encode? ")
    key=eval(input("What is the key? "))
    message=""
    newlist=str.split(the_word)
    the_word1=str.join("",the_word)
    for each_letter in the_word1:
        addition=ord(each_letter)+key
        message=message+chr(addition)
    print(message)
main()

运行这个程序,你会得到以下结果:

What word would you like to encode? sourpuss
What is the key? 2
uqwtrwuu

现在,下一个问题是,如果您将密钥添加到 ascii 数字并导致数字高于 128,则会出现问题。它要求您创建一个程序来实现 一个系统,如果数字高于 128,字母表将重置,您将返回 0 的 ascii 值。

我试图做的是这样的:

if addition>128:
    addition=addition-128

当我这样做后运行程序时,它不起作用,只是返回了一个空格而不是正确的字符。有任何想法吗?

【问题讨论】:

    标签: python if-statement for-loop python-3.x encryption


    【解决方案1】:

    尝试使用模运算而不是条件:

    ((ord('z') + 0 - 97) % 26) + 97
    => 122 # chr(122) == 'z'
    
    ((ord('z') + 1 - 97) % 26) + 97
    => 97 # chr(97) == 'a'
    
    ((ord('z') + 2 - 97) % 26) + 97
    => 98 # chr(98) == 'b'
    

    注意这个表达式:

    ((ord(character) + i - 97) % 26) + 97
    

    返回代表给定character的正确整数我们添加一个偏移量i(你称之为)。特别是,如果我们将0 添加到ord('z'),那么我们将返回'z' 的代码。如果我们将1 添加到ord('z'),那么我们将得到a 的代码,依此类推。

    这适用于a-z之间的小写字符,幻数97a的代码,26az之间的字符数;调整这些数字,您可以调整代码以支持更大范围的字符。

    【讨论】:

    • 优秀...我希望我能想到这一点。现在效果很好。
    【解决方案2】:

    英文字母表中没有 128 个字符,所以你不应该用 128 减去。而且我不知道你为什么认为问题会出现在 128 处。英文字母表中最后一个字符的序数是122. 当你达到 122 时,问题就发生了。

    另外,你没有处理大写和小写,但我想没关系,只要你总是使用小写。 :-)

    您提到这样做是为了“更多字符”。你可以做的是做一个二进制凯撒密码,它不关心你使用的是什么字符,而只是把它看作数字。

    def cipher(text, key):
        return [(c + key) % 256 for c in text.encode('utf8')]
    
    def decipher(data, key):
        return bytes([(c - key) % 256 for c in data]).decode('utf8')
    
    
    if __name__ == "__main__":
        data = cipher("This is a test text. !^äöp%&ł$€", 101)
        print("Cipher data:", data)
        print("Text:", decipher(data, 101))
    

    输出:

    Cipher data: [185, 205, 206, 216, 133, 206, 216, 133, 198, 133, 217, 202, 216, 217, 133, 217, 202, 221, 217, 147, 133, 134, 195, 40, 9, 40, 27, 213, 138, 139, 42, 231, 137, 71, 231, 17]
    Text: This is a test text. !^äöp%&ł$€
    

    【讨论】:

    • 是的,我正在考虑对所有字符都这样做,而不仅仅是字母......它也适用于大写。
    • @Pcarlitz:那么问题是什么是“所有字符”。你在这里说的是 Python 3,它有 Unicode 字符串。 Unicode 有 110.000 个字符,它们的值不是一个序列。并非所有字符都可以在任何地方使用。因此,这将成为一场彻头彻尾的噩梦。但是你可以用二进制数据来做,但是问题不会出现在 >128 而是 >255。
    【解决方案3】:

    尝试将其合并到您的代码中。这将做的是,如果你的凯撒密码的 ascii 数字高于 z 的 ascii 值,那么它将 - 26。例如,如果你的加法变量的值变为 123,程序将减去 26 给你 97给你'a'。如果 ascii 值低于 'a' 的值,这也有效。

    if addition > ord("z")
        addition -= 26
    elif addition < ord("a"):
        addition+=26
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-07
      相关资源
      最近更新 更多