问题
According to Swift - Converting String to Int, there's a String
method toInt()
.
But, there's no toUInt()
method. So, how to convert a String
to a Uint
?
回答1:
Update for Swift 2/Xcode 7:
As of Swift 2, all integer types have a (failable) constructor
init?(_ text: String, radix: Int = default)
which replaces the toInt()
method of String
, so no custom
code is needed anymore for this task:
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)
Old answer for Swift 1.x:
This looks a bit complicated, but should work for all numbers in the
full range of UInt
, and detect all possible errors correctly
(such as overflow or trailing invalid characters):
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
}
}
}
}
Remarks:
The BSD library function strtoul is used for the conversion. The
endPtr
is set to first "invalid character" in the input string, thereforeendPtr.memory == 0
must be hold if all characters could be converted. In the case of a conversion error, the globalerrno
variable is set to a non-zero value (e.g.ERANGE
for an overflow).The test for a minus sign is necessary because
strtoul()
accepts negative numbers (which are converted to the unsigned number with the same bit pattern).A Swift string is converted to a C string "behind the scenes" when passed to a function taking a
char *
parameter, so one could be tempted to callstrtoul(self, &endPtr, 0)
(which is what I did in the first version of this answer). The problem is that the automatically created C string is only temporary and can already be invalid whenstrtoul()
returns, so thatendPtr
does not point to a character in the input string anymore. This happened when I tested the code in the Playground. Withself.withCString { ... }
, this problem does not occur because the C string is valid throughout the execution of the closure.
Some tests:
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)
回答2:
You might be interested in a safer solution similar to:
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
Hope this helps
// Edited following @Martin R. suggestion
回答3:
Please, for the love of not crashing, don’t use !
to do this.
It’s easy to tack a map
on the end of toInt
to convert it to an optional UInt
:
let str = "4"
let myUInt = str.toInt().flatMap { $0 < 0 ? nil : UInt($0) }
then use the usual unwrapping techniques on myUInt
.
And if you find yourself doing this a lot:
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")
}
edit: as @MartinR points out, while safe, this doesn’t extract the full range of possible values for a UInt
that Int
doesn’t cover, see the other two answers.
回答4:
Use Forced Unwrapping or Optional Binding to make sure the string can be converted to UInt. eg:
let string = "123"
let number = UInt(string) //here number is of type *optional UInt*
//Forced Unwrapping
if number != nil {
//converted to type UInt
}
回答5:
just use UInt's init:
let someString = "4"
UInt(someString.toInt()!) // 4
来源:https://stackoverflow.com/questions/30382414/swift-how-to-convert-string-to-uint