凯撒密码(与众不同)
大家好,我正在尝试制作一个密码,按照以下步骤进行:
- 打印一个标题。
- 提示用户输入包含加密信息的文件名、解码密钥(也就是位移数字)以及存储解密信息的文件名。
- 从文件中读取加密信息。
- 使用解码密钥,将加密信息中的每个字符按相应的位移数字进行转换,生成对应的解密信息字符串。
- 将解密后的信息保存到第二个文件中。
- 在屏幕上打印出加密和解密后的信息。注意,我不能使用ord()或chr()这两个函数。
让我感到困惑的是关于加密和解密文件的部分。我不太知道该怎么编码。
我对这些还很陌生,所以任何帮助都将非常感激。提前谢谢大家。
2 个回答
既然你说文件的处理是你最大的难题,我猜你需要一个这样的功能:
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
功能,那么你可以把这段代码插入到上面的伪代码中合适的位置,你就会得到一个基本可用的解决方案。
注意:听起来你可能是在做学校的作业。我强烈建议你把下面的代码仅作为示例,而不是完整的解决方案。我不希望你的作业出现抄袭的问题,而且我相信你的教授/老师在网上查找之前的工作方面很有经验。祝你作业顺利!
我写了一个快速示例,展示我可能如何解决你的问题。这个示例有几个已知的问题:
- 它没有处理大写字母。(除了把它们转换成小写字母。)
- 它没有处理标点符号或非字母数字字符。(比如数字、空格或换行符。)
- 没有错误检查。
- 如果你尝试转换一个小于 -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.