Objective-C analizar la cadena hexadecimal a un entero

94

Me gustaría saber cómo analizar una cadena hexadecimal, que representa un número, en Objective-C. Estoy dispuesto a utilizar tanto un método objetivo como uno basado en C, cualquiera de los dos está bien.

ejemplo:

#01FFFFAB

debe analizar en el entero: 33554347

¡Cualquier ayuda sería apreciada!

Richard J. Ross III
fuente

Respuestas:

169

La respuesta de Joshua Weinberg es en su mayoría correcta, sin embargo, el 0xprefijo es opcional cuando se escanean enteros hexadecimales. Si tiene una cadena en el formato #01FFFFAB, aún puede usar NSScanner, pero puede omitir el primer carácter.

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

[scanner setScanLocation:1]; // bypass '#' character
[scanner scanHexInt:&result];
Dreamlax
fuente
1
Gracias, ¡exactamente lo que necesitaba!
Richard J. Ross III
Tenga en cuenta que si desea realizar un análisis estricto, primero debe verificar que la cadena no comience con 0x(o 0X). NSScanner aceptará esos prefijos.
Chris Page
63

puede utilizar NSScanner para esto

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

outValcontendrá el int que estás buscando. El 0x es opcional.

Joshua Weinberg
fuente
1
Además, puede utilizar una sustitución de cadena para convertir el carácter # en el prefijo 0x.
hotpaw2
debe estar sin firmar int outVal;
wanghq
12

strtol () es tu amigo.

Convierte una cadena en una larga, y puede pasar la base del número. Sin embargo, elimine primero el signo # o pase a strtol un puntero al primer carácter numérico.

Beneficios de Graham
fuente
1
Voy con este método, mucho más simple (y potencialmente más rápido) que asignar un nsscanner.
Chris
1
@Chris: Probablemente no sea más rápido si tiene un NSString, porque necesitaría convertir el NSString a una cadena C antes de poder usar strtol. Si ya tiene el texto en una cadena C, probablemente será más rápido, pero a menos que esté haciendo esto miles o millones de veces, dudo que sienta el impacto en el rendimiento.
Dreamlax
4
int res = strtol ([yourString UTF8String], NULL, base)
loretoparisi
1
@dreamlax La definición de - [NSString UTF8String] muestra que devuelve un puntero a la cadena C UTF8 de respaldo (NS_RETURNS_INNER_POINTER). En un nivel alto, es solo una operación para devolver este puntero de carácter constante frente a la sobrecarga de asignar memoria para NSScanner, copiando el parámetro de entrada NSString, sin mencionar la latencia adicional de paso de mensajes ObjC incurrida con cada invocación del método ObjC. Es algorítmicamente mucho más rápido usar strtoull (), pero es probable que no observe la diferencia a menos que esté comparando el escaneo de enteros hexadecimales de millones de cadenas :-)
Jacob
1
La strtolfunción también es mucho más indulgente. Escriba pruebas unitarias exhaustivas (incluya espacios, caracteres no hexadecimales, etc.) ya que encontrará algunos casos extremos sorprendentes sobre los que tendrá NSScannermás control.
Quintin Willison
5

Puede utilizar la siguiente línea para la conversión. Es solo un código de línea:

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

Codificación feliz !!!

Sahil Mahajan
fuente
Tenga en cuenta que si desea realizar un análisis estricto, primero debe verificar que la cadena no comience con 0x(o 0X) o +/- o cualquier otro carácter que no se considere válido en su entrada.
Chris Page
2

La biblioteca estándar de Swift 4 introdujo un nuevo inicializador para analizar todos los tipos de enteros. Se necesita una cadena para analizar con radix (es decir, base) y devuelve un entero opcional:

let number = Int("01FFFFAB", radix: 16)!
Alexander Vasenin
fuente
@MZaragoza Agregué algunas explicaciones
Alexander Vasenin
0

Según Apple:

Un objeto NSScanner interpreta y convierte los caracteres de un objeto NSString en valores numéricos y de cadena.

entonces, si tienes un objetivo, NSDatapuedes hacer lo siguiente

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
fuente
Tenga en cuenta que si desea realizar un análisis estricto, primero debe verificar que la cadena no comience con 0x(o 0X) o cualquier otro carácter que no se considere válido en su entrada, pero que NSScanner acepta.
Chris Page
0

Para Swift 3:

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