Objective-C analizuje ciąg szesnastkowy na liczbę całkowitą

94

Chciałbym wiedzieć, jak analizować ciąg szesnastkowy reprezentujący liczbę w Objective-C. Jestem gotów użyć zarówno metody obiektywnej, jak i opartej na C, albo jest w porządku.

przykład:

#01FFFFAB

powinien przeanalizować liczbę całkowitą: 33554347

Każda pomoc będzie mile widziana!

Richard J. Ross III
źródło

Odpowiedzi:

169

Odpowiedź Joshua Weinberga jest w większości poprawna, jednak 0xprzedrostek jest opcjonalny podczas skanowania liczb całkowitych szesnastkowych. Jeśli masz ciąg w formacie #01FFFFAB, nadal możesz go używać NSScanner, ale możesz pominąć pierwszy znak.

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

[scanner setScanLocation:1]; // bypass '#' character
[scanner scanHexInt:&result];
dreamlax
źródło
1
Dzięki, dokładnie to, czego potrzebowałem!
Richard J. Ross III,
Zauważ, że jeśli chcesz przeprowadzić ścisłe analizowanie, powinieneś najpierw sprawdzić, czy ciąg nie zaczyna się od 0x(lub 0X). NSScanner zaakceptuje te przedrostki.
Chris Page
63

możesz użyć do tego NSScanner

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

outValbędzie zawierać int, którego szukasz. 0x jest opcjonalne.

Joshua Weinberg
źródło
1
Ponadto można użyć substytucji ciągu, aby przekonwertować znak # na przedrostek 0x.
hotpaw2
powinno być unsigned int outVal;
wanghq
12

strtol () jest twoim przyjacielem.

Konwertuje ciąg na długi i możesz przekazać podstawę liczby w. Usuń jednak ten #, który się najpierw wyloguje, lub przekaż strtolowi wskaźnik do pierwszego znaku numerycznego.

Graham Perks
źródło
1
Idę z tą metodą, o wiele prostszą (i potencjalnie szybszą) niż przydzielenie nsscanner.
Chris
1
@Chris: Prawdopodobnie nie jest to szybsze, jeśli masz NSString, ponieważ musiałbyś przekonwertować NSString na ciąg C, zanim będziesz mógł użyć strtol. Jeśli masz już tekst w ciągu C, prawdopodobnie będzie to szybsze, ale jeśli nie robisz tego tysiące lub miliony razy, wątpię, czy poczułbyś uderzenie w wydajność.
dreamlax
4
int res = strtol ([yourString UTF8String], NULL, base)
loretoparisi
1
@dreamlax Definicja - [NSString UTF8String] pokazuje, że zwraca wskaźnik do zapasowego ciągu znaków C UTF8 (NS_RETURNS_INNER_POINTER). Na wysokim poziomie jest to tylko jedna operacja zwracania tego wskaźnika const char w porównaniu z narzutem alokowania pamięci dla NSScanner, kopiowania parametru wejściowego NSString, nie wspominając o dodatkowym opóźnieniu przekazywania komunikatów ObjC, które występuje przy każdym wywołaniu metody ObjC. Strtoull () jest algorytmicznie znacznie szybszy, ale prawdopodobnie nie zauważysz różnicy, chyba że porównasz skanowanie liczb całkowitych szesnastkowych z milionów ciągów :-)
Jacob
1
strtolFunkcją jest również dużo bardziej łagodny. Napisz dokładne testy jednostkowe (uwzględniaj spacje, znaki inne niż szesnastkowe itp.), Ponieważ znajdziesz kilka zaskakujących przypadków skrajnych, które NSScannerzapewniają większą kontrolę.
Quintin Willison
5

Możesz użyć poniższej linii do konwersji. To tylko jeden wiersz kodu:

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

Miłego kodowania !!!

Sahil Mahajan
źródło
Zauważ, że jeśli chcesz przeprowadzić ścisłe analizowanie, powinieneś najpierw sprawdzić, czy ciąg nie zaczyna się od 0x(lub 0X), +/- lub innych znaków, które nie są uważane za prawidłowe w twoim wejściu.
Chris Page
2

Biblioteka standardowa Swift 4 wprowadziła nowy inicjator do analizowania wszystkich typów liczb całkowitych. Do parsowania z radixem (tj. Podstawą) potrzebny jest łańcuch i zwraca opcjonalną liczbę całkowitą:

let number = Int("01FFFFAB", radix: 16)!
Alexander Vasenin
źródło
@MZaragoza Dodałem kilka wyjaśnień
Alexander Vasenin
0

Według Apple:

Obiekt NSScanner interpretuje i konwertuje znaki obiektu NSString na wartości liczbowe i łańcuchowe.

więc jeśli masz obiekt, NSDatamożesz zrobić to dalej

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
źródło
Zauważ, że jeśli chcesz przeprowadzić ścisłe analizowanie, powinieneś najpierw sprawdzić, czy łańcuch nie zaczyna się od 0x(lub 0X) ani żadnych innych znaków, które nie są uważane za prawidłowe w twoim wejściu, ale które są akceptowane przez NSScanner.
Chris Page
0

Dla Swift 3:

var hex = "#01FFFFAB"
hex.remove(at: hex.startIndex)
var rgbValue:UInt32 = 0
Scanner(string: hex).scanHexInt32(&rgbValue)
// rgbValue == 33554347
jnelson
źródło