2009-02-23 5 views
10

Dire que j'ai un NSString (ou NSMutableString) contenant:La meilleure façon d'échapper à des personnages comme les nouvelles lignes et double citation dans NSString

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

Quelle est la meilleure façon de le transformer en:

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

Dois-je utiliser manuellement -replaceOccurrencesOfString:withString: encore et encore pour échapper des caractères, ou y a-t-il un moyen plus facile? Ces chaînes peuvent contenir des caractères d'autres alphabets/langues.

Comment cela se fait-il dans d'autres langages avec d'autres classes de chaînes?

+0

Je ne voudrais certainement pas utiliser manuellement cette méthode à plusieurs reprises.Il ne serait pas difficile d'écrire une méthode qui prend une série de remplacements tout à la fois. – Chuck

Répondre

4

Je ne pense pas qu'il existe une méthode intégrée pour "échapper" un ensemble particulier de caractères.

Si les caractères que vous souhaitez échapper sont bien définis, je m'en tiendrai probablement à la solution simple que vous avez proposée, en remplaçant grossièrement les instances des caractères. Nous vous avertissons que si votre chaîne source contient déjà des caractères échappés, vous voudrez probablement éviter de les "doubler". Une façon d'y parvenir serait de passer et de "désapparaître" toutes les chaînes de caractères échappées dans la chaîne avant de leur échapper à nouveau.

Si vous avez besoin de prendre en charge un ensemble variable de caractères échappés, consultez les méthodes NSScanner "scanUpToCharactersFromSet: intoString:" et "scanCharactersFromSet: intoString:". Vous pouvez utiliser ces méthodes sur NSScanner pour naviguer dans une chaîne, en copiant les parties de la section "scanUpTo" dans une chaîne mutable inchangée et en copiant les parties d'un jeu de caractères particulier uniquement après leur échappement.

+0

C'est beaucoup plus compliqué que je ne le pensais, mais ça marche bien. – dreamlax

0

Vous pourriez même vouloir vous pencher sur l'utilisation d'une bibliothèque regex (il y a beaucoup d'options disponibles, RegexKit est un choix populaire). Il ne devrait pas être trop difficile de trouver une regex pré-écrite pour échapper à des chaînes qui traitent des cas spéciaux comme des caractères échappés existants.

4

Cela s'échapper des guillemets doubles dans NSString:

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

Vous devez être prudent et échapper aussi le caractère d'échappement ...

5

stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding

3

Je pense que dans de tels cas, il est utile de travailler sur un caractère à la fois, soit dans UniChars ou UTF8 octets. Si vous utilisez UTF-8, alors vis(3) fera la plupart du travail pour vous (voir ci-dessous). Puis-je vous demander pourquoi vous voulez échapper un guillemet simple dans une chaîne entre guillemets? Comment envisagez-vous de gérer les caractères multi-octets? Dans l'exemple ci-dessous, j'utilise UTF-8, qui code les caractères 8 bits en utilisant des échappements octaux de style C. Cela peut également être annulé par 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

C'est un extrait que je l'ai utilisé dans le passé qui fonctionne très bien:

- (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]; 
} 
Questions connexes