2009-07-30 15 views
7

Supongamos que tengo un método con la firma:¿Cuál es la forma correcta de ajustar [NSString stringWithFormat:]?

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

Y quiero que antepone una cadena de mi elección (por ejemplo, @ "Foo"). Supongo que la mejor manera es usar [myString initWithFormat: arguments:], pero ¿cómo implementarías este método?


He intentado hacer lo siguiente, pero me da la advertencia como se especifica en el comentario:

+ (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 razón por la que estoy asumiendo va_start() puede tomar en un (char *) es por el ejemplo que vi en el manual page of STDARG(3). Siéntase libre de reescribir completamente el método si lo estoy haciendo completamente mal.

Respuesta

15

Creo que lo que quiere es algo así como:

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

Los stdarg.hva_ * macros se utilizan cuando una función (o, en este caso, el método) toma un número variable de argumentos, como se especifica en " ... ". va_start() se usa para encontrar el comienzo de donde comienza la cantidad variable de argumentos. Como tal, necesita conocer un último argumento de funciones/métodos (el anterior a "...") para determinar dónde comienza el número variable de argumentos. Esta es una explicación algo simplificada, ya que lo que sucede realmente bajo el capó es muy específico de ABI/Compiler. El punto más importante es que el segundo argumento para va_start() es siempre el nombre de la variable 'justo antes de' ... ''.

va_end() debe ser "llamado" (es realmente un macro, no una función) para una máxima portabilidad. De nuevo, esta cuestión de argumentos variables es profunda, profunda magia negra. Dependiendo de los detalles del compilador y ABI, va_end() no puede hacer nada. Por otro lado, si no se usa va_end(), el programa se bloqueará cuando se llegue a la instrucción return porque el marco de la pila (si es que hay alguno) ya no está configurado correctamente para realizar una devolución.

+0

Woops, no entiendo cómo funciona va_start(). Supongo que http://numbergrinder.com/node/35 no lo explica con suficiente claridad. Pensé que el segundo parámetro para va_start() era el recuento real de cuántos params se enviaron a la función; y que tenía una 'sobrecarga' que tomaba una cadena de formato que determinaba el recuento en función de cuántos% no escapados había en la cadena de formato ... Vaya, eso hace que sea mucho más fácil que no tenga que determinar el conde tú mismo. Gracias por la explicación. – Senseful

8

Ya casi lo tienes; solo un par de ajustes:

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

Eso debería hacer lo que usted está buscando.

Cuestiones relacionadas