创建凯撒密码方法
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 命名事物的方式。
但是现在让我们看一下源代码本身:
- 比较
c >= $A & (c <= $Z)
表示c isLetter
。
下一个字符的条件计算意味着我们要通过将其向右移动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.
所以我需要在 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 命名事物的方式。
但是现在让我们看一下源代码本身:
- 比较
c >= $A & (c <= $Z)
表示c isLetter
。 下一个字符的条件计算意味着我们要通过将其向右移动
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.