0

I want a way to detect input errors in a string and notify the user. Take the following example:

    let fraction            = "15/8"

    let fractionArray       = fraction.components(separatedBy: "/")
    let numerator           = Double(fractionArray[0])
    let denominator         = Double(fractionArray[1])
    var linearFactor        = numerator! / denominator!

    print(numerator!, "/", denominator!, " = ", linearFactor)

But if I force unwrap, invalid characters in the string will force a compile error and I’d rather notify the user that the input string contains an invalid fraction. Optional chaining seems like the way to go but I can’t get the syntax right.

In my code (below), I place the optional chaining operator next to the array as shown including fraction?.components(separatedBy: “/“) but Fix-it tells me to delete it.

If there is a better way than optional chaining to address this problem can someone please explain what I might have missed when I searched for answers here so I can make the code work ? Thanks

    let fraction            = “15/8”

    if let fractionArray    = fraction?.components(separatedBy: “/“) {
    let numerator           = Double(fractionArray[0])
    let denominator         = Double(fractionArray[1])
    var linearFactor        = numerator / denominator

    print(numerator, "/", denominator, " = ", linearFactor)
        } else {
            print(“Invalid. Re-enter fraction”)
        }
Community
  • 1
  • 1
Greg
  • 1,750
  • 2
  • 29
  • 56
  • `fraction?.components(separatedBy: “/“) seems like the most obvious place` — What? It's opposite of obvious. `fraction` is definitely not an Optional, but result of `components(separatedBy:)` is. And `?` — is not declaration here, but Optional chaining operator. – user28434'mstep Dec 28 '16 at 09:26
  • 2
    Actually both answers to your previous question http://stackoverflow.com/questions/41336818/can-i-split-a-numeric-string-using-multiple-separators-in-a-swift-closure show how to use *optional binding* instead of the forced unwrap. – Martin R Dec 28 '16 at 09:27
  • 2
    See also [When should I compare an optional value to nil?](http://stackoverflow.com/questions/29717210/when-should-i-compare-an-optional-value-to-nil) for a list of good examples how to avoid forced unwrapping. – Btw, unwrapping nil is a *runtime error,* not a compile error. – Martin R Dec 28 '16 at 09:33
  • @Martin R, the latest post is a simplified digest of something more elaborate that evolved since my earlier post. I'll certainly edit my question once I finish comparing it with the two previous answers. – Greg Dec 28 '16 at 10:44
  • In the elaborate version I compared optional values to nil so I'll look at that post too. – Greg Dec 28 '16 at 11:41
  • @user28434, point taken. I've edited accordingly. Thanks. – Greg Dec 28 '16 at 11:55

1 Answers1

3
  1. fraction is String not String? so you don't have to use fraction?
  2. components return [] not []?, so you can use fractionArray without unwrap anything
  3. the only thing you have to unwrap is numerator and denominator, their type is Double?
  4. Thanks @OOPer, should check denominator != 0
  5. Thanks @Martin R, should check fractionArray.count == 2

so I'll refactor to the following code:

let fraction = "15/8"
let fractionArray = fraction.components(separatedBy: "/")
guard let numerator = Double(fractionArray[0]), 
    let denominator = Double(fractionArray[1]),
    denominator != 0,
    fractionArray.count == 2 else {
    print("Invalid. Re-enter fraction, or denominator == 0, or fractionArray.count != 2")
    return
}
let linearFactor = numerator / denominator
print(numerator, "/", denominator, " = ", linearFactor)
Sai Li
  • 685
  • 6
  • 14
  • 2
    This may not be the main topic, but if you want to make your code crash-safe, you'd better check `denominator` is not zero. – OOPer Dec 28 '16 at 09:50
  • 1
    thx, you are right, but 1.0/0.0 = inf, 0.0/0.0 = nan will be the results in the above codes – Sai Li Dec 28 '16 at 09:54
  • 2
    Right. My mistake, `inf` and `nan` may be something to avoid, but division by zero with `Double`s does not crash. Sorry. – OOPer Dec 28 '16 at 09:56
  • thx @OOPer ! update the solution – Sai Li Dec 28 '16 at 10:05
  • 3
    You may also want to check that the array has two elements (as it is done in this answer http://stackoverflow.com/a/41337068/1187415 to the author's previous question). – Martin R Dec 28 '16 at 10:08
  • 3
    The array count should be checked *before* accessing the array elements. – Martin R Dec 28 '16 at 10:23
  • 1
    @SaiCYLi, thanks, your first three points helped me understand something I missed in the answer to the previous Stackoverflow question. I got your code running once I created a new project (it didn't run in Playground). This is the accepted answer. – Greg Dec 28 '16 at 11:31