代码之家  ›  专栏  ›  技术社区  ›  jkeesh

在objective-c中,在nsstring中洗牌字母

  •  6
  • jkeesh  · 技术社区  · 14 年前

    我已经编写了这个函数,它对 NSString 它似乎起作用,但偶尔会崩溃。这可能是一种迂回的方式,但我将字符放入数组,随机交换数组中的元素,然后将数组转换回字符串。

    我不知道我在做什么,这是不安全的,这使它崩溃。我以为可能是我在安排 finalLettersString = result 但是我也试过了 finalLettersString = [NSString stringWithString:result] 也会崩溃。我困惑的原因是它不会每次都崩溃。我只是不停地按“随机播放”按钮,有时它会崩溃。我该去什么地方看看?

    /* This function shuffles the letters in the string finalLettersString */
    
    -(IBAction)shuffleLetters:(id)sender{
        int length = [finalLettersString length];
        NSMutableArray * letters = [NSMutableArray arrayWithCapacity:length]; 
        NSLog(@"final letters: %@", finalLettersString);
        for(int i = 0; i < length; i++){
            char ch = [finalLettersString characterAtIndex:i];
            NSLog(@"%c", ch);
            NSString * cur = [NSString stringWithFormat:@"%c", ch];
            [letters insertObject:cur atIndex:i];
        }
    
        NSLog(@"LETTERS:: %@", letters);
    
        for(int i = length - 1; i >= 0; i--){
            int j = arc4random() % (i + 1);
            //NSLog(@"%d %d", i, j);
            //swap at positions i and j
            NSString * str_i = [letters objectAtIndex:i];
            [letters replaceObjectAtIndex:i withObject:[letters objectAtIndex:j]];
            [letters replaceObjectAtIndex:j withObject:str_i];      
        }
        NSLog(@"NEW SHUFFLED LETTERS %@", letters);
    
        NSString * result = @"";
        for(int i = 0; i < length; i++){
            result = [result stringByAppendingString:[letters objectAtIndex:i]];
        }
    
        NSLog(@"Final string: %@", result);
        finalLettersString = result;
        finalLetters.text = finalLettersString;
    }
    
    2 回复  |  直到 13 年前
        1
  •  8
  •   dreamlax    14 年前

    最好将字符串的内容复制到类型为的临时缓冲区中。 unichar 并无序处理缓冲区的内容,而不是创建大量的小字符串。

    NSUInteger length = [finalLettersString length];
    
    if (!length) return; // nothing to shuffle    
    
    unichar *buffer = calloc(length, sizeof (unichar));
    
    [finalLettersString getCharacters:buffer range:NSMakeRange(0, length)];
    
    for(int i = length - 1; i >= 0; i--){
        int j = arc4random() % (i + 1);
        //NSLog(@"%d %d", i, j);
        //swap at positions i and j
        unichar c = buffer[i];
        buffer[i] = buffer[j];
        buffer[j] = c;
    }
    
    NSString *result = [NSString stringWithCharacters:buffer length:length];
    free(buffer);
    
    // caution, autoreleased. Allocate explicitly above or retain below to
    // keep the string.
    finalLettersString = result;
    

    你必须注意以下几点:

    1. Unicode字符串可以包含复合字符和代理项对。在这些地方乱摆弄很可能会导致一个无效的字符串。虽然代理对很少见,但发现字符_)由两个字符(小写字母e和组合的锐音符)组成并不少见。

    2. 对于大字符串,它可能会导致内存问题,因为您最终使用的空间是原始字符串的3倍(1_表示原始字符串,2_表示我们使用的缓冲区,3_表示新字符串,然后在释放缓冲区后返回到2_)。

        2
  •  11
  •   pixelfreak    13 年前

    @dreamlax代码的一个变体,不使用char数组。当然没有效率高。但它没有unicode问题。

    NSMutableString *randomizedText = [NSMutableString stringWithString:currentText];
    
    NSString *buffer;
    for (NSInteger i = randomizedText.length - 1, j; i >= 0; i--)
    {
        j = arc4random() % (i + 1);
    
        buffer = [randomizedText substringWithRange:NSMakeRange(i, 1)];
        [randomizedText replaceCharactersInRange:NSMakeRange(i, 1) withString:[randomizedText substringWithRange:NSMakeRange(j, 1)]];
        [randomizedText replaceCharactersInRange:NSMakeRange(j, 1) withString:buffer];
    }