错误的指令错误Swift 3和XCode 8

时间:2017-01-30 21:31:47

标签: xcode swift3 swift-playground

我最近一直在学习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.

我收到此错误:

Error

如果你能让我知道如何改进我的代码以避免这样的事情变得更好。

1 个答案:

答案 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()
}