Reputation: 39
I'm new to Swift and I cannot figure out which optional variable that I unwrapped and I assigned nil to it, I tried to debug it on Playground but it won't let me step through the code.
Fatal error: Unexpectedly found nil while unwrapping an Optional value
public class ListNode {
public var val: Int
public var next: ListNode?
public init() { self.val = 0; self.next = nil; }
public init(_ val: Int) { self.val = val; self.next = nil; }
public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; }
}
class Solution {
func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
let result = ListNode()
var resultTail = result
var carry: Int = 0
var out: Int = 0
var val1: Int = 0
var val2: Int = 0
var head1: ListNode? = l1
var head2: ListNode? = l2
while (l1 != nil || l2 != nil || carry != 0) {
val1 = head1 != nil ? head1!.val : 0
val2 = head2 != nil ? head2!.val : 0
out = (val1 + val2 + carry) % 10
carry = (val1 + val2 + carry) / 10
resultTail.next = ListNode(out)
resultTail = resultTail.next!
head1 = head1?.next!
head2 = head2?.next!
}
return result.next!
}
}
let node3 = ListNode(3)
let node2 = ListNode(4, node3)
let node1 = ListNode(2, node2)
let node3a = ListNode(5)
let node2a = ListNode(6, node3a)
let node1a = ListNode(4, node2a)
let solution = Solution().addTwoNumbers(node1, node1a)
Best regards, Farros
Upvotes: 1
Views: 156
Reputation: 114856
If you search for the "unexpectedly found nil" error message you will find several questions and answers that explain what this means and suggest debugging techniques.
While the root cause of this error can be subtle, the trigger for the exception is force unwrapping an optional that is nil
or referencing an implicitly unwrapped optional that is nil
.
You don't have a lot of code here, so it isn't hard to find where you do one of those things;
You force unwrap in your ternary operator, that is after a check for nil
, so that won't crash
You force unwrap resultTail.next
and result.next
but you have assigned values in those cases, so that won't cause the crash.
The last place is where you force unwrap head1.next
and head2.next
at the bottom of your while loop. This is a mistake because you know that next
will eventually be nil
at the end of your list.
Simply removing the !
will eliminate the exception, but introduce a new bug because your while
loop condition tests the initial parameters l1
and l2
whose values never change. You risk an infinite loop. I think you meant to reference head1
and head2
.
You should try and eliminate all force unwraps and this isn't too hard:
head1
and head2
are optional, so there is no need to force unwrap next
resultTail
as an optional and use conditional unwrapping or no unwrappingclass Solution {
func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
let result = ListNode()
var resultTail: ListNode? = result
var carry = 0
var head1 = l1
var head2 = l2
while (head1 != nil || head2 != nil || carry != 0) {
let val1 = head1?.val ?? 0
let val2 = head2?.val ?? 0
let sum = val1 + val2 + carry
let out = sum % 10
carry = sum / 10
resultTail?.next = ListNode(out)
resultTail = resultTail?.next
head1 = head1?.next
head2 = head2?.next
}
return result.next
}
}
Note that idiomatic Swift you only explicitly type variables where the correct type cannot be inferred automatically by the compiler or you need a different type to that which the compiler will infer.
You can also simplify and clarify your ListNode
by using named parameters with defaults in a single init
public class ListNode {
public var val: Int
public var next: ListNode?
public init(val: Int = 0, next: ListNode? = nil) {
self.val = val
self.next = next
}
}
class Solution {
func addTwoNumbers(_ l1: ListNode?, _ l2: ListNode?) -> ListNode? {
let result = ListNode()
var resultTail: ListNode? = result
var carry = 0
var head1 = l1
var head2 = l2
while (head1 != nil || head2 != nil || carry != 0) {
let val1 = head1?.val ?? 0
let val2 = head2?.val ?? 0
let sum = val1 + val2 + carry
let out = sum % 10
carry = sum / 10
resultTail?.next = ListNode(val: out)
resultTail = resultTail?.next
head1 = head1?.next
head2 = head2?.next
}
return result.next
}
}
let node3 = ListNode(val:3)
let node2 = ListNode(val: 4, next: node3)
let node1 = ListNode(val: 2, next: node2)
let node3a = ListNode(val:5)
let node2a = ListNode(val: 6, next: node3a)
let node1a = ListNode(val: 4, next: node2a)
let solution = Solution().addTwoNumbers(node1, node1a)
Upvotes: 0