Обратный текст NSString

Я так много разбираюсь в том, как это сделать, но как я могу изменить NSString? Пример: hi станет: ih

Я ищу самый простой способ сделать это.

Благодаря!

@Vince я сделал этот метод:

- (IBAction)doneKeyboard { // first retrieve the text of textField1 NSString *myString = field1.text; NSMutableString *reversedString = [NSMutableString string]; NSUInteger charIndex = 0; while(myString && charIndex < [myString length]) { NSRange subStrRange = NSMakeRange(charIndex, 1); [reversedString appendString:[myString substringWithRange:subStrRange]]; charIndex++; } // reversedString is reversed, or empty if myString was nil field2.text = reversedString; } 

Я подключил этот метод к didendonexit textfield1. Когда я нажимаю кнопку «Готово», она не отменяет текст, UILabel просто показывает текст UITextField, который я ввел. Что не так?

Напишите простой цикл для этого:

 // myString is "hi" NSMutableString *reversedString = [NSMutableString string]; NSInteger charIndex = [myString length]; while (charIndex > 0) { charIndex--; NSRange subStrRange = NSMakeRange(charIndex, 1); [reversedString appendString:[myString substringWithRange:subStrRange]]; } NSLog(@"%@", reversedString); // outputs "ih" 

В твоем случае:

 // first retrieve the text of textField1 NSString *myString = textField1.text; NSMutableString *reversedString = [NSMutableString string]; NSInteger charIndex = [myString length]; while (myString && charIndex > 0) { charIndex--; NSRange subStrRange = NSMakeRange(charIndex, 1); [reversedString appendString:[myString substringWithRange:subStrRange]]; } // reversedString is reversed, or empty if myString was nil textField2.text = reversedString; 

Блочная версия.

 NSString *myString = @"abcdefghijklmnopqrstuvwxyz"; NSMutableString *reversedString = [NSMutableString stringWithCapacity:[myString length]]; [myString enumerateSubstringsInRange:NSMakeRange(0,[myString length]) options:(NSStringEnumerationReverse | NSStringEnumerationByComposedCharacterSequences) usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { [reversedString appendString:substring]; }]; // reversedString is now zyxwvutsrqponmlkjihgfedcba 

Ответ jano правильный. К сожалению, он создает много ненужных временных объектов. Вот гораздо более быстрая (более сложная) реализация, которая в основном делает то же самое, но использует memcpy и unichar buffers, чтобы свести ограничения памяти к минимуму.

 - (NSString *)reversedString { NSUInteger length = [self length]; if (length < 2) { return self; } unichar *characters = calloc(length, sizeof(unichar)); unichar *reversedCharacters = calloc(length, sizeof(unichar)); if (!characters || !reversedCharacters) { free(characters); free(reversedCharacters); return nil; } [self getCharacters:characters range:NSMakeRange(0, length)]; NSUInteger i = length - 1; NSUInteger copiedCharacterCount = 0; // Starting from the end of self, copy each composed character sequence into reversedCharacters while (copiedCharacterCount < length) { NSRange characterRange = [self rangeOfComposedCharacterSequenceAtIndex:i]; memcpy(reversedCharacters + copiedCharacterCount, characters + characterRange.location, characterRange.length * sizeof(unichar)); i = characterRange.location - 1; copiedCharacterCount += characterRange.length; } free(characters); NSString *reversedString = [[NSString alloc] initWithCharactersNoCopy:reversedCharacters length:length freeWhenDone:YES]; if (!reversedString) { free(reversedCharacters); } return reversedString; } 

Я тестировал это на 100 000 случайных многобайтовых строк Unicode с длиной от 1 до 128. Эта версия примерно в 4-5 раз быстрее, чем у jano.

 Enumerate substrings: 2.890528 MemCopy: 0.671090 Enumerate substrings: 2.840411 MemCopy: 0.662882 

Тестовый код находится на странице https://gist.github.com/prachigauriar/9739805 .

Обновление . Я попробовал это снова, просто переведя его в буфер UTF-32 и изменив его.

 - (NSString *)qlc_reversedStringWithUTF32Buffer { NSUInteger length = [self length]; if (length < 2) { return self; } NSStringEncoding encoding = NSHostByteOrder() == NS_BigEndian ? NSUTF32BigEndianStringEncoding : NSUTF32LittleEndianStringEncoding; NSUInteger utf32ByteCount = [self lengthOfBytesUsingEncoding:encoding]; uint32_t *characters = malloc(utf32ByteCount); if (!characters) { return nil; } [self getBytes:characters maxLength:utf32ByteCount usedLength:NULL encoding:encoding options:0 range:NSMakeRange(0, length) remainingRange:NULL]; NSUInteger utf32Length = utf32ByteCount / sizeof(uint32_t); NSUInteger halfwayPoint = utf32Length / 2; for (NSUInteger i = 0; i < halfwayPoint; ++i) { uint32_t character = characters[utf32Length - i - 1]; characters[utf32Length - i - 1] = characters[i]; characters[i] = character; } return [[NSString alloc] initWithBytesNoCopy:characters length:utf32ByteCount encoding:encoding freeWhenDone:YES]; } 

Это примерно в 3-4 раза быстрее, чем версия memcpy. Вышеупомянутая спецификация была обновлена ​​с последней версией кода.

 Enumerate substrings: 2.168705 MemCopy: 0.488320 UTF-32: 0.150822 Enumerate substrings: 2.169655 MemCopy: 0.481786 UTF-32: 0.147534 Enumerate substrings: 2.248812 MemCopy: 0.505995 UTF-32: 0.154531 

Я подумал, что я бы выбрал другую версию там, если кто-то заинтересован. Лично мне нравится более чистый подход, использующий NSMutableString, но если производительность является наивысшим приоритетом, это быстрее:

 - (NSString *)reverseString:(NSString *)input { NSUInteger len = [input length]; unichar *buffer = malloc(len * sizeof(unichar)); if (buffer == nil) return nil; // error! [input getCharacters:buffer]; // reverse string; only need to loop through first half for (NSUInteger stPos=0, endPos=len-1; stPos < len/2; stPos++, endPos--) { unichar temp = buffer[stPos]; buffer[stPos] = buffer[endPos]; buffer[endPos] = temp; } return [[NSString alloc] initWithCharactersNoCopy:buffer length:len freeWhenDone:YES]; } 

Я также написал быстрый тест, чтобы сравнить его с более традиционным методом NSMutableString (который я также включил ниже):

 // test reversing a really large string NSMutableString *string = [NSMutableString new]; for (int i = 0; i < 10000000; i++) { int digit = i % 10; [string appendFormat:@"%d", digit]; } NSTimeInterval startTime = [[NSDate date] timeIntervalSince1970]; NSString *reverse = [self reverseString:string]; NSTimeInterval elapsedTime = [[NSDate date] timeIntervalSince1970] - startTime; NSLog(@"reversed in %f secs", elapsedTime); 

Результаты:

  • используя метод NSMutableString (ниже) - «отменено в 3.720631 сек»

  • используя метод unichar * buffer (выше) - «отменено в 0.032604 сек»

Для справки, здесь используется метод NSMutableString, используемый для этого сравнения:

 - (NSString *)reverseString:(NSString *)input { NSUInteger len = [input length]; NSMutableString *result = [[NSMutableString alloc] initWithCapacity:len]; for (int i = len - 1; i >= 0; i--) { [result appendFormat:@"%c", [input characterAtIndex:i]]; } return result; } 

Использовать метод с любыми объектами: NSString, NSNumber и т. Д.:

 NSLog(@"%@",[self reverseObject:@12345]); NSLog(@"%@",[self reverseObject:@"Hello World"]); 

Метод:

 -(NSString*)reverseObject:(id)string{ string = [NSString stringWithFormat:@"%@",string]; NSMutableString *endString = [NSMutableString new]; while ([string length]!=[endString length]) { NSRange range = NSMakeRange([string length]-[endString length]-1, 1); [endString appendString: [string substringWithRange:range]]; } return endString;} 

Журнал:

 2014-04-16 11:20:25.312 TEST[23733:60b] 54321 2014-04-16 11:20:25.313 TEST[23733:60b] dlroW olleH 

Было бы быстрее, если бы вы только повторили более половины строки, заменяя символы на каждом конце? Итак, для строки с 5 символами вы меняете символы 1 + 5, затем 2 + 4 и 3 не нуждаются в замене.

 NSMutableString *reversed = [original mutableCopyWithZone:NULL]; NSUInteger i, length; length = [reversed length]; for (i = 0; i < length / 2; i++) { // Store the first character as we're going to replace with the character at the end // in the example, it would store 'h' unichar startChar = [reversed characterAtIndex:i]; // Only make the end range once NSRange endRange = NSMakeRange(length - i, 1); // Replace the first character ('h') with the last character ('i') // so reversed now contains "ii" [reversed replaceCharactersInRange:NSMakeRange(i, 1) withString:[reversed subStringWithRange:endRange]; // Replace the last character ('i') with the stored first character ('h) // so reversed now contains "ih" [reversed replaceCharactersInRange:endRange withString:[NSString stringWithFormat:@"%c", startChar]]; } 

редактировать ----

Проведя некоторые тесты, ответ «Нет», примерно в 6 раз медленнее, чем версия, которая перебирает все. Вещь, которая замедляет нас, создает временные NSStrings для метода replaceCharactersInRange: withString. Вот метод, который создает только одну NSString, манипулируя символьными данными напрямую и в простых тестах намного быстрее.

 NSUInteger length = [string length]; unichar *data = malloc(sizeof (unichar) * length); int i; for (i = 0; i < length / 2; i++) { unichar startChar = [string characterAtIndex:i]; unichar endChar = [string characterAtIndex:(length - 1) - i]; data[i] = endChar; data[(length - 1) - i] = startChar; } NSString *reversed = [NSString stringWithCharacters:data length:length]; free(data); 

Swift 2.0:

1) пусть str = «Привет, мир!» let reverseed = String (str.characters.reverse ()) print (reverse)

Вкратце:

 String("This is a test string.".characters.reverse()) 

2)

 let string = "This is a test string." let characters = string.characters let reversedCharacters = characters.reverse() let reversedString = String(reversedCharacters) 

Короткий путь:

 String("This is a test string.".characters.reverse()) 

ИЛИ

 let string = "This is a test string." let array = Array(string) let reversedArray = array.reverse() let reversedString = String(reversedArray) The short way : String(Array("This is a test string.").reverse()) 

Протестировано на игровой площадке:

 import Cocoa //Assigning a value to a String variable var str = "Hello, playground" //Create empty character Array. var strArray:Character[] = Character[]() //Loop through each character in the String for character in str { //Insert the character in the Array variable. strArray.append(character) } //Create a empty string var reversedStr:String = "" //Read the array from backwards to get the characters for var index = strArray.count - 1; index >= 0;--index { //Concatenate character to String. reversedStr += strArray[index] } 

Более короткая версия:

 var str = “Hello, playground” var reverseStr = “” for character in str { reverseStr = character + reverseStr } 

Переверните строку с помощью рекурсии:

 @implementation NSString (Reversed) + (NSString *)reversedStringFromString:(NSString *)string { NSUInteger count = [string length]; if (count <= 1) { // Base Case return string; } else { NSString *lastLetter = [string substringWithRange:NSMakeRange(count - 1, 1)]; NSString *butLastLetter = [string substringToIndex:count - 1]; return [lastLetter stringByAppendingString:[self reversedStringFromString:butLastLetter]]; } } @end 

Ни один из ответов не рассматривает многобайтовые символы, поэтому здесь приведен пример кода. Предполагается, что вы только когда-либо проходите в строке длиной более одного символа.

 - (void)testReverseString:(NSString *)string { NSMutableString *rString = [NSMutableString new]; NSInteger extractChar = [string length] - 1; while (extractChar >= 0) { NSRange oneCharPos = [string rangeOfComposedCharacterSequenceAtIndex:extractChar]; for (NSUInteger add = 0; add < oneCharPos.length; ++ add) { unichar oneChar = [string characterAtIndex:oneCharPos.location + add]; [rString appendFormat:@"%C", oneChar]; } extractChar -= oneCharPos.length; } NSLog(@"%@ becomes %@", string, encryptedString ); } 
  • NSString в char utf32 (всегда 32 бита (unsigned int))
  • Задний ход
  • char utf32 в NSString

 + (NSString *)reverseString3:(NSString *)str { unsigned int *cstr, buf, len = [str length], i; cstr = (unsigned int *)[str cStringUsingEncoding:NSUTF32LittleEndianStringEncoding]; for (i=0;i < len/2;i++) buf = cstr[i], cstr[i] = cstr[len -i-1], cstr[len-i-1] = buf; return [[NSString alloc] initWithBytesNoCopy:cstr length:len*4 encoding:NSUTF32LittleEndianStringEncoding freeWhenDone:NO]; } 

Пример: Apple_is  --->  si_elppA

 NSMutableString *result = [NSMutableString stringWithString:@""]; for (long i = self.length - 1; i >= 0; i--) { [result appendFormat:@"%c", [self characterAtIndex:i]]; } return (NSString *)result; 

Google – ваш друг :

 -(NSString *) reverseString { NSMutableString *reversedStr; int len = [self length]; // Auto released string reversedStr = [NSMutableString stringWithCapacity:len]; // Probably woefully inefficient... while (len > 0) [reversedStr appendString: [NSString stringWithFormat:@"%C", [self characterAtIndex:--len]]]; return reversedStr; } 

Вот набор категорий в Objective-C, который будет отменять как NSStrings, так и NSAttributedStrings (при сохранении атрибутов символов): TextFlipKit

Например:

 NSString *example = @"Example Text"; NSString *reversed = example.tfk_reversed; NSLog(@"Reversed: %@", reversed); //prints 'Reversed: txeT elpmaxE' 

Swift:

 let string = "reverse" let reversedStringCollection = string.characters.reversed() for character in reversedStringCollection { reversedString.append(character) print(reversedString) } 

Мы также можем получить обратную строку следующим образом.

 NSString *originalString = @"Hello"; NSString *reverseString; for (NSUInteger index = originalString.length; index > 0; index--) { char character = [originalString characterAtIndex:index]; reverseString = [reverseString stringByAppendingString:[NSString stringWithFormat:@"%c", character]]; } 

или

 NSString *originalString = @"Hello"; NSString *reverseString; for (NSUInteger index = originalString.length; index > 0; index--) { char *character = [originalString characterAtIndex:index]; reverseString = [reverseString stringByAppendingString:[NSString stringWithFormat:@"%s", character]]; } 

Добавьте категорию в NSString, чтобы в будущем можно было называть обратный вызов любой NSString следующим образом:

 #import "NSString+Reverse.h" @implementation NSString (Reverse) -(NSString*)reverse { char* cstring = (char*)[self UTF8String]; int length = [self length]-1; int i=0; while (i<=length) { unichar tmp = cstring[i]; cstring[i] = cstring[length]; cstring[length] = tmp; i++; length--; } return [NSString stringWithCString:cstring encoding:NSUTF8StringEncoding]; } @end 
 [email protected]"india is my countery"; array1=[[NSMutableArray alloc] init]; for(int i =0 ;i<[str length]; i++) { NSString *singleCharacter = [NSString stringWithFormat:@"%c", [str characterAtIndex:i]]; [array1 addObject:singleCharacter]; } NSMutableString* theString = [NSMutableString string]; for (int i=[array1 count]-1; i>=0;i--){ [theString appendFormat:@"%@",[array1 objectAtIndex:i]]; } 

Я написал категорию ove, что один: D

//NSString+Reversed.h #import

 // // NSString+Reversed.h // HTMLPageFormatter // Created by beit46 on 21.06.13. // @interface NSString (Reversed) - (NSString *)reversedString; @end 

//NSString+Reversed.m

 // // NSString+Reversed.m // HTMLPageFormatter // Created by beit46 on 21.06.13. #import "NSString+Reversed.h" @implementation NSString (Reversed) - (NSString *)reversedString { NSMutableString *reversedString = [NSMutableString stringWithCapacity:[self length]]; [self enumerateSubstringsInRange:NSMakeRange(0,[self length]) options:(NSStringEnumerationReverse | NSStringEnumerationByComposedCharacterSequences) usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { [reversedString appendString:substring]; }]; return [reversedString copy]; } @end 

Для этого у меня есть два простых решения:

 +(NSString*)reverseString:(NSString *)str { NSMutableString* reversed = [NSMutableString stringWithCapacity:str.length]; for (int i = (int)str.length-1; i >= 0; i--){ [reversed appendFormat:@"%c", [str characterAtIndex:i]]; } return reversed; } +(NSString*)reverseString2:(NSString *)str { char* cstr = (char*)[str UTF8String]; int len = (int)str.length; for (int i = 0; i < len/2; i++) { char buf = cstr[i]; cstr[i] = cstr[len-i-1]; cstr[len-i-1] = buf; } return [[NSString alloc] initWithBytes:cstr length:len encoding:NSUTF8StringEncoding]; } 

Теперь давайте протестируем его!

 NSString* str = @"Objective-C is a general-purpose, object-oriented programming language that adds Smalltalk-style messaging to the C programming language"; NSLog(@"REV 1: %@", [Util reverseString:str]); start = [NSDate date]; for (int i = 0 ; i < 1000; ++i) [Util reverseString:str]; end = [NSDate date]; NSLog(@"Time per 1000 repeats: %f", [end timeIntervalSinceDate:start]); NSLog(@"REV 2: %@", [Util reverseString2:str]); start = [NSDate date]; for (int i = 0 ; i < 1000; ++i) [Util reverseString2:str]; end = [NSDate date]; NSLog(@"Time per 1000 repeats: %f", [end timeIntervalSinceDate:start]); 

Результаты:

 ConsoleTestProject[68292:303] REV 1: egaugnal gnimmargorp C eht ot gnigassem elyts-klatllamS sdda taht egaugnal gnimmargorp detneiro-tcejbo ,esoprup-lareneg a si C-evitcejbO ConsoleTestProject[68292:303] Time per 1000 repeats: 0.063880 ConsoleTestProject[68292:303] REV 2: egaugnal gnimmargorp C eht ot gnigassem elyts-klatllamS sdda taht egaugnal gnimmargorp detneiro-tcejbo ,esoprup-lareneg a si C-evitcejbO ConsoleTestProject[68292:303] Time per 1000 repeats: 0.002038 

И еще результат был:

 ConsoleTestProject[68322:303] chars: 1982 ConsoleTestProject[68322:303] Time 1 per 1000 repeats: 1.014893 ConsoleTestProject[68322:303] Time 2 per 1000 repeats: 0.024928 

Тот же текст с вышеуказанными функциями:

 ConsoleTestProject[68366:303] Time 1 per 1000 repeats: 0.873574 ConsoleTestProject[68366:303] Time 2 per 1000 repeats: 0.019300 ConsoleTestProject[68366:303] Time 3 per 1000 repeats: 0.342735 <-Vladimir Gritsenko ConsoleTestProject[68366:303] Time 4 per 1000 repeats: 0.584012 <- Jano 

Итак, выберите производительность!

 -(NSString *) reverseString: (NSString *) string { NSMutableArray *letters = [[NSMutableArray alloc] init]; for (int i=0; i<[string length]; i++) [letters addObject: [string substringWithRange: NSMakeRange(i, 1)]]; NSArray *reversed = [[letters reverseObjectEnumerator] allObjects]; return [reversed componentsJoinedByString: @""]; } 
  • В чем разница между и nil?
  • Код примера Objective-C для HMAC-SHA1
  • Должен ли я использовать свойства или прямую ссылку при доступе к переменным экземпляра внутри?
  • Префикс имен свойств с подчеркиванием в Objective C
  • Декодирование символов UTF8 в Objective C
  • Objective C - получение номера строки или полной трассировки стека из-за ошибки отладчика?
  • Разделить NSString для доступа к одной конкретной части
  • Как разбить строковый литерал на несколько строк в C / Objective-C?
  • Каков наилучший способ поместить c-struct в NSArray?
  • Calling -retainCount считается вредным
  • Как создать хеш-файл MD5 в Cocoa?
  • Давайте будем гением компьютера.