2010-09-10 8 views
6

में एनएसएसटींग में शफलिंग लेटर्स मैंने इस फ़ंक्शन को लिखा है जो NSString की सामग्री को shuffles करता है, और ऐसा लगता है, लेकिन हर अब और फिर यह दुर्घटनाग्रस्त हो जाता है। यह एक चौराहे का तरीका हो सकता है, लेकिन मैंने अक्षरों को सरणी में रखा है, तत्वों को सरणी में यादृच्छिक रूप से स्वैप करें, और फिर सरणी को स्ट्रिंग में वापस चालू करें।उद्देश्य-सी

मुझे यकीन नहीं है कि मैं क्या कर रहा हूं वह असुरक्षित है जो इसे दुर्घटनाग्रस्त कर देता है। मैंने सोचा कि यह संभवतः है कि मैं 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; 
} 

उत्तर

8

बेहतर होगा बजाय छोटे तार के बहुत सारे बनाने के बजाय, प्रकार 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. यूनिकोड तार समग्र अक्षर और सरोगेट जोड़े हो सकते हैं। इन चारों ओर घूमने से सबसे अमान्य स्ट्रिंग में परिणाम होगा। जबकि सरोगेट जोड़े दुर्लभ होते हैं, यह पता लगाना असामान्य नहीं है कि चरित्र दो अक्षरों से बना है (आधार लोअरकेस अक्षर ई और संयोजन तीव्र उच्चारण)।

  2. बड़े तारों के लिए यह स्मृति समस्याओं का कारण बन सकता है क्योंकि आप मूल स्ट्रिंग के रूप में 3 गुना अधिक स्थान (मूल स्ट्रिंग के लिए 1 ×, 2 × बफर के लिए 2 × और नई स्ट्रिंग के लिए 3 × , और फिर हम बफर को मुक्त करने के बाद 2 × तक वापस आते हैं)।

+0

धन्यवाद! निश्चित रूप से एक बेहतर समाधान। वास्तव में एक समस्या यह थी कि आप NSUIntegers का उपयोग नहीं कर सकते हैं, क्योंकि 0 पर असीमित होने के बाद 0 पर वास्तव में बड़ी संख्या होती है और -1 नहीं होती है। मैं इसे स्याही और बनाए रखने का उपयोग करने के लिए मिल गया। इस स्थिति में, क्या आपको लगता है कि इसे बनाए रखने या स्पष्ट रूप से आवंटित करना बेहतर है? – jkeesh

+0

@jkeesh: हस्ताक्षरित पूर्णांक के बारे में अच्छा बिंदु। स्पष्ट रूप से आवंटित करने के संबंध में, यह लक्ष्य मंच पर निर्भर करता है। यदि आप आईफोन को लक्षित कर रहे हैं, तो कुछ लोग ऑटोरेलीज पूल से बचने के लिए कहते हैं, जब आप सुंदर तरीके से ऐसा कर सकते हैं, लेकिन मैक ओएस एक्स (यानी आईफोन की तुलना में अधिक मेमोरी वाले सिस्टम) के लिए यह कोई ध्यान देने योग्य अंतर नहीं देगा। निजी तौर पर, मैं हमेशा 'रखरखाव' के साथ 'ऑटोरेलीज' का मुकाबला करने के बजाय स्पष्ट रूप से आवंटित करता हूं, लेकिन परिणाम वही तरीका है। – dreamlax

+0

इस दिन और अंतर्राष्ट्रीयकरण की उम्र में, आप यह नहीं मान सकते कि एक यूनिकार नक्शा एक चरित्र में है। – JeremyP

11

@ dreamlax के कोड का एक संस्करण जो char array का उपयोग नहीं करता है। निश्चित रूप से कुशल नहीं है। लेकिन इसमें यूनिकोड मुद्दा नहीं है।

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]; 
}