Objective-C将十六进制字符串解析为整数

95
我想知道如何在Objective-C中解析代表数字的十六进制字符串。 我愿意使用目标方法或基于C的方法,两种方法都可以。
示例:
#01FFFFAB

应该解析为整数: 33554347

任何帮助将不胜感激!

7个回答

172

Joshua Weinberg的答案基本正确,然而在扫描十六进制整数时,0x前缀是可选的。如果你有一个格式为#01FFFFAB的字符串,你仍然可以使用NSScanner,但是可以跳过第一个字符。

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

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

请注意,如果您想执行严格的解析,应首先检查字符串是否不以“0x”(或“0X”)开头。NSScanner将接受这些前缀。 - Chris Page

65

你可以使用NSScanner来完成这个任务。

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

outVal将包含你需要的整数。0x是可选项。


1
此外,您可以使用字符串替换将#字符转换为0x前缀。 - hotpaw2
应该是无符号整数 outVal; - wanghq

12

strtol() 是你的好帮手。

它将一个字符串转换为长整型,可以传递数字的进制。但是,要先去掉那个#符号,或者将指向第一个数字字符的指针传递给 strtol。


1
我选择这种方法,比分配nsscanner更简单(并且可能更快)。 - Chris
1
@Chris:如果你有一个NSString,那么使用strtol之前需要将NSString转换为C字符串,这样可能不会更快。如果你已经有了C字符串中的文本,那么这可能会更快,但除非你要这样做数千或数百万次,否则我怀疑你能感受到性能影响。 - dreamlax
4
使用以下代码将字符串转换为整数:int res = strtol([yourString UTF8String], NULL, base);其中,yourString 是要转换的字符串,base 是转换时使用的进制数。 - loretoparisi
2
@dreamlax 的定义 -[NSString UTF8String] 表明它返回指向后备 UTF8 C 字符串的指针 (NS_RETURNS_INNER_POINTER)。从高层次来看,与为 NSScanner 分配内存、复制 NSString 输入参数以及每个 ObjC 方法调用产生的额外 ObjC 消息传递延迟相比,只需要一个操作即可返回此 const char 指针。使用 strtoull() 算法上要快得多,但除非你在对数百万个字符串进行十六进制整数扫描的基准测试,否则你可能不会观察到差异 :-) - Jacob
@Jacob:根据文档NSString对象存储为UTF-16而不是UTF-8,因此需要首先进行转换为UTF-8(这可能是代价高昂的),而 NSScanner可能已经针对UTF-16进行了优化。NS_RETURNS_INNER_POINTER是一个注释,它延长了对象的生命周期,直到返回指针的最后使用(或任何从中派生的指针)。请参见这里。它适用于ARC / GC。 - dreamlax
1
strtol函数也更加宽容。编写彻底的单元测试(包括空格、非十六进制字符等),因为你会发现一些令人惊讶的边缘情况,而NSScanner可以给你更多的控制权。 - Quintin Willison

6
您可以使用以下代码进行转换。这只是一行简单的代码:
NSString *hexString = @"01FFFFAB";
length = (UInt64)strtoull([hexString UTF8String], NULL, 16);
NSLog(@"The required Length is %d", length);

愉快编码!!!


请注意,如果您想进行严格的解析,应首先检查字符串是否不以“0x”(或“0X”)或+/-开头,或任何其他在您的输入中不被视为有效的字符。 - Chris Page

2

Swift 4 标准库引入了一种新的初始化方法,用于解析所有整数类型。它接受要解析的字符串和进制(即基数),并返回可选的整数:

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

@MZaragoza 我添加了一些解释 - Alexander Vasenin

0

对于Swift 3:

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

0

根据 Apple:

NSScanner 对象将 NSString 对象的字符解释和转换为数字和字符串值。

因此,如果您有 NSData 对象,则可以执行以下操作

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接受的字符开头。 - Chris Page

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接