加密插入单词,并用密钥将字母向右移动
这是我的代码,它会让用户输入一个字母和一个数字。我的代码会根据这个数字,把字母在字母表中向右移动。
def code_char(character, number):
characterOrd = ord(character)
characterNew = characterOrd + number
if 65 <= characterOrd <= 90:
characterNew = characterOrd + number
if characterNew > 90:
characterNewi = characterNew - 26
return (chr(characterNewi))
elif characterNew <= 90:
return (chr(characterNew))
elif 97 <= characterOrd <= 122:
characterNew = characterOrd + number
if characterNew > 122:
characterNewi = characterNew - 26
return (chr(characterNewi))
elif characterNew <= 122:
return (chr(characterNew))
(别担心我代码里的缩进,复制粘贴的时候没带上 - 我测试过了,运行得很好 - 比如输入'a'会得到'b',输入'Z'会得到'A'。)
我想知道怎么在一个新函数里使用这个功能,让它询问一个8个字符长的字符串'abcdefgh'和一个8位的数字'11111111',然后把对应的字母在字母表中向右移动。所以我的例子会返回'bcdefghi'。
问题是,我更想处理字符串,而不是像我上面函数那样用数字。
任何建议或方法都很受欢迎,但我对python的了解有限,所以如果能用一些基本的函数就好了。
2 个回答
0
看起来你在做凯撒密码加密。
这里有个简化版:
def code_char(text, shift):
a = ord('a')
return ''.join(
chr((ord(char) - a + shift) % 26 + a) if 'a' <= char <= 'z' else char
for char in text.lower())
print code_char('abcdefgh', 1)
>>> bcdefghi
这样做可以让你更加灵活:
print code_char('rstuwxyz', 1)
>>> stuvxyza
记住,ASCII码的编号从26之后开始,这一点很重要:
>>> ord('a')
97
所以你仍然需要使用序号,这就是我设置 a = ord('a')
的原因,这样你就可以传递字符串,而不需要指定一个'字符串'列表或偏移量。
1
最简单的方法就是在一个循环里使用你的函数,并用zip把字符串和偏移量结合起来。
def new_func(string, offsets):
outstr = ""
for char, num in zip(string, offsets):
outstr += code_char(char, int(num))
print(outstr)
还有一种更简洁的写法:
print("".join([code_char(char, int(num)) for char, num in zip(string, offsets)]))
看看它是怎么运行的(使用python3):
if __name__ == '__main__':
string = input("string: ")
offsets = input("offsets: ")
if len(string) != len(offsets):
print("They must be the same length!")
else:
print("".join([code_char(char, int(num))
for char, num in zip(string, offsets)]))
# string: abcdefgh
# offsets: 12345678
# bdfhjlnp
你也可以简单地更新你现有的函数,以满足新的需求。
# Modified original
def code_char_string(character_string, offsets):
out_string = ""
for character, offset in zip(character_string, offsets):
number = int(offset)
characterOrd = ord(character)
characterNew = characterOrd + number
if 65 <= characterOrd <= 90:
characterNew = characterOrd + number
if characterNew > 90:
characterNewi = characterNew - 26
out_string += (chr(characterNewi))
elif characterNew <= 90:
out_string+= (chr(characterNew))
elif 97 <= characterOrd <= 122:
characterNew = characterOrd + number
if characterNew > 122:
characterNewi = characterNew - 26
out_string += (chr(characterNewi))
elif characterNew <= 122:
out_string += (chr(characterNew))
return out_string
你还可以使用以下技巧,让代码更容易阅读。
# Simplified readable version
def code_char_string_compact(character_string, offsets):
out_string = ""
for cord, number in zip([ord(x) for x in character_string], [int(x) for x in offsets]):
newchar = cord + number
if 65 <= cord <= 90:
out_string += chr(newchar - 26) if newchar > 90 else chr(newchar)
elif 97 <= cord <= 122:
out_string += chr(newchar - 26) if newchar > 122 else chr(newchar)
return out_string
你的函数也可以简化成一行很长的代码。
# oneliner awesomeness
def code_char_one_line(character_string, offsets): return "".join([chr(cord + number - 26) if 65 <= cord <= 90 < cord + number or 97 <= cord <= 122 < cord + number else chr(cord + number) for cord, number in zip([ord(x) for x in character_string], [int(x) for x in offsets])])
试试这些方法:
string, offsets, offsets2 = "abcdefgh", "11111111", "48151623"
print(code_char_string(string, offsets), code_char_string_compact(string, offsets), code_char_one_line(string, offsets))
# bcdefghi bcdefghi bcdefghi
print(code_char_string(string, offsets2), code_char_string_compact(string, offsets2), code_char_one_line(string, offsets2))
# ejdiflik ejdiflik ejdiflik