Objective-C analyse une chaîne hexadécimale en entier

94

Je voudrais savoir comment analyser une chaîne hexadécimale, représentant un nombre, en Objective-C. Je suis prêt à utiliser à la fois une méthode objective ou une méthode basée sur C, c'est bien.

exemple:

#01FFFFAB

devrait analyser le nombre entier: 33554347

Toute aide serait appréciée!

Richard J. Ross III
la source

Réponses:

169

La réponse de Joshua Weinberg est généralement correcte, mais le 0xpréfixe est facultatif lors de l'analyse des entiers hexadécimaux. Si vous avez une chaîne dans le format #01FFFFAB, vous pouvez toujours l'utiliser NSScanner, mais vous pouvez ignorer le premier caractère.

unsigned result = 0;
NSScanner *scanner = [NSScanner scannerWithString:@"#01FFFFAB"];

[scanner setScanLocation:1]; // bypass '#' character
[scanner scanHexInt:&result];
dreamlax
la source
1
Merci, exactement ce dont j'avais besoin!
Richard J.Ross III
Notez que si vous souhaitez effectuer une analyse stricte, vous devez d'abord vérifier que la chaîne ne commence pas par 0x(ou 0X). NSScanner acceptera ces préfixes.
Chris Page
63

vous pouvez utiliser NSScanner pour cela

unsigned int outVal;
NSScanner* scanner = [NSScanner scannerWithString:@"0x01FFFFAB"];
[scanner scanHexInt:&outVal];

outValcontiendra l'int que vous recherchez. Le 0x est facultatif.

Joshua Weinberg
la source
1
De plus, vous pouvez utiliser une substitution de chaîne pour convertir le caractère # en préfixe 0x.
hotpaw2
devrait être unsigned int outVal;
wanghq
12

strtol () est votre ami.

Il convertit une chaîne en un long, et vous pouvez passer la base du nombre en. Supprimez d'abord cette # signature ou passez à strtol un pointeur vers le premier caractère numérique.

Avantages Graham
la source
1
Je vais avec cette méthode, bien plus simple (et potentiellement plus rapide) que d'allouer un nsscanner.
Chris
1
@Chris: Ce n'est probablement pas plus rapide si vous avez une NSString, car vous auriez besoin de convertir la NSString en une chaîne C avant de pouvoir utiliser strtol. Si vous avez déjà le texte dans une chaîne C, ce sera probablement plus rapide, mais à moins que vous ne le fassiez des milliers ou des millions de fois, je doute que vous ressentiez une baisse des performances.
dreamlax
4
int res = strtol ([yourString UTF8String], NULL, base)
loretoparisi
1
@dreamlax La définition de - [NSString UTF8String] montre qu'elle renvoie un pointeur vers la chaîne de sauvegarde UTF8 C (NS_RETURNS_INNER_POINTER). À un niveau élevé, ce n'est qu'une seule opération pour renvoyer ce pointeur de caractères const par rapport à la surcharge de l'allocation de mémoire pour NSScanner, en copiant le paramètre d'entrée NSString, sans parler de la latence supplémentaire de passage de message ObjC encourue avec chaque appel de méthode ObjC. Il est algorithmiquement beaucoup plus rapide d'utiliser strtoull (), mais vous n'observerez probablement pas la différence à moins que vous ne compariez des nombres entiers hexadécimaux à partir de millions de chaînes :-)
Jacob
1
La strtolfonction est également beaucoup plus clémente. Écrivez des tests unitaires approfondis (incluez des espaces, des caractères non hexadécimaux, etc.) car vous trouverez des cas extrêmes surprenants qui NSScannervous donnent plus de contrôle.
Quintin Willison
5

Vous pouvez utiliser la ligne ci-dessous pour la conversion. C'est juste un code de ligne:

NSString *hexString = @"01FFFFAB";
length = (UInt64)strtoull([hexString UTF8String], NULL, 16);
NSLog(@"The required Length is %d", length);

Bon codage !!!

Sahil Mahajan
la source
Notez que si vous souhaitez effectuer une analyse stricte, vous devez d'abord vérifier que la chaîne ne commence pas par 0x(ou 0X) ou +/- ou tout autre caractère qui n'est pas considéré comme valide dans votre entrée.
Chris Page
2

La bibliothèque standard Swift 4 a introduit un nouvel initialiseur pour analyser tous les types d'entiers. Il faut une chaîne pour analyser avec radix (c'est-à-dire base) et retourne un entier facultatif:

let number = Int("01FFFFAB", radix: 16)!
Alexandre Vasenin
la source
@MZaragoza J'ai ajouté quelques explications
Alexander Vasenin
0

Selon Apple:

Un objet NSScanner interprète et convertit les caractères d'un objet NSString en valeurs numériques et chaînes.

Donc, si tu as NSDataobj, tu peux faire ensuite

NSString *dataDescription = data.description;
NSString *dataAsString = [dataDescription substringWithRange:NSMakeRange(1, [dataDescription length]-2)];
unsigned intData = 0;
NSScanner *scanner = [NSScanner scannerWithString:dataAsString];
[scanner scanHexInt:&intData];
gbk
la source
Notez que si vous souhaitez effectuer une analyse stricte, vous devez d'abord vérifier que la chaîne ne commence pas par 0x(ou 0X) ou tout autre caractère qui n'est pas considéré comme valide dans votre entrée, mais qui est accepté par NSScanner.
Chris Page
0

Pour Swift 3:

var hex = "#01FFFFAB"
hex.remove(at: hex.startIndex)
var rgbValue:UInt32 = 0
Scanner(string: hex).scanHexInt32(&rgbValue)
// rgbValue == 33554347
jnelson
la source