Swift: jak przekonwertować ciąg na UInt?


Według

Szybka konwersja ciągu znaków na Int
https://coderoad.ru/24115141/
istnieje metoda
String
toInt ()
.
Ale nie ma metody
toUInt ()
. Jak więc przekonwertować
String
na
Uint
?
Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:


Aktualizacja dla Swift 2/Xcode 7

:
Od wersji Swift 2 wszystkie typy liczb całkowitych mają konstruktora (odpornego na awarie)
init?(_ text: String, radix: Int = default)

która zastępuje metodę
toInt ()
z
String
, więc
do tego zadania nie jest już wymagany kod niestandardowy:
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)


Stara odpowiedź dla Swift 1.x

:
Wygląda to trochę skomplikowanie, ale powinno działać dla wszystkich liczb w
pełny zakres
UInt
i poprawnie wykryj wszystkie możliwe błędy
(jak przepełnienie lub zakończenie nieprawidłowych znaków):
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
}
}
}
}


Uwagi

:
  • Do konwersji służy funkcja biblioteki BSDhttps://developer.apple.com/li ... .html
    strtoul
    .
    endPtr
    to pierwszy „nieprawidłowy znak” w ciągu wejściowym, więc
    endPtr.memory == 0
    powinno zostać wstrzymane, jeśli wszystko symbolika można przekształcić. W przypadku błędu konwersji ustawiana jest zmienna globalna
    errno
    na wartość różną od zera (na przykład
    ERANGE
    dla przepełnienia).
  • Test znaku minus jest konieczny, ponieważ
    strtoul ()
    trwa liczby ujemne (które są konwertowane na liczbę bez znaku, tzw ten sam wzór bitowy).
  • Swift string jest konwertowany na łańcuch C „za kulisami”, gdy przekazanie funkcji, która przyjmuje parametr
    char *
    , aby można było pokusa wywołania
    strtoul (self, & amp; endPtr, 0)
    (co zrobiłem w pierwsza wersja tej odpowiedzi). Problem w tym, że automatycznie wygenerowany ciąg C jest tylko tymczasowy i może już być nieprawidłowy, gdy return
    strtoul ()
    , aby
    endPtr
    nie wskazywał już znak w ciągu wejściowym. Stało się to, gdy testowałem kod na placu zabaw. W przypadku
    self.withCString {...}
    ten problem nie występuje, ponieważ ciąg C jest prawidłowy przez cały czas wykonywania domknięcia.

Niektóre testy:
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)
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Możesz być zainteresowany bezpieczniejszym rozwiązaniem, takim jak:
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

Mam nadzieję że to pomoże
// edytowano w następujący sposób sugestia @Martin R.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Proszę, aby nie ulegać awariom, nie używaj
!
.
Łatwo jest dołączyć
mapę
na końcu
toInt
, aby przekonwertować ją na opcjonalny
UInt
:
let str = "4"
let myUInt = str.toInt().flatMap { $0 < 0 ? nil : UInt($0) }

następnie użyj

konwencjonalne metody rozwijania
https://stackoverflow.com/a/29717505/3925941
do
myUInt
.
A jeśli często to robisz:
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")
}

edycja: jak wskazuje @MartinR, chociaż jest to bezpieczne, nie wyodrębnia to pełnego zakresu możliwych wartości dla
UInt
, których
Int
nie obejmuje, zobacz pozostałe dwa odpowiedzi.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Użyj wymuszonego rozpakowywania lub opcjonalnego przyciągania, aby upewnić się, że ciąg można przekonwertować na UInt.
np .:
let string = "123"
let number = UInt(string)//here number is of type *optional UInt*//Forced Unwrappingif number != nil {
//converted to type UInt
}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

po prostu użyj UInt init:
let someString = "4"UInt(someString.toInt()!)// 4

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się