Python:解密凯撒密码

时间:2019-07-18 21:59:17

标签: python encryption caesar-cipher

任务:

编写一个脚本,该脚本输入一行加密的文本和一个距离值,并使用凯撒密码输出纯文本。

我的问题:

正在打印hello ^ 3 world ^ 2

我不确定为什么。我将不胜感激,帮助您解决或理解代码中的错误。 (这不是为年级分配的,即没有为自己的利益而做的截止日期

它希望我能够使用其相应的输入:

Lipps${svph% 4

Jhss'tl'Pzothls5 7

Zu&hk2&ux&tuz&zu&hk 2

khoor#zruog$ 3

我的代码:

code = input("enter coded text: ") 
distance = int(input("enter value: ")) 
plainText = "" 
for ch in code: 
  ordvalue = ord(ch) 
  ciphervalue = ordvalue - distance 
  if ciphervalue < ord('a'): 
    ciphervalue = ord('z') - \
      (distance - (ord('a')-ordvalue - 1))
  plainText += chr(ciphervalue) 
print(plainText)

1 个答案:

答案 0 :(得分:1)

首先,您应该将输入/输出与处理分离,因为您的代码将更易于测试:

Option Explicit
'Moves a UserForm accurately onto or near a Worksheet Range
'Adapts to the host hardware and settings

'Original code at MrExcel.COM question 765416 
'https://www.mrexcel.com/forum/excel-questions/765416-how-get-x-y-screen-coordinates-excel-cell-range.html
'added new Function PXtoPT, returning Points as Single (similar style to PTtoPX)
'NB x64 PtrSafe options NOT coded


Public Type RECT
  Left                  As Long
  Top                   As Long
  Right                 As Long
  Bottom                As Long
End Type

Private Declare Function GetDC Lib "user32" ( _
  ByVal hwnd As Long) As Long
Private Declare Function ReleaseDC Lib "user32" ( _
  ByVal hwnd As Long, ByVal hDC As Long) As Long
Private Declare Function GetSystemMetrics Lib "user32.dll" ( _
  ByVal nIndex As Long) As Long
Private Declare Function GetDeviceCaps Lib "gdi32" ( _
  ByVal hDC As Long, ByVal nIndex As Long) As Long
Private Declare Function GetCurrentThreadId Lib "kernel32" ( _
  ) As Long


Private Function ScreenDPI(bVert As Boolean) As Long
  'in most cases this simply returns 96
  Static lDPI&(1), lDC&
  If lDPI(0) = 0 Then
    lDC = GetDC(0)
    lDPI(0) = GetDeviceCaps(lDC, 88&)    'horz
    lDPI(1) = GetDeviceCaps(lDC, 90&)    'vert
    lDC = ReleaseDC(0, lDC)
  End If
  ScreenDPI = lDPI(Abs(bVert))
End Function

Private Function PTtoPX(Points As Single, bVert As Boolean) As Long
  PTtoPX = Points * ScreenDPI(bVert) / 72
End Function

Function PXtoPT(Pixels As Long, bVert As Boolean) As Single
'new function added
  PXtoPT = Pixels / ScreenDPI(bVert) * 72
End Function

Sub GetRangeRect(ByVal rng As Range, ByRef rc As RECT)
  Dim wnd               As Window

  'requires additional code to verify the range is visible
  'etc.

  Set wnd = rng.Parent.Parent.Windows(1)
  With rng
    rc.Left = PTtoPX(.Left * wnd.Zoom / 100, 0) _
              + wnd.PointsToScreenPixelsX(0)
    rc.Top = PTtoPX(.Top * wnd.Zoom / 100, 1) _
             + wnd.PointsToScreenPixelsY(0)
    rc.Right = PTtoPX(.Width * wnd.Zoom / 100, 0) _
               + rc.Left
    rc.Bottom = PTtoPX(.Height * wnd.Zoom / 100, 1) _
                + rc.Top
  End With
End Sub

Sub GetCoordinateXY()
Dim rc As RECT

Dim X, Y                            'PIXELS, not points
Dim Xpt As Single, Ypt As Single    'POINTS, not pixels
    On Error GoTo done
    Call GetRangeRect(ActiveCell, rc)
    X = rc.Left
    Y = rc.Top
    'ADDED
    Xpt = PXtoPT(rc.Left, False)
    Ypt = PXtoPT(rc.Top, True)

done:
End Sub

现在,您有:

def cipher(code, distance):
    plainText = ""
    for ch in code:
        ordvalue = ord(ch)
        ciphervalue = ordvalue - distance
        if ciphervalue < ord('a'):
            ciphervalue = ord('z') - (distance - (ord('a')-ordvalue - 1))
        plainText += chr(ciphervalue)
    return plainText

code = input("enter coded text: ")
distance = int(input("enter value: "))
print(cipher(code, distance))

我想您期望的是“ Hello world!”之类的东西。如果删除了这两行,就会得到以下结果:

>>> cipher("Lipps${svph%", 4)
'\x8aello²world±'

看:

if ciphervalue < ord('a'):
    ciphervalue = ord('z') - (distance - (ord('a')-ordvalue - 1))

那是问题的有趣部分。但是我认为您有一个正确的直觉:如果产生的def cipher2(code, distance): plainText = "" for ch in code: ordvalue = ord(ch) ciphervalue = ordvalue - distance plainText += chr(ciphervalue) return plainText >>> cipher2("Lipps${svph%", 4) 'Hello world!' >>> cipher2("Jhss'tl'Pzothls5", 7) 'Call me Ishmael.' >>> cipher2("Zu&hk2&ux&tuz&zu&hk", 6) # was 2, but I guess it's 6 'To be, or not to be' >>> cipher2("khoor#zruog$", 3) 'hello world!' 值不在预期范围内(即负数或很大),会发生什么?

ordvalue

函数>>> cipher2("hello", 103) Traceback (most recent call last): ... ValueError: chr() arg not in range(0x110000) 产生一个Unicode代码点,介于0和1114111之间,但是我认为对于一个练习,您可以将范围限制为0-127(ASCII字符):

ord

请注意:

def cipher3(code, distance):
    assert abs(distance) < 128
    plainText = ""
    for ch in code:
        ordvalue = ord(ch)
        ciphervalue = ordvalue - distance
        if ciphervalue < 0:
            ciphervalue += 128
        elif ciphervalue >= 128: # don't forget distance can be negative
            ciphervalue -= 128
        plainText += chr(ciphervalue)
    return plainText

>>> cipher3("hello", 103)
'\\x01~\\x05\\x05\\x08'
>>> cipher3('\x01~\x05\x05\x08', -103)
'hello'

等效于:

        if ciphervalue < 0:
            ciphervalue += 128
        elif ciphervalue >= 128: # don't forget distance can be negative
            ciphervalue -= 128

如果只想使用可打印字符,则可以使用 ciphervalue = ciphervalue % 128 模块:

string