Swift: 如何将String 转换为UInt?
Swift: How to convert String to UInt?
根据Swift - Converting String to Int,有一个String
方法toInt()
。
但是,没有 toUInt()
方法。那么,如何将 String
转换为 Uint
?
只需使用 UInt 的 init:
let someString = "4"
UInt(someString.toInt()!) // 4
为了不崩溃,请不要使用!
来做这个。
很容易在 toInt
的末尾添加一个 map
以将其转换为可选的 UInt
:
let str = "4"
let myUInt = str.toInt().flatMap { [=10=] < 0 ? nil : UInt([=10=]) }
然后在 myUInt
上使用 。
如果您发现自己经常这样做:
extension String {
func toUInt() -> UInt? {
return self.toInt().flatMap { [=11=] < 0 ? nil : UInt([=11=]) }
}
}
let str = "-4"
if let myUInt = str.toUInt() {
println("yay, \(myUInt)")
}
else {
println("nuh-uh")
}
编辑:正如@MartinR 指出的那样,虽然安全,但这并没有提取 Int
未涵盖的 UInt
的全部可能值范围,请参阅其他两个答案.
您可能对类似于以下的更安全的解决方案感兴趣:
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. 建议编辑
更新 Swift 2/Xcode 7:
从 Swift 2 开始,所有整数类型都有一个(可失败的)构造函数
init?(_ text: String, radix: Int = default)
替换了String
的toInt()
方法,所以没有自定义
此任务不再需要代码:
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)
Swift1.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
设置为输入字符串中的第一个 "invalid character",
因此 endPtr.memory == 0
必须保持如果 all 个字符
可以转换。
在转换错误的情况下,设置全局 errno
变量
为非零值(例如 ERANGE
表示溢出)。
减号测试是必要的,因为 strtoul()
接受
负数(用
相同的位模式)。
A Swift 字符串转换为 C 字符串 "behind the scenes" 时
传递给带有 char *
参数的函数,因此可以是
很想打电话给 strtoul(self, &endPtr, 0)
(这是我在
这个答案的第一个版本)。问题是自动
创建的 C 字符串只是临时的,当
strtoul()
returns, 所以 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)
使用 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
}
根据Swift - Converting String to Int,有一个String
方法toInt()
。
但是,没有 toUInt()
方法。那么,如何将 String
转换为 Uint
?
只需使用 UInt 的 init:
let someString = "4"
UInt(someString.toInt()!) // 4
为了不崩溃,请不要使用!
来做这个。
很容易在 toInt
的末尾添加一个 map
以将其转换为可选的 UInt
:
let str = "4"
let myUInt = str.toInt().flatMap { [=10=] < 0 ? nil : UInt([=10=]) }
然后在 myUInt
上使用
如果您发现自己经常这样做:
extension String {
func toUInt() -> UInt? {
return self.toInt().flatMap { [=11=] < 0 ? nil : UInt([=11=]) }
}
}
let str = "-4"
if let myUInt = str.toUInt() {
println("yay, \(myUInt)")
}
else {
println("nuh-uh")
}
编辑:正如@MartinR 指出的那样,虽然安全,但这并没有提取 Int
未涵盖的 UInt
的全部可能值范围,请参阅其他两个答案.
您可能对类似于以下的更安全的解决方案感兴趣:
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. 建议编辑
更新 Swift 2/Xcode 7:
从 Swift 2 开始,所有整数类型都有一个(可失败的)构造函数
init?(_ text: String, radix: Int = default)
替换了String
的toInt()
方法,所以没有自定义
此任务不再需要代码:
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)
Swift1.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
设置为输入字符串中的第一个 "invalid character", 因此endPtr.memory == 0
必须保持如果 all 个字符 可以转换。 在转换错误的情况下,设置全局errno
变量 为非零值(例如ERANGE
表示溢出)。减号测试是必要的,因为
strtoul()
接受 负数(用 相同的位模式)。A Swift 字符串转换为 C 字符串 "behind the scenes" 时 传递给带有
char *
参数的函数,因此可以是 很想打电话给strtoul(self, &endPtr, 0)
(这是我在 这个答案的第一个版本)。问题是自动 创建的 C 字符串只是临时的,当strtoul()
returns, 所以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)
使用 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
}