2015-05-21 18 views
7

Gemäß Swift - Converting String to Int gibt es eine String Methode toInt().Swift: Wie konvertiert man String in UInt?

Aber es gibt keine toUInt() Methode. Also, wie konvertiert man eine String in eine Uint?

+0

für zusätzliches Detail swift 2.x, String nicht toInt enthalten() –

+0

@suraj Bitte beenden Sie die "ios" Tag zu Fragen hinzufügen, die auf iOS nicht direkt verwandt sind. Swift funktioniert auch mit OS X und Linux und diese Fragen können zutreffen. Vielen Dank. – Moritz

+0

@Eric D .. Danke für die Klärung der Tags. –

Antwort

10

Update für Swift 2/Xcode 7 :

Ab Swift 2 haben alle Integer-Typen einen (failable) Konstruktor

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

die die toInt() Methode der String ersetzt, so dass keine benutzerdefinierte Code benötigt wird, mehr für diese Aufgabe:

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) 

Alte Antwort für Swift 1.x:

Das sieht etwas kompliziert aus, sollte aber für alle Nummern im vollen Bereich vonfunktionierenund erfassen alle möglichen Fehler korrekt (wie beispielsweise Überlauf oder nachlauf ungültige Zeichen):

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 
      } 
     } 
    } 
} 

Bemerkungen:

  • Die BSD Bibliotheksfunktion strtoul für die Umwandlung verwendet wird. Die endPtr wird auf das erste "ungültige Zeichen" in der Eingabezeichenfolge gesetzt, daher muss endPtr.memory == 0 gehalten werden, wenn alle Zeichen konvertiert werden konnten. Im Fall eines Konvertierungsfehlers wird die globale Variable errno auf auf einen Wert ungleich Null gesetzt (z. B. ERANGE für einen Überlauf).

  • Der Test für ein Minuszeichen ist notwendig, weil strtoul() negative Zahlen annimmt (die die Zahl ohne Vorzeichen mit dem gleichen Bitmuster umgewandelt werden).

  • Ein Swift-String in einen C-String „hinter den Kulissen“ umgewandelt wird, wenn an eine Funktion übergeben einen char * Parameter genommen wird, so könnte man zu nennen strtoul(self, &endPtr, 0) versucht sein (das ist, was ich in hat die erste Version dieser Antwort). Das Problem ist, dass die automatisch erzeugte C-Zeichenfolge nur temporär ist und bereits ungültig sein kann, wenn strtoul() zurückkehrt, so dass endPtr nicht mehr auf ein Zeichen in der Eingabezeichenfolge zeigt. Das passierte, als ich den Code im Playground getestet habe. Mit self.withCString { ... } tritt dieses Problem nicht auf, da die C-Zeichenfolge während der Ausführung des Abschlusses gültig ist.

Einige 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) 
+1

Es wäre hilfreich, wenn der Downvoter einen erklärenden Kommentar hinterlassen würde. –

+0

Wie konvertiert man '0xff0000' in UInt? – TomSawyer

+0

@ TomSawyer einfach :-) Lassen Sie str = "0xff0000"; p = UInt (String (str.characters.dropFirst (2)), radix: 16) // Optional (16711680) – user3441734

-1

verwenden nur UInt init:

let someString = "4" 

UInt(someString.toInt()!) // 4 
+0

Dies generiert eine __runtime Ausnahme__, wenn die Konvertierung fehlschlägt – Antonio

2

Bitte, für die Liebe nicht abstürzt, nicht !, dies zu tun.

Es ist einfach ein map am Ende der toInt tack es zu einem optionalen UInt zu konvertieren:

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

dann the usual unwrapping techniques auf myUInt verwenden.

Und wenn Sie sich, dies zu tun eine Menge:

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: wie @MartinR weist darauf hin, während sicher, diese extrahieren nicht den vollen Bereich der möglichen Werte für eine UInt dass Int doesn‘ Bedecken Sie, sehen Sie die anderen zwei Antworten.

+0

Sollte es nicht FlatMap() in der ersten dort sein? – oisdk

+1

Diese (wie auch die vorherigen zwei Antworten) funktionieren nicht, wenn die Zahl außerhalb des Bereichs einer * signed * Ganzzahl liegt. –

+0

oops ja du bist absolut richtig, ich zog die zusätzliche Prüfung bis zum ersten Beispiel, aber vergessen, die Karte zu ändern –

3

Sie könnten in einer sichereren Lösung interessiert ähnlich sein:

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 

hoffe, das hilft

// Edited folgende @ Martin R. Vorschlag

+0

Ein Anliegen Hier ist, dass dies Müll am Ende des Strings akzeptiert, der nicht mit dem Verhalten der ähnlichen 'toInt()' Funktion übereinstimmt, dh '" 4blah ".toInt()' gibt 'nil' zurück, aber' "4blah". toUInt() 'returns' 4' –

+0

... Das lässt sich leicht lösen, indem man den Test '&& scanner.atEnd' hinzufügt. Ein weiteres Problem ist, dass * Überlauf * nicht erkannt wird. –

+0

@Martin R. Die _Overflow_Detection kann hinzugefügt werden, indem nach "Decimal" gesucht wird und dann die entsprechenden Prüfungen durchgeführt werden. Diese schnelle Lösung könnte für die Mehrzahl der Fälle funktionieren und "!" Abstürze vermeiden. –

0

Verwenden Zwang Auswickeln oder Optional Binding, um sicherzustellen, kann die Zeichenfolge in UInt umgewandelt werden. zB:

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

//Forced Unwrapping 

if number != nil { 
    //converted to type UInt 
} 
Verwandte Themen