2009-11-25 9 views
17

Estoy tratando de hacer algo realmente trivial: una macro que toma una cadena e imprime eso en NSLog.¿Cómo hacer una macro que puede tomar una cadena?

De esta manera:

#define PRINTTHIS(text) \ 
    NSLog(@"text"); 

Sin embargo, cuando trato de pasar una cadena de este tipo con el que acaban obteniendo "texto" imprimen en la consola. ¿No se reemplazan todas las variables en un nivel de cadena dentro de la macro? ¿Cómo hacer eso verdad?

+1

Tal vez usted quiere para buscar NSLog () en referencia para ver cómo usarlo? – stefanB

+0

Como han señalado otros, parece que desea la sintaxis '' stringing '' cpp': Vea http://en.wikipedia.org/wiki/C_preprocessor#Quoting_macro_arguments –

Respuesta

12

Usted querrá utilizar el operador del preprocesador 'stringizing', #, y probablemente el operador 'pegar símbolo', '##':

#define STRINGIFY2(x) #x 
#define STRINGIFY(x) STRINGIFY2(x) 
#define PASTE2(a, b) a##b 
#define PASTE(a, b) PASTE2(a, b) 

#define PRINTTHIS(text) \ 
    NSLog(PASTE(@, STRINGIFY(text))); 

no estoy seguro de si Objective-C requiere la '@' no tiene espacios en blanco entre ella y la cita de apertura; si se permite el espacio en blanco, suelte la operación PEGAR().

Tenga en cuenta que necesitará los extraños 2 niveles de direccionamiento indirecto para STRINGIFY() y PASTE() para que funcionen correctamente con los parámetros de macro. Y casi nunca duele a menos que esté haciendo algo muy inusual (donde no quiere expandir los macroparámetros), por lo que es bastante estándar usar estos operadores de esa manera.

3

Creo que el problema con el que se está metiendo es que "texto" está dentro de lo que parece al preprocesador como una cadena literal (las comillas, y posiblemente el símbolo @), por lo que no reemplaza. Solo una suposición, pero, ¿funcionaría?

#define PRINTTHIS(text) \ 
    NSLog(@"%@", text); 

PRINTTHIS(@"string");

También puede definir una versión que lleva cadenas de C en lugar de cadenas ObjC:

#define PRINTTHIS_C(text) \ 
    NSLog(@"%s", text); 

PRINTTHIS_C("string");
+0

Por la forma en que lo escribió, parece que él quiere para escribir PRINTTHIS (hello world) y hacer que NSLog (@ "Hello World"). – Chuck

+1

@Chuck: Sí, pero se volverá loco si tiene un '%' en la cadena. – Wevah

0

tomar esto con un grano de sal ... No soy un desarrollador de Objective-C. Pero en las macros en forma de C, los parámetros macro que aparecen dentro de los literales de cadena no se reemplazan por sus argumentos reales correspondientes, por lo que la sustitución que intentas hacer no funcionará.

Esto podría funcionar:

#define PRINTTHIS(text) \ 
    NSLog(@text); 

PRINTTHIS("your message here"); 

(por lo que las cotizaciones se mueven fuera de la definición de la macro.)

Chuck señala en un comentario que en Objective-C, la @ se considera parte de el token en este constructo. Por lo que podría ser necesario utilizar el operador pegar token de ##:

#define PRINTTHIS(text) \ 
     NSLog(@##text); 
+1

El preprocesador Objective-C funciona exactamente de la misma manera, excepto que @ es parte del token (especifica un literal NSString, en oposición a "", que especifica un literal C-string). Estás en lo cierto sobre el motivo. – Chuck

+0

Gracias Chuck! He actualizado mi respuesta; con suerte, eso hará que walkthedog apunte en la dirección correcta. –

9

Aquí está una manera de escribir una macro que se pega su argumento textualmente en un objeto de cadena, aunque me parece un poco retorcido:

#define PRINTTHIS(text) NSLog((NSString *)CFSTR(#text)) 

Utiliza el operador de stringizing para convertir el argumento en una cadena C, que luego utiliza para crear una CFString, que se conecta de forma gratuita con NSString.

4

Uso

#define PRINTTHIS(text) \ 
    do { NSLog(@"%s", #text); } while(0) 

De esta manera, el texto puede contener caracteres%, su 'si a prueba', los puntos y comas están en el lugar correcto, etc ...

Personalmente, sin embargo, yo diría que tiene más sentido usar simplemente NSLog() directamente.

+0

Eso imprimirá cualquier expresión que pase a la macro. Si pasa '[foo objectAtIndex: idx]', se imprimirá "[foo objectAtIndex: idx]". Suponiendo que la persona que pregunta quiere decir realmente imprimir la cadena, debe dejar fuera el operador #, y puede querer usar '% @' en lugar de '% s' (dependiendo de qué tipo de cadena sea). –

7

Parece que esto también funcionaría.

#define PRINTTHIS(text) NSLog(@#text); 

Acabo de probarlo, y parece funcionar bien.

+0

También puede ser este NSLog (@ # text "algo agregado"); – malhal

0

Creo que es solo cuestión de tener cuidado con los espacios. Esto debería funcionar bien:

#define PRINTTEXT(msg) NSLog((msg))

Otro ejemplo:

#define TFCheckPoint(msg) [TestFlight passCheckpoint: (msg) ];

0

Tengo la impresión de que este es lo que quiere decir, y quiere

¿Quieres una cadena que puede tomar un argumento, mientras contiene otras cadenas, algo similar a una función de cadena con formato.

#define ThisMacro(value) @"Hello my name is %@, and I'm a developer", value 

Luego de usar la macro que acaba de pasar es el valor al que se suma a la cadena completa

NSLog(ThisMacro(@"Mthokozisi")) 

El resultado final será, @"Hello my name is Mthokozisi, and I'm a developer"

Cuestiones relacionadas