Перемешивание букв в строке NSS в Objective-C - PullRequest
6 голосов
/ 10 сентября 2010

Я написал эту функцию, которая перетасовывает содержимое 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 ]

11 голосов
/ 02 сентября 2011

Вариант кода @ 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];
}
8 голосов
/ 10 сентября 2010

Было бы лучше скопировать содержимое строки во временный буфер типа 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 в нижнем регистре и комбинированный острый акцент).может вызвать проблемы с памятью, потому что вы в конечном итоге используете в 3 раза больше места, чем исходная строка (1 × для исходной строки, 2 × для буфера, который мы используем, и 3 × для новой строки, а затем обратно до 2 × один разосвобождаем буфер).

...