2009-02-23 11 views
10

Dire che ho un NSString (o NSMutableString) contenente:Il modo migliore per sfuggire personaggi come nuova riga e fare doppio citazione in NSString

I said "Hello, world!". 
He said "My name's not World." 

Qual è il modo migliore per trasformarla in:

I said \"Hello, world!\".\nHe said \"My name\'s not World.\" 

Devo utilizzare manualmente lo -replaceOccurrencesOfString:withString: per sfuggire ai caratteri o esiste un modo più semplice? Queste stringhe possono contenere caratteri di altri alfabeti/lingue.

Come è fatto in altre lingue con altre classi di stringhe?

+0

certamente non utilizzare manualmente che il metodo più e più volte.Non sarebbe difficile scrivere un metodo che prende una serie di sostituzioni tutte in una volta. – Chuck

risposta

4

Non penso che esista alcun metodo incorporato per "sfuggire" a un particolare gruppo di caratteri.

Se i personaggi che desideri scappare sono ben definiti, probabilmente mi attengo alla semplice soluzione che hai proposto, sostituendo le istanze dei personaggi in modo grossolano.

Si noti che se la stringa di origine contiene già caratteri di escape, è probabile che si desideri evitare di "eseguirne l'escape". Un modo per ottenere questo risultato è quello di analizzare e "rimuovere" le stringhe di caratteri di escape nella stringa prima di sfuggire nuovamente a tutte loro.

Se è necessario supportare un set variabile di caratteri di escape, osservare i metodi di NSScanner "scanUpToCharactersFromSet: intoString:" e "scanCharactersFromSet: intoString:". È possibile utilizzare questi metodi su NSScanner per navigare attraverso una stringa, copiando le parti dalla sezione "scanUpTo" in una stringa mutabile invariata e copiando le parti da un particolare set di caratteri solo dopo averle sfuggite.

+0

È molto più complicato di quanto pensassi dovesse essere, ma fa bene il lavoro. – dreamlax

0

Si potrebbe anche voler utilizzare una libreria di espressioni regolari (ci sono molte opzioni disponibili, RegexKit è una scelta popolare). Non dovrebbe essere troppo difficile trovare un'espressione regolare pre-scritta per evitare stringhe che gestiscono casi speciali come caratteri esistenti di escape.

4

Questa sfuggirà virgolette doppie in NSString:

NSString *escaped = [originalString stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]; 

quindi è necessario stare attenti e anche sfuggire il carattere di escape ...

5

stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding

3

Penso che in casi come questi, è utile operare su un personaggio alla volta, in UniChar o UTF8 byte. Se stai usando UTF-8, allora vis(3) farà la maggior parte del lavoro per te (vedi sotto). Posso chiederti perché vuoi evadere da una virgoletta singola all'interno di una stringa doppia citazione? Come pensate di gestire i caratteri multi-byte? Nell'esempio seguente, sto usando UTF-8, codificando caratteri a 8 bit usando gli escape ottali C-Style. Questo può anche essere annullato da unvis(3).

#import <Foundation/Foundation.h> 
#import <vis.h> 

@interface NSString (Escaping) 

- (NSString *)stringByEscapingMetacharacters; 

@end 

@implementation NSString (Escaping) 

- (NSString *)stringByEscapingMetacharacters 
{ 
    const char *UTF8Input = [self UTF8String]; 
    char *UTF8Output = [[NSMutableData dataWithLength:strlen(UTF8Input) * 4 + 1 /* Worst case */] mutableBytes]; 
    char ch, *och = UTF8Output; 

    while ((ch = *UTF8Input++)) 
     if (ch == '\'' || ch == '\'' || ch == '\\' || ch == '"') 
     { 
      *och++ = '\\'; 
      *och++ = ch; 
     } 
     else if (isascii(ch)) 
      och = vis(och, ch, VIS_NL | VIS_TAB | VIS_CSTYLE, *UTF8Input); 
     else 
      och+= sprintf(och, "\\%03hho", ch); 

    return [NSString stringWithUTF8String:UTF8Output]; 
} 

@end 

int 
main(int argc, const char *argv[]) 
{ 
    NSAutoreleasePool *pool = [NSAutoreleasePool new]; 

    NSLog(@"%@", [@"I said \"Hello, world!\".\nHe said \"My name's not World.\"" stringByEscapingMetacharacters]); 

    [pool drain]; 
    return 0; 
} 
2

Si tratta di un frammento che ho usato in passato che funziona abbastanza bene:

- (NSString *)escapeString:(NSString *)aString 
{ 
    NSMutableString *returnString = [[NSMutableString alloc] init]; 

    for(int i = 0; i < [aString length]; i++) { 

     unichar c = [aString characterAtIndex:i]; 

     // if char needs to be escaped 
     if((('\\' == c) || ('\'' == c)) || ('"' == c)) { 
      [returnString appendFormat:@"\\%c", c];    
     } else { 
      [returnString appendFormat:@"%c", c]; 
     } 
    } 

    return [returnString autorelease]; 
} 
Problemi correlati