2015-05-21 17 views
7

In base allo Swift - Converting String to Int, esiste un metodo StringtoInt().Swift: Come convertire String in UInt?

Tuttavia, non esiste il metodo toUInt(). Quindi, come convertire un String in un Uint?

+0

per ulteriori dettagli rapida 2.x, String non contiene Toint() –

+0

@suraj Si prega di smettere di aggiungere le "ios" tag a domande che non sono direttamente legate a iOS. Swift funziona anche con OS X e Linux e possono essere applicate queste domande. Grazie. – Moritz

+0

@Eric D .. Grazie per aver chiarito i tag. –

risposta

10

Aggiornamento per Swift 2/Xcode 7 :

A partire da Swift 2, tutti i tipi interi hanno un costruttore (disponibile)

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

che sostituisce il metodo di StringtoInt(), in modo che nessun codice personalizzato è più necessaria per questo compito:

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) 

Vecchio risposta per 1.x Swift:

Sembra un po 'complicato, ma dovrebbe funzionare per tutti i numeri nell'intervallo completo di UInt, e rilevare tutti i possibili errori correttamente (come overflow o caratteri finali non validi):

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

Osservazioni:

  • BSD funzione di libreria strtoul viene utilizzato per la conversione. Il endPtr è impostato sul primo "carattere non valido" nella stringa di input, pertanto endPtr.memory == 0 deve essere conservato se tutti caratteri possono essere convertiti. In caso di errore di conversione, la variabile globale errno è impostata su su un valore diverso da zero (ad esempio ERANGE per un overflow).

  • Il test per il segno meno è necessario perché strtoul() accetta numeri negativi (che sono convertiti nel numero senza segno con lo stesso modello bit).

  • Una stringa Swift viene convertito in una stringa C "dietro le quinte" quando passato a una funzione di prendere un parametro char *, quindi uno potrebbe essere tentati di chiamare strtoul(self, &endPtr, 0) (che è quello che ho fatto nel la prima versione di questa risposta). Il problema è che la stringa C creata automaticamente da è solo temporanea e può essere già valida quando restituisce strtoul(), in modo che endPtr non punti più a un carattere nella stringa di input. Questo è successo quando ho testato il codice nel Playground. Con self.withCString { ... }, questo problema non si verifica perché la stringa C è valida durante l'esecuzione della chiusura.

Alcuni test:

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

Sarebbe utile se il downvoter lasciasse un commento esplicativo. –

+0

come convertire la stringa '0xff0000' in UInt? – TomSawyer

+0

@TomSawyer facile :-) let str = "0xff0000"; let p = UInt (String (str.characters.dropFirst (2)), radix: 16) // Opzionale (16711680) – user3441734

-1

basta usare init di UInt:

let someString = "4" 

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

Questo genera un'eccezione __runtime__ se la conversione fallisce – Antonio

2

prega, per l'amore di non schiantarsi, non utilizzare ! per fare questo.

E 'facile virare un map sulla fine della toInt per convertirlo in un optional UInt:

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

quindi utilizzare the usual unwrapping techniques su myUInt.

E se vi trovate a fare questo molto:

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: come sottolinea @MartinR, mentre sicuro, questo non estrae l'intera gamma di possibili valori per un UInt che Int doesn' t cover, guarda le altre due risposte.

+0

Non dovrebbe essere flatMap() nel primo? – oisdk

+1

Questo (così come le due risposte precedenti) non funzionerà se il numero è al di fuori dell'intervallo di un intero * firmato *. –

+0

oops si hai assolutamente ragione, ho tirato il controllo extra fino al primo esempio ma ho dimenticato di modificare la mappa –

3

Potreste essere interessati a una soluzione più sicura simile a:

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 

Spero che questo aiuti

// A cura seguendo @ Martin R. suggerimento

+0

Una preoccupazione ecco che questo accetterà spazzatura alla fine della stringa, che non corrisponde al comportamento della funzione 'toInt()', cioè "4blah" .toInt() 'restituisce' nil' ma '" 4blah ". toUnt() 'restituisce' 4' –

+0

... Che può essere facilmente risolto aggiungendo il test '&& scanner.atEnd'. Un altro problema è che * l'overflow * non viene rilevato. –

+0

@Martin R. Il rilevamento _overflow_ potrebbe essere aggiunto alla scansione per un 'Decimale' e quindi facendo i controlli appropriati. Questa soluzione rapida potrebbe funzionare per la maggior parte dei casi comuni, evitando arresti '!'. –

0

Usa forzata Scartare o opzionale Binding per assicurarsi che la stringa può essere convertita in uint. esempio:

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

//Forced Unwrapping 

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