凯撒密码(与众不同)

-2 投票
2 回答
3235 浏览
提问于 2025-04-17 16:55

大家好,我正在尝试制作一个密码,按照以下步骤进行:

  1. 打印一个标题。
  2. 提示用户输入包含加密信息的文件名、解码密钥(也就是位移数字)以及存储解密信息的文件名。
  3. 从文件中读取加密信息。
  4. 使用解码密钥,将加密信息中的每个字符按相应的位移数字进行转换,生成对应的解密信息字符串。
  5. 将解密后的信息保存到第二个文件中。
  6. 在屏幕上打印出加密和解密后的信息。注意,我不能使用ord()或chr()这两个函数。

让我感到困惑的是关于加密和解密文件的部分。我不太知道该怎么编码。

我对这些还很陌生,所以任何帮助都将非常感激。提前谢谢大家。

2 个回答

0

既然你说文件的处理是你最大的难题,我猜你需要一个这样的功能:

def decaesar(message, shift):
   pass

这个功能可以逐个字符串地进行解密,也就是说,它接收一个加密的消息字符串,然后返回一个解密后的消息字符串。如果你还没有写这个功能,先把它写出来,并用一些固定的字符串来测试一下。现在先不考虑“加密和解密的文件”部分,编程就是要一步一步解决问题。

一旦你有了这个功能,并且确认它能正常工作,那么把你的程序扩展到处理文件而不是字符串就简单多了,只需要问自己:

  • 我能否通过文件名获取文件内容的字符串?还有,
  • 我能否把一个字符串写入一个指定名称的文件?

如果你能对这两个问题都回答“是”,那么你就可以在不改变你的decaesar功能的情况下,按照这个思路扩展你的程序。你的逻辑大致是这样的:

# Print header
encrypted_filename, decrypted_filename, shift = # get from user input
encrypted_message = # get the contents of encrypted_filename as a string
decrypted_message = decaesar(encrypted_message, shift)
# write decrypted_message to decrypted_filename
# print encrypted_message and decrypted_message

幸运的是,Python的文件输入输出正是基于这种将字符串和文件之间转换的原理。如果你打开了一个文件进行读取:

in_file = open(filename)

那么:

in_file.read()

的返回值正好是回答第一个问题的字符串。同样,如果你打开了一个文件进行写入:

out_file = open(filename, 'w')

那么:

out_file.write(my_string)

就会把my_string写入那个文件。

所以这意味着,如果你已经有了你的decaesar功能,那么你可以把这段代码插入到上面的伪代码中合适的位置,你就会得到一个基本可用的解决方案。

3

注意:听起来你可能是在做学校的作业。我强烈建议你把下面的代码仅作为示例,而不是完整的解决方案。我不希望你的作业出现抄袭的问题,而且我相信你的教授/老师在网上查找之前的工作方面很有经验。祝你作业顺利!

我写了一个快速示例,展示我可能如何解决你的问题。这个示例有几个已知的问题:

  1. 它没有处理大写字母。(除了把它们转换成小写字母。)
  2. 它没有处理标点符号或非字母数字字符。(比如数字、空格或换行符。)
  3. 没有错误检查。
  4. 如果你尝试转换一个小于 -25 的数字,它会出错。

可能最大的问题是不能使用 ord()chr()。我通过创建自己的字母和数字转换列表来绕过这个限制。一个棘手的情况是,如果位移使字母超出了转换范围 [0,25],该怎么处理。

顺便提一下,如果你想解密一个文件,你可以简单地把它当作明文打开,并使用一个负的偏移量,其绝对值等于加密时的偏移量。换句话说,如果你使用以下参数:

infile = clear.txt, offset = 1, outfile = encrypted.txt

要解密,你可以使用:

infile = encrypted.txt, offset = -1, outfile = decrypted.txt   

caesarcipher.py

import itertools

letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
           'r','s','t','u','v','w','x','y','z']
numbers = range(26) # Numbers 0 - 25
lettersToNumbers = dict(zip(letters, numbers))
numbersToLetters = dict(zip(numbers, letters))

def printHeader():
    """ Print the program informational header """
    print """=======================================
Welcome to CaesarCipher - The unbreakable
Roman cipher.
======================================="""

def convertToNumber(letter):
    """ Convert a letter to a number using our predefined conversion table
        @param letter: The letter to convert to an integer value
        @type letter: str
        @rtype: int
    """
    return lettersToNumbers[letter]

def convertToLetter(number):
    """ Convert a number to a letter using our predefined conversion table
        @param number: The number to convert to a letter
        @type number: int
        @rtype: str
    """
    # If we shift outside of our range make sure to wrap
    if number > 25:
        return numbersToLetters[number%25]
    elif number < 0:
        return numbersToLetters[number+25]
    else:
        return numbersToLetters[number]

def shiftUp(letter, shift):
    """ Shift letter up a given number of positions
        @param letter: The letter we're shifting
        @param shift: The number of positions to shift up
        @type letter: str
        @type shift: int

        @note: For simplicity we encode both capital and lowercase letters
               to the same values
    """
    number = convertToNumber(letter.lower())
    number += shift
    return convertToLetter(number)

def prompt():
    """ Prompt for user input
        @rtype: tuple of str, int, str
    """
    infile = raw_input("File to encrypt: ")
    offset = int(raw_input("Encoding number: "))
    outfile = raw_input("Encrypted file destination: ")
    return (infile, offset, outfile)

def encrypt(infile, offset, outfile):
    """ Encrypt the file using the given offset """
    print "=== Plaintext input ==="
    printFile(infile)
    with open(infile) as red_file:
        with open(outfile, 'w') as black_file:
            for line in red_file:
                for letter in line:
                    # Only convert alphabetic characters
                    if letter.isalpha():
                        black_file.write(shiftUp(letter, offset))
                    else:
                        black_file.write(letter)
    print "=== Ciphertext output ==="
    printFile(outfile)

def printFile(path):
    """ Print the data in the given file """
    with open(path) as print_file:
        for line in print_file:
            print line

printHeader()
encrypt(*prompt()) # `*` unpacks the tuple returned by `prompt()` into 
                   # three separate arguments.

test.txt

abcdef
ABCDEF
This is some text I want to try and encrypt.

示例运行:

mike@test:~$ python caesarcipher.py 
=======================================
Welcome to CaesarCipher - The unbreakable
Roman cipher.
=======================================
File to encrypt: test.txt
Encoding number: 1
Encrypted file destination: test.out 
=== Plaintext input ===
abcdef

ABCDEF

This is some text I want to try and encrypt.

=== Ciphertext output ===
bcdefg

bcdefg

uijt jt tpnf ufyu j xbou up usz boe fodszqu.

撰写回答