Objective-C аналізує шістнадцятковий рядок на ціле число


94

Я хотів би знати, як проаналізувати шістнадцятковий рядок, що представляє число, у Objective-C. Я готовий використовувати як об'єктивний, так і метод на основі С, або це нормально.

приклад:

#01FFFFAB

слід проаналізувати ціле число: 33554347

Будь-яка допомога буде вдячна!

Відповіді:


169

Відповідь Джошуа Вайнберга переважно правильна, проте 0xпрефікс необов’язковий при скануванні шістнадцяткових цілих чисел. Якщо у вас є рядок у форматі #01FFFFAB, ви все ще можете використовувати NSScanner, але можете пропустити перший символ.

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

[scanner setScanLocation:1]; // bypass '#' character
[scanner scanHexInt:&result];

1
Дякую, саме те, що мені потрібно було!
Річард Дж. Росс III

Зверніть увагу, що якщо ви хочете виконати суворий синтаксичний аналіз, спочатку слід перевірити, чи рядок не починається з 0x(або 0X). NSScanner прийме ці префікси.
Кріс Пейдж

63

для цього можна використовувати NSScanner

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

outValміститиме інформацію, яку ви шукаєте. 0x не є обов’язковим.


1
Крім того, ви можете використовувати заміну рядка для перетворення символу # у префікс 0x.
hotpaw2

має бути без підпису int outVal;
wanghq

12

strtol () - ваш друг.

Він перетворює рядок у довгу, і ви можете передати основу числа. Зачепіть, що # підписатись спочатку, або перейдіть, щоб strtol вказівник на перший числовий символ.


1
Я піду з цим методом, набагато простішим (і потенційно швидшим), ніж розподіл nsscanner.
Кріс

1
@Chris: Можливо, це не швидше, якщо у вас є NSString, тому що вам потрібно буде перетворити NSString на рядок C, перш ніж ви зможете використовувати strtol. Якщо у вас вже є текст у рядку C, це, швидше за все, буде швидшим, але якщо ви не робите цього тисячі або мільйони разів, я сумніваюся, що ви відчули б досягнення продуктивності.
dreamlax

4
int res = strtol ([yourString UTF8String], NULL, base)
loretoparisi

1
@dreamlax Визначення - [NSString UTF8String] показує, що воно повертає вказівник на резервний рядок UTF8 C (NS_RETURNS_INNER_POINTER). На високому рівні це лише одна операція повернення цього покажчика const char проти накладних витрат на виділення пам’яті для NSScanner, копіювання вхідного параметра NSString, не кажучи вже про додаткову затримку передачі повідомлень ObjC, що виникає при кожному виклику методу ObjC. Алгоритмічно набагато швидше використовувати strtoull (), але ви, мабуть, не спостерігатимете різниці, якщо не будете проводити порівняльний аналіз шістнадцяткових цілих чисел з мільйонів рядків :-)
Яків

1
strtolФункція також набагато м'якша. Напишіть ґрунтовні модульні тести (включайте пробіли, символи, що не мають шістнадцяткової форми, тощо), оскільки ви знайдете кілька дивовижних випадків краю, які NSScannerдають вам більше контролю над ними.
Квінтін Віллісон

5

Для перетворення можна використати наведений нижче рядок. Це лише один рядок:

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

Щасливого кодування !!!


Зауважте, що якщо ви хочете виконати суворий синтаксичний аналіз, спершу перевірте, чи рядок не починається з 0x(або 0X) або +/- або будь-якими іншими символами, які не вважаються дійсними у вашому введенні.
Кріс Пейдж

2

Стандартна бібліотека Swift 4 представила новий ініціалізатор для синтаксичного аналізу всіх цілих типів. Для аналізу з radix (тобто базою) потрібен рядок і повертається необов’язкове ціле число:

let number = Int("01FFFFAB", radix: 16)!

@MZaragoza Я додав кілька пояснень
Олександр Васенін

0

За даними яблука:

Об'єкт NSScanner інтерпретує та перетворює символи об'єкта NSString у числові та рядкові значення.

отже, якщо у вас є NSDataobj, ви можете зробити наступне

NSString *dataDescription = data.description;
NSString *dataAsString = [dataDescription substringWithRange:NSMakeRange(1, [dataDescription length]-2)];
unsigned intData = 0;
NSScanner *scanner = [NSScanner scannerWithString:dataAsString];
[scanner scanHexInt:&intData];

Зауважте, що якщо ви хочете виконати суворий синтаксичний аналіз, вам слід спочатку перевірити, чи рядок не починається з 0x(або 0X) або будь-якими іншими символами, які не вважаються дійсними у вашому введенні, але які приймаються NSScanner.
Кріс Пейдж

0

Для Swift 3:

var hex = "#01FFFFAB"
hex.remove(at: hex.startIndex)
var rgbValue:UInt32 = 0
Scanner(string: hex).scanHexInt32(&rgbValue)
// rgbValue == 33554347
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.