Matte.Car
Matte.Car

Reputation: 2027

Trouble using width for String in for-in cycle

I've write a simple code:

extension String {
    func trailingSpaces (width: Int) -> String {
        var s = "\(self)"
        for i in count(s)..<width {
            s = s + " "
        }
        return s
    }

    func leadingSpaces (width: Int) -> String {
        var s = "\(self)"
        for i in count(s)..<width {
            s = " " + s
        }
        return s
    }
}

class ViewController: UIViewController {

    var users = ["Marco", "Gianni", "Antonio", "Giulio", "Franco"]
    var ages = [29, 45, 17, 33, 37]

    override func viewDidLoad() {
        super.viewDidLoad()

        var merged = [String: Int] ()
        var totalAge = 0.0

        for var i = 0; i < ages.count; i++ {
            merged[users[i]] = ages[i]
        }

        for user in sorted(merged.keys) {
            let age = merged[user]
            totalAge += Double(age!)
            let paddedUser = user.trailingSpaces(10)
            let paddedAge = "\(age)".leadingSpaces(3)
            println("\(paddedUser) \(age!)")
        }

        println("\n\(merged.count) users")
        println("average age: \(totalAge / Double(merged.count))")
    }
}

but I can't make it work the leadingSpaces function and I can't understand the reason, it's quite identical to the other extension func that works.

It give the error

fatal error: Can't form Range with end < start

on runtime

Upvotes: 0

Views: 57

Answers (2)

Grimxn
Grimxn

Reputation: 22507

Your variable age is not an Int - it's an optional - Int?. You know this already as you are unwrapping it in the lines totalAge += Double(age!) and println("\(paddedUser) \(age!)") - but you are not unwrapping it in the failing line let paddedAge = "\(age)".leadingSpaces(3). The string being passed to leadingSpaces is not "17", it's "Optional(17)", which is why your padding function is failing, as the length is greater than the requested width.

Having said that, as the commentator @milo256 points out, Swift can only iterate upwards, and so unless you put a check on width >= .count in your padding functions they will crash at some point.

Upvotes: 2

SnyersK
SnyersK

Reputation: 1296

in case you run into this kind of problem, always do a println() of the variable you are using

println("\(age)") right before let paddedAge = "\(age!)".leadingSpaces(3) reveals the problem

age is an optional, meaning that you are trying to do the padding on a String which has this value "Optional(17)"

Thus, your count(s) is higher than 3, and you have an invalid range

Upvotes: 2

Related Questions