2009-11-25 25 views
17

Sto provando a fare qualcosa di veramente banale: una macro che prende una stringa e la stampa su NSLog.Come creare una macro che può prendere una stringa?

Ti piace questa:

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

Tuttavia, quando provo a passare una stringa a questo ragazzo che finisce per ottenere "testo" stampato sulla console. Non tutte le variabili sono sostituite a livello di stringa all'interno della macro? Come farlo giusto?

+1

forse si vuole per ricerca NSLog () in riferimento per vedere come usarlo? – stefanB

+0

Come altri hanno sottolineato, sembra che tu voglia la sintassi "cpp" "stringizing": vedi http://en.wikipedia.org/wiki/C_preprocessor#Quoting_macro_arguments –

risposta

12

Ti consigliamo di utilizzare l'operatore del preprocessore 'stringizing', #, e, probabilmente, l'operatore 'token incollare', '##':

#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))); 

io non sono sicuro se Objective-C richiede '@' per non avere spazi bianchi tra esso e la citazione di apertura - se è consentito lo spazio bianco, rilasciare l'operazione PASTE().

Si noti che è necessario il buffo 2 livelli di riferimento indiretto per STRINGIFY() e PASTE() per funzionare correttamente con i parametri macro. E non fa mai male a meno che tu non stia facendo qualcosa di molto insolito (dove non vuoi che i parametri macro siano espansi), quindi è abbastanza normale usare questi operatori in quel modo.

3

Penso che il problema che stai incontrando è che "testo" è dentro ciò che appare al preprocessore come una stringa letterale (le virgolette, e possibilmente il simbolo @), quindi non sta sostituendo. Solo una supposizione, ma funzionerebbe?

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

PRINTTHIS(@"string");

Si potrebbe anche definire una versione che prende le stringhe C invece di stringhe objc:

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

PRINTTHIS_C("string");
+0

Dal modo in cui lo ha scritto, sembra che voglia scrivere PRINTTHIS (ciao mondo) e farlo fare NSLog (@ "Hello World"). – Chuck

+1

@Chuck: Sì, ma andrà fuori di testa se ha un '%' nella stringa. – Wevah

0

prendere questo con un grano di sale ... io non sono uno sviluppatore Objective-C. Ma nelle macro di tipo C, i parametri macro che appaiono all'interno di stringhe letterali non vengono sostituiti dai corrispondenti argomenti reali, quindi la sostituzione che si sta tentando di fare non funzionerà.

Questo potrebbe funzionare:

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

PRINTTHIS("your message here"); 

(così le virgolette sono spostati fuori dalla definizione di macro.)

Chuck sottolinea in un commento che in Objective-C, la @ è considerata parte della il token in questo costrutto. Quindi potrebbe essere necessario utilizzare l'operatore incolla token di ##:

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

Il preprocessore Objective-C funziona esattamente nello stesso modo, tranne che @ è parte del token (specifica un letterale NSString, al contrario di "", che specifica un valore letterale C-string). Hai ragione sul motivo. – Chuck

+0

Grazie Chuck! Ho aggiornato la mia risposta; si spera che otterrà walkthedog puntato nella giusta direzione. –

9

Ecco un modo di scrivere una macro che attacca il suo argomento testualmente in un oggetto stringa, anche se mi sembra un po 'nodoso:

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

Esso utilizza l'operatore di stringa per trasformare l'argomento in una stringa C, che quindi utilizza per creare un CFString, che è un ponte senza pedaggio con NSString.

4

Usa

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

In questo modo, il testo può contenere caratteri%, la sua 'se a prova', i punti e virgola sono tutti al posto giusto, ecc ...

Personalmente, tuttavia, direi che ha più senso usare semplicemente NSLog() direttamente.

+0

Questo stamperà qualsiasi espressione passi alla macro. Se passi '[foo objectAtIndex: idx]', stamperà "[foo objectAtIndex: idx]". Supponendo che l'interrogante significhi effettivamente stampare la stringa, dovrebbero lasciare fuori l'operatore # e potrebbe voler usare '% @' invece di '% s' (a seconda del tipo di stringa). –

7

Sembra che anche questo funzionerebbe.

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

Appena testato, sembra funzionare correttamente.

+0

Può anche essere questo NSLog (@ # testo "qualcosa di aggiunto"); – malhal

0

Credo sia solo questione di stare attenti con gli spazi. Questo dovrebbe funzionare bene:

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

Un altro esempio:

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

0

Ho l'impressione che questo è quello che vuoi dire, e si desidera

Si desidera una stringa che può prendere un argomento, pur contenendo altre stringhe, qualcosa di simile a una funzione stringwithformat.

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

quindi di utilizzare la macro appena passarlo il valore a cui si aggiunge la stringa completa

NSLog(ThisMacro(@"Mthokozisi")) 

Il risultato finale sarà, @"Hello my name is Mthokozisi, and I'm a developer"

Problemi correlati