2009-07-30 7 views
7

Supposons que j'ai une méthode avec la signature:Quelle est la bonne façon d'encapsuler [NSString stringWithFormat:]?

+ (NSString *) myFormattedString:(NSString *)format, ...; 

Et je veux qu'il préfixer une chaîne de mon choix (par exemple @ « Foo: »). Je suppose que le meilleur moyen est d'utiliser [myString initWithFormat: arguments:], mais comment implémenteriez-vous cette méthode?


J'ai essayé de faire ce qui suit, mais je reçois l'avertissement comme indiqué dans le commentaire:

+ (NSString *) myFormattedString:(NSString *)format, ... { 
    char *buffer; 
    [format getCString:buffer maxLength:[format length] encoding:NSASCIIStringEncoding]; 

    va_list args; 
    va_start(args, buffer); // WARNING: second parameter of 'va_start' not last named argument 

    NSString *str = [[NSString alloc] initWithFormat:format arguments:args]; 
    [str autorelease]; 

    return [NSString stringWithFormat:@"Foo: %@.", str]; 
} 

La raison pour laquelle je suppose va_start() peut prendre dans un (char *) est à cause de l'exemple que j'ai vu sur le manual page of STDARG(3). N'hésitez pas à réécrire complètement la méthode si je le fais totalement faux.

Répondre

15

Je pense que ce que vous voulez est quelque chose comme:

+ (NSString *) myFormattedString:(NSString *)format, ... { 
    va_list args; 
    va_start(args, format); 
    NSString *str = [[[NSString alloc] initWithFormat:format arguments:args] autorelease]; 
    va_end(args); 
    return [NSString stringWithFormat:@"Foo: %@.", str]; 
} 

Les stdarg.hva_ * macros sont utilisées lorsqu'une fonction (ou, dans ce cas, la méthode) prend un nombre variable d'arguments, tel que spécifié par " ... ". va_start() est utilisé pour trouver le début de l'endroit où le nombre variable d'arguments commence. En tant que tel, il doit connaître un dernier argument fonctions/méthodes (celui juste avant le "...") afin de déterminer où commence le nombre variable d'arguments. C'est une explication quelque peu simplifiée car ce qui se passe réellement sous le capot est très spécifique à ABI/Compiler. Le point le plus important est que le deuxième argument à va_start() est toujours le nom de la variable 'juste avant le "..."'.

va_end() devrait être "appelé" (c'est vraiment une macro, pas une fonction) pour une portabilité maximale. Encore une fois, toute cette histoire d'arguments variables est une magie noire profonde et profonde. Selon les spécificités du compilateur et ABI, va_end() ne peut rien faire du tout. D'un autre côté, l'échec de l'utilisation de va_end() peut provoquer le blocage de votre programme lorsque l'instruction return est atteinte car la trame de la pile (s'il en existe une) n'est plus correctement configurée pour effectuer un retour.

+0

Woops, j'ai mal compris comment fonctionne va_start(). Je suppose que http://numbergrinder.com/node/35 ne l'explique pas assez clairement. Je pensais que le deuxième paramètre à va_start() était le nombre réel de combien de paramètres ont été envoyés à la fonction; et qu'il y avait une «surcharge» qui contenait une chaîne de format qui déterminait le nombre basé sur le nombre de% non-échappés présents dans la chaîne de format ... Wow cela rend tellement plus facile que vous n'avez pas à déterminer le compte toi-même. Merci pour l'explication. – Senseful

8

Vous l'avez presque compris; juste un couple de tweaks:

+ (NSString *) myFormattedString:(NSString *)format, ... { 
    va_list args; 
    va_start(args, format); 

    NSString *str = [[NSString alloc] initWithFormat:format arguments:args]; 
    [str autorelease]; 

    va_end(args); 

    return [NSString stringWithFormat:@"Foo: %@.", str]; 
} 

Cela devrait faire ce que vous cherchez.

Questions connexes