简体   繁体   中英

Swift4 Playgrounds Caesar Cipher error

I'm trying to make a caesar cipher in Swift Playgrounds but whenever the letter is for example "W" and I'm trying to shift it by 4, instead of getting "A" I just get an error. If the ascii code + shift doesn't exceed the ascii code for Z, it works just fine, otherwise I get

error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0).

Here is my code:

func cipher(messageToCipher: String, shift: UInt32) {
    var ciphredMessage = ""

    for char in messageToCipher.unicodeScalars {
        var unicode : UInt32 = char.value

        if char.value > 64 && char.value < 123 {
            var modifiedShift = shift
            if char.value >= 65 && char.value <= 90 {
                while char.value + modifiedShift > 90 {
                 //return to A
                    modifiedShift -= 26
                }
            } else if char.value >= 97 && char.value <= 122 {
                while char.value + modifiedShift > 122 {
                  //return to a
                    modifiedShift -= 26
                }
            }

            unicode = char.value + modifiedShift
        }

        ciphredMessage += String(UnicodeScalar(unicode)!)
    }

    print(ciphredMessage)
}

Can anyone tell me why I get error when the ascii code for the letter + shift exceeds the "z"'s ascii code?

The shift is UInt32 . So, with var modifiedShift = shift , modifiedShift is inferred to be UInt32 , too. So when you set modifiedShift to 4, and then try to subtract 26 from it, that's not an acceptable UInt32 value.

Bottom line, use signed integers.

The problem is that the value of modifiedShift can be negative which is NOT allowed for a value of type UInt32 so I would suggest to use only Int whenever you can:

// use `Int` for `shift`
func cipher(messageToCipher: String, shift: Int) {
    var ciphredMessage = ""

    for char in messageToCipher.unicodeScalars {
        // convert to `Int`
        var unicode = Int(char.value)

        if unicode > 64 && unicode < 123 {
            var modifiedShift = shift
            if unicode >= 65 && unicode <= 90 {
                while unicode + modifiedShift > 90 {
                    //return to A
                    modifiedShift -= 26
                }
            } else if unicode >= 97 && unicode <= 122 {
                while unicode + modifiedShift > 122 {
                    //return to a
                    modifiedShift -= 26
                }
            }

            unicode += modifiedShift
        }

        ciphredMessage += String(UnicodeScalar(unicode)!)
    }

    print(ciphredMessage)
}

Note: you can also use if case for range matching. The following lines are semantically equivalent:

if unicode > 64 && unicode < 123 { ... }
if case 65..<123 = unicode { ... }
if (65..<123).contains(unicode) { ... }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM