创建凯撒密码方法

Creating a Caesar Cipher Method

所以我需要在 smalltalk 中获取 Caesar Cipher 代码并创建一个方法并使用它以便我可以对其进行以下测试

|aString|
aString:=Caesar new encrypt: 'CAESAR'.
Transcript show: aString.

我已经制作了 class。但是我需要制作它的方法。

我找到了这个,但是我怎样才能用它制作一个方法,这样我就可以在操场上使用上面的所有代码。

| i c strCipherText strText iShiftValue iShift |

strText := 'the quick brown fox jumps over the lazy dog'.
iShiftValue := 3.

strCipherText := ''.
iShift := iShiftValue \ 26.

i := 1.
[ i <= (strText size) ]
whileTrue: [
  c := (strText at: i) asUppercase.

  ( ( c >= $A) & ( c <= $Z ) )
  ifTrue: [

    ((c asciiValue) + iShift > $Z asciiValue)
    ifTrue: [
      strCipherText := strCipherText, (((c asciiValue) + iShift - 26)
                      asCharacter asString).
    ]
    ifFalse: [
      strCipherText := strCipherText, (((c asciiValue) + iShift)
                      asCharacter asString).
    ].

  ]
  ifFalse: [
    strCipherText := strCipherText, ' '.
  ].

  i := i + 1.
].

Transcript show: strCipherText.
Transcript cr.

所以为了清楚起见,我需要使用 Caesar Cipher 代码创建一个方法,并在开头使用 "aString" 代码并用它进行测试。我上面有这段代码,但是里面已经有文本,不能放入方法中。

如有任何帮助,我们将不胜感激。

正如 Max 在他的评论中所说,上面的代码可以放在一个方法中。唯一缺少的部分是带有选择器和正式参数的第一行:

caesarCipherOf: strText
  <insert the code here>

Max 的另一个好建议是调用参数 aString 而不是 strText 因为这更符合 Smalltalkers 命名事物的方式。

但是现在让我们看一下源代码本身:

  1. 比较c >= $A & (c <= $Z)表示c isLetter
  2. 下一个字符的条件计算意味着我们要通过将其向右移动3个字符来移位旋转c,如果超出则将其环绕$Z。这可以很容易地表示为:

    (c codePoint - 64 + 3 \ 26 + 64) asCharacter
    

    其中 64 = $A codePoint - 1$A 和任何给定大写字符 c 之间的偏移量。另请注意,我已将 asciiValue 替换为 codePoint

根据这两个观察结果,该方法可以重写为

    caesarCipherOf: aString
      ^aString collect: [:c |
        c isLetter
          ifTrue: [(c asUppercase codePoint - 64 + 3 \ 26 + 64) asCharacter]
          ifFalse: [$ ]]

这不仅更短,而且效率更高,因为它避免了在每个字符处创建 两个 String 的新实例。具体来说,

形式的任何表达式
string := string , <character> asString

创建两个 Strings:一个作为发送 #asString 的结果,另一个作为发送连接消息 #, 的结果。相反,#collect: 只创建一个实例,即方法 returns.