7

の内容をシャッフルするこの関数を作成しましたが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;
}
4

2 に答える 2

11

char配列を使用しない@dreamlaxのコードの変形。確かにそれほど効率的ではありません。ただし、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];
}
于 2011-09-01T21:58:50.467 に答える
9

たくさんの小さな文字列を作成するのではなく、文字列の内容をタイプの一時バッファにコピーして、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文字列には、複合文字とサロゲートペアを含めることができます。これらをシャッフルすると、文字列が無効になる可能性があります。サロゲートペアはまれですが、文字éが2つの文字(ベース小文字のeとアキュートアクセントの組み合わせ)で構成されていることは珍しくありません。

  2. 大きな文字列の場合、元の文字列の3倍のスペース(元の文字列の場合は1倍、使用するバッファの場合は2倍、新しい文字列の場合は3倍)を使用してから元に戻すため、メモリの問題が発生する可能性があります。バッファを解放したら2倍に)。

于 2010-09-10T06:45:19.727 に答える