各 unichar をプルして NSString を列挙するにはどうすればよいですか? characterAtIndex を使用できますが、それは unichar* をインクリメントするよりも遅くなります。Apple のドキュメントには、文字列を 2 番目のバッファにコピーする必要のないものは何もありませんでした。
次のようなものが理想的です。
for (unichar c in string) { ... }
また
unichar* ptr = (unichar*)string;
各 unichar をプルして NSString を列挙するにはどうすればよいですか? characterAtIndex を使用できますが、それは unichar* をインクリメントするよりも遅くなります。Apple のドキュメントには、文字列を 2 番目のバッファにコピーする必要のないものは何もありませんでした。
次のようなものが理想的です。
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++;
}
バッファを処理するためにメモリを割り当てたくない場合は、これが方法です。
唯一のオプションは、文字を新しいバッファにコピーすることです。これは、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];
}
非常に長い可能性のある文字列を使用している場合は、固定サイズのバッファを割り当てて、文字列をチャンクで列挙することをお勧めします(これは実際には列挙が機能する速度です)。
getCharacters:range:彼の回答でのughoavgfhwの提案に従って、固定サイズのバッファを使用するブロックスタイルの列挙メソッドを作成しました。null を返す状況を回避しCFStringGetCharactersPtr、大きなバッファーを malloc する必要はありません。必要に応じて、NSString カテゴリにドロップするか、パラメーターとして文字列を取るように変更できます。
-(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は、文字データの内部ストレージについて保証しない多数のクラスへの抽象インターフェイスであるため、ポインタを取得する文字配列がない可能性があります。
質問で言及されているオプションのどちらもアプリに適していない場合は、この目的のために独自の文字列クラスを作成するか、文字列オブジェクトの代わりに生のmallocされたunichar配列を使用することをお勧めします。
これはうまくいきます:
char *s = [string UTF8String];
for (char *t = s; *t; t++)
/* use as */ *t;
[編集] Unicode 文字が本当に必要な場合は、lengthとcharacterAtIndexを使用する以外に選択肢はありません。ドキュメントから:
NSString クラスには、length と characterAtIndex: という 2 つのプリミティブ メソッドがあり、そのインターフェイスの他のすべてのメソッドの基礎を提供します。length メソッドは、文字列内の Unicode 文字の総数を返します。characterAtIndex: 0 から始まるインデックス値を使用して、文字列内の各文字にインデックスでアクセスできます。
したがって、コードは次のようになります。
for (int index = 0; index < string.length; index++)
{
unichar c = [string characterAtIndex: index];
/* ... */
}
[編集2]
また、NSString は CFString に「無料でブリッジ」されていることを忘れないでください。したがって、Objective-C 以外のすべてのストレート C コード インターフェイス関数を使用できます。関連するものはCFStringGetCharacterAtIndex