我最近一直在学习Swift 3语法,我认为一个好的第一个项目是VigenèreCipher。所以我开始在Playground中为它创建一个脚本。
问题是当我调用方法时我一直收到错误,我知道错误是什么,它与我如何调用我的字典值以及我打开它的事实有关,但我不知道我知道还有什么可做的。有什么想法吗?
import Foundation
let alphabet: [String: Int] = ["a": 0, "b": 1, "c": 2, "d": 3, "e": 4, "f": 5, "g": 6, "h": 7, "i": 8,
"j": 9, "k": 10, "l": 11, "m": 12, "n": 13, "o": 14, "p": 15, "q": 16,
"r": 17, "s": 18,"t": 19, "u": 20, "v": 21, "w": 22, "x": 23, "y": 24, "z": 25]
let alphabet2: [Int: String] = [0: "a", 1: "b", 2: "c", 3: "d", 4: "e", 5: "f", 6: "g", 7: "h", 8: "i",
9: "j", 10: "k", 11: "l", 12: "m", 13: "n", 14: "o", 15: "p", 16: "q",
17: "r", 18: "s", 19: "t", 20: "u", 21: "v", 22: "w", 23: "x", 24: "y", 25: "z"]
var mess = "I once saw a big mosquito"
var key = "pass"
func cipher(message: String, key: String) -> String{
var code: [Int] = [] // will hold the encripted code
// removes whietspace from message and key
let trimmedMessage = message.trimmingCharacters(in: NSCharacterSet.whitespaces)
let trimmedKey = key.trimmingCharacters(in: NSCharacterSet.whitespaces)
// Sets the key the same size as the message
let paddedTrimmedKey = trimmedKey.padding(toLength: message.characters.count, withPad: trimmedKey, startingAt: 0)
// separates the message and key into individual characters
let charTrimmedMessage = Array(trimmedMessage.characters)
let charPaddedTrimmedKey = Array(paddedTrimmedKey.characters)
// Compare the values in the key to the message and scrambles the message.
var i = 0
for chr in charTrimmedMessage{
code.append((alphabet[String(chr)]! + alphabet[String(charPaddedTrimmedKey[i])]!) % 26) // <- I think the error comes from this line. Maybe the exclamation marks?
i += 1
}
var cyphr: String = "" // this will hold the return String
// I think I could have used some sort of "join" function here.
for number in code{
cyphr = cyphr + alphabet2[number + 1]!
}
return cyphr
}
cipher(message: mess, key: key) // <--- this returns an error, no clue why. The code works and compiles great.
我收到此错误:
如果你能让我知道如何改进我的代码以避免这样的事情变得更好。
答案 0 :(得分:2)
您的alphabet
字典没有包含在纯文本中的字母“I”,“”的查找值。因此密码函数失败(因为它是强制解包一个可选的nil)
如果您初始化mess
变量,则会使密码生效
var mess = "ioncesawabigmosquito"
cipher(...) -> "ypgvuttpqcbzcpljkjmh"
要么
alphabet
查询词典。例如。添加''作为有效输入,更新alphabet2
以提供反向查找,并将mod因子从26更改为27(以考虑新的''字符)OR
要修改输入以仅包含字母表中的有效字母,您可以尝试:
let validSet = CharacterSet.init(charactersIn: alphabet.keys.joined())
var messTrimmed = mess.trimmingCharacters(in: validSet.inverted)
请注意,这样做意味着丢失原始邮件中的信息
另一个错误:
第cyphr = cyphr + alphabet2[number+1]!
行应为cyphr = cyphr + alphabet2[number]!
。
向数字添加1是不正确的,因为代码数组中的值是以模数26计算的,而字母表中的最大键值是25.当强制解包到不存在的键时会导致异常。
E.g。尝试cipher(message: "ypgvuttpqcbzcpljkjmh", key: "pass")
让它失败。
<强>脚注强>
完全不谈,这里有一个密码函数的变体(我没有清理输入;只显示代码如何以函数方式编写)
func cipher2(message: String, key: String) -> String {
return
message
.characters
.enumerated()
.map { ($0, String($1)) }
.map {
(
alphabet[$1]!
+ alphabet[String(key[key.index(key.startIndex, offsetBy: ($0 % key.characters.count))])]!
) % 26
}
.map { alphabet2[$0]! }
.joined()
}