JAHelia
JAHelia

Reputation: 7922

print a unicode NSString in reverse order

I have used this code to print an English NSString in reverse order:

     NSString *str = term;
    NSMutableArray *temp=[[NSMutableArray alloc] init];
    for(int i=0;i<[str length];i++)
    {
        [temp addObject:[NSString stringWithFormat:@"%c",[str characterAtIndex:i]]];
    }
    temp = [NSMutableArray arrayWithArray:[[temp reverseObjectEnumerator] allObjects]];
    NSString *reverseString=@"";
    for(int i=0;i<[temp count];i++)
    {
        reverseString=[NSString stringWithFormat:@"%@%@",reverseString,[temp objectAtIndex:i]];
    }
    NSLog(@"%@",reverseString);

but this code works only with English words, so when I try to use an Arabic word like this: تجريب the console will show random English characters.

how can I use this code to print the reversed version of the above word (and any other similar Arabic (unicode) strings) ?

Upvotes: 1

Views: 720

Answers (3)

Abizern
Abizern

Reputation: 150615

A Cocoa way of doing it:

NSString *originalString = @"تجريب";

NSUInteger stringLength = originalString.length;

NSMutableString *reversedString = [[NSMutableString alloc] initWithCapacity:stringLength];

while (stringLength) {
    [reversedString appendFormat:@"%C", [originalString characterAtIndex:--stringLength]];
}

NSLog(@"The reversed string is %@:", reversedString);

And this will work without leaking reversedString when compiled with ARC.

Upvotes: 2

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726569

You need to use %C (uppercase C) instead of %c (lowercase c) format specifier in the first call to stringWithFormat. The lowercase 'c' format specifier is for 8-bit characters; the uppercase 'C' is for unicode.

EDIT : If you want to do it more efficiently, copy the data into an array of unichar elements, reverse the array, and feed the result into another NSString. This lets you reverse the string in Length/2 steps:

NSString * s = @"تجريب";
unichar *cc = (unichar*)malloc(s.length+1);
[s getCharacters:cc];
for (NSUInteger i=0 ; i < s.length/2 ; i++) {
    // swap elements at i and s.length-i-1
    unichar tmp = cc[i];
    cc[i] = cc[s.length-i-1];
    cc[s.length-i-1] = tmp;
}
s = [NSString stringWithCharacters:cc length:s.length];
free(cc);
NSLog(@"%@", s);

Upvotes: 3

Fabian Kreiser
Fabian Kreiser

Reputation: 8337

You have two for loops there and this code is very inefficient. I'd use substringWithRange: instead of characterAtIndex: and append it directly to the output string by iterating backwards through the string:

- (NSString *) createReverseStringFromString:(NSString *)inputString {
    if (inputString.length <= 0)
        return inputString;

    NSMutableString *mutableReverseString = [[NSMutableString alloc] initWithCapacity:inputString.length];
    for (NSInteger i = inputString.length -1; i >= 0; i--) {
        NSString *characterString = [inputString substringWithRange:NSMakeRange(i, 1)];
        [mutableReverseString appendString:characterString];
    }

    NSString *outputString = [mutableReverseString copy];
    [mutableReverseString release];
    return [outputString autorelease];
}

You can then use this method like this:

NSString *inputString = @"تجريب";
NSString *outputString = [self createReverseStringFromString:inputString];

Upvotes: 2

Related Questions