通过指针枚举NSString字符
我怎么能通过拉每个unichar来枚举NSString? 我可以使用characterAtIndex,但这比通过增加unichar *来做要慢。 我没有看到任何苹果的文件,不需要复制string到第二个缓冲区。
像这样的东西将是理想的:
for (unichar c in string) { ... }
要么
unichar* ptr = (unichar*)string;
你可以加速-characterAtIndex:
先把它转换成IMP格式:
NSString *str = @"This is a test"; NSUInteger len = [str length]; // only calling [str length] once speeds up the process as well SEL sel = @selector(characterAtIndex:); // using typeof to save my fingers from typing more unichar (*charAtIdx)(id, SEL, NSUInteger) = (typeof(charAtIdx)) [str methodForSelector:sel]; for (int i = 0; i < len; i++) { unichar c = charAtIdx(str, sel, i); // do something with C NSLog(@"%C", c); }
编辑:看来, CFString
参考包含以下方法:
const UniChar *CFStringGetCharactersPtr(CFStringRef theString);
这意味着您可以执行以下操作:
const unichar *chars = CFStringGetCharactersPtr((__bridge CFStringRef) theString); while (*chars) { // do something with *chars chars++; }
如果你不想分配内存来处理缓冲区,这是要走的路。
您唯一的select是将字符复制到一个新的缓冲区。 这是因为NSString类不能保证有一个你可以使用的内部缓冲区。 最好的方法是使用getCharacters:range:
方法。
NSUInteger i, length = [string length]; unichar *buffer = malloc(sizeof(unichar) * length); NSRange range = {0,length}; [string getCharacters:buffer range:range]; for(i = 0; i < length; ++i) { unichar c = buffer[i]; }
如果你使用的是非常长的string,最好是分配一个固定大小的缓冲区,并以块的forms枚举string(这实际上是枚举的快速运行)。
我创build了一个块样式的枚举方法,使用getCharacters:range:
和一个固定大小的缓冲区,根据ughoavgfhw在他的回答中的build议。 它避免了CFStringGetCharactersPtr
返回null并且不需要malloc一个大缓冲区的情况。 你可以把它放到一个NSString类中,或者修改它来把一个string作为参数。
-(void)enumerateCharactersWithBlock:(void (^)(unichar, NSUInteger, BOOL *))block { const NSInteger bufferSize = 16; const NSInteger length = [self length]; unichar buffer[bufferSize]; NSInteger bufferLoops = (length - 1) / bufferSize + 1; BOOL stop = NO; for (int i = 0; i < bufferLoops; i++) { NSInteger bufferOffset = i * bufferSize; NSInteger charsInBuffer = MIN(length - bufferOffset, bufferSize); [self getCharacters:buffer range:NSMakeRange(bufferOffset, charsInBuffer)]; for (int j = 0; j < charsInBuffer; j++) { block(buffer[j], j + bufferOffset, &stop); if (stop) { return; } } } }
我不认为你可以做到这一点。 NSString
是许多类的抽象接口,不能保证字符数据的内部存储,所以完全有可能没有字符数组来获取指针。
如果在你的问题中提到的选项都不适合你的应用程序,我build议为此创build自己的string类,或使用原始的malloc'ed unichar数组而不是string对象。
这将工作:
char *s = [string UTF8String]; for (char *t = s; *t; t++) /* use as */ *t;
[编辑]如果你真的需要unicode字符,那么你别无select,只能使用长度和characterAtIndex 。 从文档:
NSString类有两个基本的方法 – length和characterAtIndex: – 为接口中的所有其他方法提供基础。 length方法返回string中的Unicode字符总数。 characterAtIndex:通过索引给出string中每个字符的访问权限,索引值从0开始。
所以你的代码是:
for (int index = 0; index < string.length; index++) { unichar c = [string characterAtIndex: index]; /* ... */ }
编辑2
此外,不要忘记,NSString是“免费桥接”到CFString,因此所有非Objective-C,直接的C代码接口函数都是可用的。 相关的将是CFStringGetCharacterAtIndex