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!

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];

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.


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.


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


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)!

@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];

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.