-2

Good Evening, Hi guys i am new with swift, so i try to make a simple calculator by converting an infix notation to a postfix notation. Basically the code gonna works like this, All numbers are pushed to the output when they are read. At the end of reading the expression, pop all operators off the stack and onto the output.

So i try to compile the code and it says that Fatal error: Unexpectedly found nil while unwrapping an Optional value:

can someone help with with this thank you so much :)

Fatal error: Unexpectedly found nil while unwrapping an Optional value:

    import UIKit

var tokens: [String] = ["4 + 4 + 2"]
func precedence(op: String) -> Int{
    if(op == "+" || op == "-"){
        return 1
    }
    if(op == "*" || op == "/" || op == "%"){
        return 2
    }
    
    return 0
}

func applyOp(a: Int, b: Int, op: String) -> Int{
    switch op{
    case "+":
        return a + b
    case "-":
        return a -  b
    case "*":
        return a * b
    case "/":
        return a / b
    case "%":
        return a % b
    default:
        return 0
    }
    return 0
}


func evaluate(tokens: [String]) -> Int{
    var i: Int! = 0
    
    var values: [Int] = []
    var ops : [String] = []
    
    while i < tokens.count{
        if(tokens[i] >= "0" && tokens[i] <= "9"){
            var val : Int = 0
            
            while i < tokens.count && tokens[i] >= "0" && tokens[i] <= "9"{
                val = (val * 10) + Int(tokens[i])!
                i = i + 1
            }
            
            values.append(val)
            i = i - 1
        }
        else{
            while ops.count != 0 && precedence(op: ops[-1]) >= precedence(op: tokens[i]){
                
                let val2 : Int! = values.popLast()
                let val1 : Int! = values.popLast()
                let op : String! = ops.popLast()
                
                values.append(applyOp(a: val1, b: val2, op: op))
            }
        }
        
        i = i + 1
    }
    
    while ops.count != 0{
        
        let val2 : Int! = values.popLast()
        let val1 : Int! = values.popLast()
        let op : String! = ops.popLast()
        
        values.append(applyOp(a: val1, b: val2, op: op))
    }
    
    return Int(values[-1])
}


print(evaluate(tokens: tokens))
CloverZZ
  • 9
  • 2
  • Two notes, firstly your input is a single element array but judging by the code you expect it to be an array with one element per number or operator so change the `tokens` property or change the code, secondly you have a bad habit of using forced unwrapping and implicitly unwrapped properties so remove all the ! and then adjust your code to deal with any possible nil values (optionals). More work but your code will be safer and you will learn more :) – Joakim Danielson Mar 13 '21 at 14:35

1 Answers1

0

you try to force cast a String to Int

val = (val * 10) + Int(tokens[i])!

tokens is an array of String, so if you force cast to Int you will get a nil

  • Where is the force cast? – Joakim Danielson Mar 13 '21 at 14:30
  • Why was this upvoted, it's clearly wrong – Joakim Danielson Mar 14 '21 at 13:35
  • I just copy past the code, Int(tokens[i]) is a cast of String to Int, by adding !, he force the cast, so if the cast is nil, there is an error during runtime due to the force unwrap – Etienne Jézéquel Mar 15 '21 at 09:15
  • No that is not a cast of string to int, that is proper conversion of string to int using an init method for the Int type, see [the documentation](https://developer.apple.com/documentation/swift/int/2927504-init). The result is an Optional so one could argue that the forced unwrap is bad but since OP is checking for a number earlier in the code it is ok although not optimal. – Joakim Danielson Mar 15 '21 at 09:24