Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 迭代NSString中所有字符的最有效方法_Objective C - Fatal编程技术网

Objective c 迭代NSString中所有字符的最有效方法

Objective c 迭代NSString中所有字符的最有效方法,objective-c,Objective C,迭代NSString中所有字符的最佳方法是什么?是否要在字符串长度上循环并使用该方法 [aNSString characterAtIndex:index]; 或者,您想使用基于NSString的字符缓冲区吗?我肯定会先得到一个字符缓冲区,然后在上面迭代 NSString *someString = ... unsigned int len = [someString length]; char buffer[len]; //This way: strncpy(buffer, [someSt

迭代NSString中所有字符的最佳方法是什么?是否要在字符串长度上循环并使用该方法

[aNSString characterAtIndex:index];

或者,您想使用基于NSString的字符缓冲区吗?

我肯定会先得到一个字符缓冲区,然后在上面迭代

NSString *someString = ...

unsigned int len = [someString length];
char buffer[len];

//This way:
strncpy(buffer, [someString UTF8String]);

//Or this way (preferred):

[someString getCharacters:buffer range:NSMakeRange(0, len)];

for(int i = 0; i < len; ++i) {
   char current = buffer[i];
   //do something with current...
}
NSString*someString=。。。
无符号整数长度=[someString长度];
字符缓冲区[len];
//这样:
strncpy(缓冲区,[someString UTF8String]);
//或通过这种方式(首选):
[someString getCharacters:缓冲区范围:NSMakerRange(0,len)];
对于(int i=0;i
两者都不是。委员会建议:

如果您想在 字符串的字符,其中一个 你不应该做的事情是使用
characterAtIndex:
要检索的方法 每个字符分别显示。这种方法 不是为重复访问而设计的。 取而代之的是考虑取回 使用
getCharacters:范围:
方法和 直接迭代字节

如果要在字符串中搜索 特定字符或子字符串,是否 不遍历一个字符 一个接一个。相反,使用更高的级别 方法,例如
rangeOfString:
rangeOfCharacterFromSet:
,或
substringWithRange:
,它们是 优化搜索
NSString
人物


查看此示例,了解如何让
rangeOfCharacterFromSet:
迭代字符串中的字符,而不是自己进行迭代。

我认为人们了解如何处理unicode很重要,因此我最终以tl的精神编写了一个怪物答案;dr我将从一个应该可以正常工作的片段开始。如果你想知道细节(你应该知道!),请在片段之后继续阅读

NSUInteger len = [str length];
unichar buffer[len+1];

[str getCharacters:buffer range:NSMakeRange(0, len)];

NSLog(@"getCharacters:range: with unichar buffer");
for(int i = 0; i < len; i++) {
  NSLog(@"%C", buffer[i]);
}
另一方面,如果您想在字符串中的字节上迭代,那么它开始变得复杂,结果将完全取决于您选择使用的编码。不错的默认选择是UTF8,这就是我要展示的

要执行此操作,您必须计算出生成的UTF8字符串的字节数,这一步很容易出错,并使用字符串的
-长度
。这很容易出错的一个主要原因,特别是对于美国开发人员来说,是一个字母落入7位ASCII频谱的字符串将具有相等的字节和字母长度。这是因为UTF8用一个字节对7位ASCII字母进行编码,所以一个简单的测试字符串和基本英文文本可能工作得很好

正确的方法是使用方法
-lengthofBytes usingencoding:NSUTF8StringEncoding
(或其他编码),分配具有该长度的缓冲区,然后使用
-cStringUsingEncoding:
将字符串转换为相同的编码,并将其复制到该缓冲区。此处的示例代码:

NSUInteger byteLength = [str lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
char proper_c_buffer[byteLength+1];
strncpy(proper_c_buffer, [str cStringUsingEncoding:NSUTF8StringEncoding], byteLength);

NSLog(@"strncpy with proper length");
for(int i = 0; i < byteLength; i++) {
  NSLog(@"%c", proper_c_buffer[i]);
}

虽然从技术上讲,您将获得单个NSString值,但有一种替代方法:

NSRange range = NSMakeRange(0, 1);
for (__unused int i = range.location; range.location < [starring length]; range.location++) {
  NSLog(@"%@", [aNSString substringWithRange:range]);
}
NSRange range=NSMakeRange(0,1);
对于(_unused int i=range.location;range.location<[starring length];range.location++){
NSLog(@“%@,[aNSString substringWithRange:range]);
}

(未使用的int i
位是使编译器警告静音所必需的。)

虽然Daniel的解决方案可能大部分时间都有效,但我认为解决方案取决于上下文。例如,我有一个拼写应用程序,需要在每个字符出现在屏幕上时对其进行迭代,这可能与它在内存中的表示方式不一致。用户提供的文本尤其如此

在NSString上使用类似于此类别的内容:

- (void) dumpChars
{
    NSMutableArray  *chars = [NSMutableArray array];
    NSUInteger      len = [self length];
    unichar         buffer[len+1];

    [self getCharacters: buffer range: NSMakeRange(0, len)];
    for (int i=0; i<len; i++) {
        [chars addObject: [NSString stringWithFormat: @"%C", buffer[i]]];
    }

    NSLog(@"%@ = %@", self, [chars componentsJoinedByString: @", "]);
}
但它也可以很容易地产生:

mañana = m, a, n, ̃, a, n, a
如果字符串是预合成的unicode格式,则生成前者;如果字符串是分解格式,则生成后者

 e̊gâds = e, ̊, g, â, d, s
您可能认为可以通过使用NSString的precomposedStringWithCanonicalMapping或precomposedStringWithCompatibilityMapping的结果来避免这种情况,但这不一定是Apple在中警告的情况。例如,像
e̊g–ds
(完全由我编造)这样的字符串即使在转换为预合成形式后仍会生成以下内容

 e̊gâds = e, ̊, g, â, d, s
我的解决方案是使用NSString的EnumerateSubstringsRange传递NSStringEnumerationByComposedCharacterSequences作为枚举选项。将前面的示例改写为如下所示:

- (void) dumpSequences
{
    NSMutableArray  *chars = [NSMutableArray array];

    [self enumerateSubstringsInRange: NSMakeRange(0, [self length]) options: NSStringEnumerationByComposedCharacterSequences
        usingBlock: ^(NSString *inSubstring, NSRange inSubstringRange, NSRange inEnclosingRange, BOOL *outStop) {
        [chars addObject: inSubstring];
    }];

    NSLog(@"%@ = %@", self, [chars componentsJoinedByString: @", "]);
}
如果我们输入这个版本
e̊g–ds
,那么我们得到

e̊gâds = e̊, g, â, d, s
正如所料,这正是我想要的

关于的文档部分也可能有助于解释其中的一些内容


注意:看起来我使用的一些unicode字符串在格式化为代码时会出错。我使用的字符串是mañana和e̊g–ds

尝试使用块枚举字符串

创建NSString的类别

h

m

你不应该使用

NSUInteger len = [str length];
unichar buffer[len+1];
您应该使用内存分配

NSUInteger len = [str length];
unichar* buffer = (unichar*) malloc (len+1)*sizeof(unichar);
而最终的用途呢

free(buffer);

为了避免内存问题。

对于这个问题,这是一个不同的解决方案,但我认为这可能对某些人有用。我想要的是在NSString中作为实际的unicode字符进行迭代。因此,我找到了这个解决方案:


NSString*str=@“您好,这是一个不错的方法,但值得记住的是,沿着这些行对NSString进行的任何字符转换都会遇到一些非常棘手的多字节文本边缘情况,最好尽可能避免。(不幸的是,仅仅使用UTF-16或UTF-32还不足以解决所有国际文本的问题,尽管它会将您的内存需求推向月球。)你为什么要使用字符缓冲区呢?那么Chuck,还有什么选择呢?你是说使用characterAtIndex,尽管它很昂贵吗?这根本不是正确的方法,因为unicode字符的存储方式。检查@som
@interface NSString (Category)

- (void)enumerateCharactersUsingBlock:(void (^)(NSString *character, NSInteger idx, bool *stop))block;

@end
@implementation NSString (Category)

- (void)enumerateCharactersUsingBlock:(void (^)(NSString *character, NSInteger idx, bool *stop))block
{
    bool _stop = NO;
    for(NSInteger i = 0; i < [self length] && !_stop; i++)
    {
        NSString *character = [self substringWithRange:NSMakeRange(i, 1)];
        block(character, i, &_stop);
    }
}
@end
NSString *string = @"Hello World";
[string enumerateCharactersUsingBlock:^(NSString *character, NSInteger idx, bool *stop) {
        NSLog(@"char %@, i: %li",character, (long)idx);
}];
NSUInteger len = [str length];
unichar buffer[len+1];
NSUInteger len = [str length];
unichar* buffer = (unichar*) malloc (len+1)*sizeof(unichar);
free(buffer);