9

根据Swift - Converting String to Int,有一个String方法toInt()

但是,没有toUInt()办法。那么,如何将 a 转换String为 a Uint

4

5 回答 5

13

Swift 2/Xcode 7 的更新:

从 Swift 2 开始,所有整数类型都有一个(可失败的)构造函数

init?(_ text: String, radix: Int = default)

它替换了 的toInt()方法String,因此此任务不再需要自定义代码:

print(UInt("1234")) // Optional(1234)
// This is UInt.max on a 64-bit platform:
print(UInt("18446744073709551615")) // Optional(18446744073709551615)
print(UInt("18446744073709551616")) // nil (overflow)
print(UInt("1234x")) // nil (invalid character)
print(UInt("-12")) // nil (invalid character)

Swift 1.x 的旧答案:

这看起来有点复杂,但应该适用于 的全部范围内的所有数字UInt,并正确检测所有可能的错误(例如溢出或尾随无效字符):

extension String {
    func toUInt() -> UInt? {
        if contains(self, "-") {
            return nil
        }
        return self.withCString { cptr -> UInt? in
            var endPtr : UnsafeMutablePointer<Int8> = nil
            errno = 0
            let result = strtoul(cptr, &endPtr, 10)
            if errno != 0 || endPtr.memory != 0 {
                return nil
            } else {
                return result
            }
        }
    }
}

评论:

  • BSD 库函数strtoul用于转换。endPtr设置为输入字符串中的第一个“无效字符”,因此如果所有字符都可以转换,endPtr.memory == 0则必须保留。在转换错误的情况下,全局变量被设置为非零值(例如溢出)。errnoERANGE

  • 负号测试是必要的,因为strtoul()它接受负数(使用相同的位模式转换为无符号数)。

  • 当传递给带参数的函数时,Swift 字符串会“在幕后”转换为 C 字符串char *,因此可能会被诱惑调用strtoul(self, &endPtr, 0)(这是我在此答案的第一个版本中所做的)。问题是自动创建的 C 字符串只是临时的, strtoul()返回时可能已经无效,因此endPtr不再指向输入字符串中的字符。这发生在我在 Playground 中测试代码时。使用self.withCString { ... },则不会出现此问题,因为 C 字符串在闭包的整个执行过程中都是有效的。

一些测试:

println("1234".toUInt()) // Optional(1234)
// This is UInt.max on a 64-bit platform:
println("18446744073709551615".toUInt()) // Optional(18446744073709551615)
println("18446744073709551616".toUInt()) // nil (overflow)
println("1234x".toUInt()) // nil (invalid character)
println("-12".toUInt()) // nil (invalid character)
于 2015-05-21T19:53:12.523 回答
4

您可能对类似于以下的更安全的解决方案感兴趣:

let uIntString = "4"
let nonUIntString = "foo"

extension String {
    func toUInt() -> UInt? {
        let scanner = NSScanner(string: self)
        var u: UInt64 = 0
        if scanner.scanUnsignedLongLong(&u)  && scanner.atEnd {
            return UInt(u)
        }
        return nil
    }
}

uIntString.toUInt()     // Optional(4)
nonUIntString.toUInt()  // nil

希望这可以帮助

// 根据@Martin R. 的建议编辑

于 2015-05-21T19:33:28.210 回答
3

请,为了不崩溃的爱,不!要这样做。

很容易map在末尾添加 atoInt以将其转换为可选的UInt

let str = "4"
let myUInt = str.toInt().flatMap { $0 < 0 ? nil : UInt($0) }

然后在. _myUInt

如果你发现自己经常这样做:

extension String {
    func toUInt() -> UInt? {
        return self.toInt().flatMap { $0 < 0 ? nil : UInt($0) }
    }
}

let str = "-4"
if let myUInt = str.toUInt() {
    println("yay, \(myUInt)")
}
else {
    println("nuh-uh")
}

编辑:正如@MartinR 指出的那样,虽然安全,但这并没有提取未涵盖的全部可能值UIntInt请参阅其他两个答案。

于 2015-05-21T19:27:26.487 回答
1

使用 Forced Unwrapping 或 Optional Binding 确保字符串可以转换为 UInt。例如:

let string = "123"
let number = UInt(string) //here number is of type *optional UInt*

//Forced Unwrapping

if number != nil {
  //converted to type UInt
}
于 2017-12-12T12:49:42.727 回答
-1

只需使用 UInt 的初始化:

let someString = "4"

UInt(someString.toInt()!) // 4
于 2015-05-21T19:15:21.817 回答