【问题标题】:How would I decompose an NSString into individual characters?如何将 NSString 分解为单个字符?
【发布时间】:2024-01-01 12:10:01
【问题描述】:

所以我有一个将 NSString 作为参数的方法,我希望该方法基本上将字符串分解为单个字符并将它们存储在一个数组(NSArray)中。

换句话说,我想读取字符串中的每个字符并将各个字符以相同的顺序存储在一个数组中,以便以后处理各个字符。

有什么想法吗?

【问题讨论】:

    标签: iphone iphone-sdk-3.0 ios4


    【解决方案1】:

    遍历字符串,使用 characterAt - 并将每个字符附加到 NSMutableArray。

    但如果你这样做了 - 为什么还要把它们放在 NSArray 中呢?

    NSMutableArray *myArray = [[NSMutableArray] alloc] initWithCapacity:[string length]];
    
    for (i=0;i<[string length];i++) {
      unichaar ch;
      ch = [string  characterAtIndex:i];
      NSLog(@"Processing charachter %c",ch);
    
       // If you really want
      [myArray addObject:(id) ch];
    }
    

    【讨论】:

    • 是的,好点,我不妨边走边处理。非常感谢,我会试试看。
    • 更正:1) 它是unichar 2) [[NSMutableArray alloc] initWithCapacity: 将使用默认分配器。默认分配器假定id,并将发送保留/释放消息到 unichars - 当然会崩溃。您有两个选择:对每个字符使用 NSString,或者使用不对 unichars 执行引用计数的自定义分配器下拉分配 CFMutableArray
    • @Justin - 谢谢,是的,你的权利。 NSArray 是事后才想到的——因为,就像我建议的那样,他甚至不应该费心去需要它。
    • @Brad 是的 - 我也同意,与使用 unichar 相比,为每个字符使用/分配 NSString 会降低性能。有时这是微不足道的。在极少数情况下,单个 char NSStrings 数组很有用。
    • 也可以使用 -getCharacters:range: 将所有字符复制到 c 样式的 unichars 数组中,这可能比使用 -characterAtIndex: 单独提取字符更有效。不过,最好的解决方案可能是随时处理而不使用数组。
    【解决方案2】:

    我通常不会这么判断,但当前的答案会起作用……直到它们不起作用!

    在 ObjC/Foundation 中只有一种方法可以枚举实际的 Unicode 字符:

    - (void)enumerateSubstringsInRange:(NSRange)range options:(NSStringEnumerationOptions)opts usingBlock:(void (^)(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop))block
    

    使用选项

    NSStringEnumerationByComposedCharacterSequences
    

    这里的问题最好用表情符号来说明:

    ?(Unicode 名称:PILE OF PO,代码点:U+1F4A9)在表示为 UTF-16 Cocoa/Foundation/CoreFoundation 内部使用时为 0xD83DDCA9。使用其他方法,您将获得两个(损坏的、无效的)条目。

    如果您的字符串很长并且性能成为问题,但内存不是,您可以使用 UTF-32 并且您可以在恒定时间内再次访问您的字符。只需将它们存储在 C 数组或 C++ 向量中。或者只是将 32 位值包装在 NSNumber 中,如果性能不是那么关键,则使用 NSArray...

    我强烈建议通读 objc.io 问题 #9 中的 NSString and Unicode

    编辑 2016-05-15:在这种情况下,“角色”一词没有明确定义,可能会产生误导。我在上面所说的“字符”实际上是一个 Unicode 代码点。 Swift 在这里做了正确的事情,并将角色定义为“用户认为的角色”。

    【讨论】:

      【解决方案3】:

      除了 Brad 的回答(他表明,如果你愿意,你当然可以将每个字符存储在 NSArray 实例中),你还有更直接的机会将 NSString 值作为普通的旧 C null终止字符串。所以你可以像这样迭代它:

      char c;
      int i = 0;
      const char *buffer = [nsstringInstance cStringUsingEncoding:NSASCIIStringEncoding];
      while (c = buffer[i++]) {
          // iterating using c char
      
      }
      

      【讨论】:

      • 但是如果 NSString 包含非 ascii 字符,或者超过 1024 个字符怎么办?另请注意,-getCString: 自 iOS2.0 起已弃用。
      • @大卫:是的。将其更改为 cStringUsingEncoding。
      最近更新 更多