问题
So currently, my code looks like this (thanks to help in another post I made)
phrase = raw_input("Enter text to Cipher: ")
shift = int(raw_input("Please enter shift: "))
result = ("Encrypted text is: ")
for character in phrase:
#Loops through phrase and shows ascii numbers, example: hello is: 104,101,108,108,111
x = ord(character)
#adds a shift to each character so if shift is 1 'hello' becomes: ifmmp 105,102,109,109,112
result += chr(x + shift)
print "\n",result,"\n"
The problem is, if I type in more than one word for example: hello world , with a shift of 1
the output is: ifmmp!xpsme
The exclamation mark shows up for a space (varies depending on shift). I was thinking of doing an if statement to detect spaces:
phrase = raw_input("Enter text to Cipher: ")
shift = int(raw_input("Please enter shift: "))
result = ("Encrypted text is: ")
for character in phrase:
#Loops through phrase and shows ascii numbers, example: hello is: 104,101,108,108,111
x = ord(character)
if x == ord(' '):
print "\nfound a space space"
#adds 1 to each character so 'hello' becomes: ifmmp 105,102,109,109,112
result += chr(x + shift)
print "\n",result,"\n"
But I don't know how to add the space into the result variable. Also, I saw in this thread: Caesar's Cipher using python, could use a little help
That JeffB used a while loop for dealing with the ASCII table 32 being space and 127 being DEL. Why did he use 96? I don't understand.
while x < 32:
x += 96
while x > 127:
x -= 96
Sorry this question is rather long. Many thanks in advance! Your help is invaluable to me.
回答1:
You can just skip the space:
for character in phrase:
x = ord(character)
if character == ' ':
result += ' '
else:
result += chr(x + shift)
Your shift won't restrict the output to just ASCII. If you want to ensure that, you should use the modulo operator:
chr(32 + (x + shift) % (127 - 32))
回答2:
You can add a space like this:
if character.isspace():
result += ' '
or split the string at white-spaces:
Example:
>>> "hello world".split()
['hello', 'world']
code:
new_strs = []
result = ("Encrypted text is:")
for word in phrase.split():
new_word = []
for character in word:
x = ord(character) + shift
new_word.append(chr(x if 97 <= x <= 122 else 96 + x % 122))
new_strs.append("".join(new_word))
print result, " ".join(new_strs)
Why x if 97 <= x <= 122 else 96 + x % 122
?
For 'z'
with shift = 1 x + shift
will be 123, i.e '{'
.So, to get 'a'
instead of '{'
take the modulus of the new ordinance value with 122(ord('z')
) and add 96(ord('a') -1
) to it.
Output:
$ python so.py
Enter text to Cipher: hello xyz
Please enter shift: 1
Encrypted text is: ifmmp yza
回答3:
just use the maketrans and translate functions that basically encrypt or decrypt the message for you.they make for a very short and efficient solution to the problem
message = input('enter message').lower()
offset = int(input('enter offset (enter a negative number to decrypt)'))
alphabet = 'abcdefghijklmnopqrstuvwxyz'
enc_alphabet = (alphabet[alphabet.index(alphabet[offset]):len(alphabet)])+ alphabet[0:offset]
data = str.maketrans(alphabet,enc_alphabet)
final_message = str.translate(message, data)
print(final_message)
and then you won't have to worry about adding spaces or anything, this is a fully working caesar cipher encryption program
回答4:
Spaces are not the only problem that the Cesar Cipher (a.k.a. Shift Cipher) needs to deal with. Historically the characters are set to all upper case (or lower) and all spaces and all punctuation is removed.
This site shows a good example of the Cesar Cipher Implementation that deals with all of the punctuation removal as well as key generation (optionally). The linked implementation chose to use a whitelist of allowed characters implemented by regular expressions.
# Message is a the string to be encrypted / decrypted
sub(r'[^A-Z]', '', message.upper())
来源:https://stackoverflow.com/questions/18031520/caesar-cipher-python-additional-features