2009-11-25 11 views
17

Ich versuche etwas wirklich Triviales zu tun: Ein Makro, das eine Zeichenkette nimmt und diese an NSLog ausgibt.Wie mache ich ein Makro, das eine Zeichenkette aufnehmen kann?

So:

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

Allerdings, wenn ich versuche, eine Zeichenfolge zu diesem Kerl gehe ich an die Konsole „text“ gedruckt am Ende immer. Werden nicht alle Variablen innerhalb des Makros auf String-Ebene ersetzt? Wie macht man das richtig?

+1

vielleicht möchten Sie Nachschlag NSLog () in Bezug zu sehen, wie man es benutzt? – stefanB

+0

Wie andere gezeigt haben, scheint es, als ob Sie die "stringizing" 'cpp'-Syntax wollen: http://en.wikipedia.org/wiki/C_preprocessor#Quoting_macro_arguments –

Antwort

12

Sie wollen den 'Zeichenfolge' Betreiber Präprozessor verwenden, #, und wahrscheinlich den 'token einfügen' Operator '##':

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

Ich bin mir nicht sicher, ob Objective-C erfordert Das '@' muss zwischen dem Eröffnungszitat und dem Leerzeichen kein Leerzeichen enthalten. Wenn Leerzeichen erlaubt sind, löschen Sie die Operation PASTE().

Beachten Sie, dass Sie die doof 2 Ebenen der Indirektion für STRINGIFY() und PASTE() benötigen, um ordnungsgemäß mit Makroparametern zu arbeiten. Und es tut so gut wie nie weh, es sei denn, Sie tun etwas sehr Ungewöhnliches (wo Sie keine Makro-Parameter erweitert haben wollen), also ist es ziemlich normal, diese Operatoren auf diese Weise zu verwenden.

3

Ich glaube, das Problem, in das Sie geraten, ist, dass "Text" innerhalb des Präprozessors als String-Literal (die Anführungszeichen und möglicherweise das @ -Symbol) erscheint, so dass es nicht ersetzt. Nur eine Vermutung, aber würde das funktionieren?

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

PRINTTHIS(@"string");

Sie können auch eine Version definieren, die C-Strings statt ObjC Strings nimmt:

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

PRINTTHIS_C("string");
+0

Von der Art, wie er es geschrieben hat, sieht es so aus, als ob er es möchte schreibe PRINTTHIS (Hallo Welt) und lass es NSLog (@ "Hello World") tun. – Chuck

+1

@Chuck: Ja, aber es wird ausflippen, wenn er ein '%' in der Zeichenfolge hat. – Wevah

0

dieses Salz mit einem Korn nehmen ... Ich bin kein Objective-C-Entwickler. In C-Funktions-ähnlichen Makros werden Makroparameter, die in String-Literalen erscheinen, jedoch nicht durch ihre entsprechenden tatsächlichen Argumente ersetzt, so dass die Ersetzung, die Sie versuchen, nicht funktioniert.

Dies könnte funktionieren:

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

PRINTTHIS("your message here"); 

(so sind die Zitate aus der Makrodefinition verschoben.)

Chuck in einem Kommentar darauf hin, dass in Objective-C wird die @ Teil betrachtet von das Token in diesem Konstrukt. So könnte es notwendig sein, die token einfügen Operator verwenden ##:

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

Der Objective-C-Präprozessor funktioniert genauso, außer dass @ Teil des Tokens ist (es gibt ein NSString-Literal im Gegensatz zu "" an, das ein C-String-Literal angibt). Du hast Recht über den Grund. – Chuck

+0

Danke Chuck! Ich habe meine Antwort aktualisiert. hoffentlich wird das walkthedog in die richtige Richtung weisen. –

9

Hier ist eine Möglichkeit, ein Makro zu schreiben, die ihr Argument klebt textlich in einem String-Objekt, wenn es mir auffällt, als ein bisschen knorrigen:

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

Es verwendet den stringizing-Operator, um das Argument in eine C-Zeichenfolge umzuwandeln, die es dann verwendet, um eine CFString zu erstellen, die mit NSString gebührenfrei überbrückt wird.

4

Verwenden

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

Auf diese Weise kann Text% Zeichen, sein ‚wenn sicher‘, die Semikolons alle an der richtigen Stelle sind, etc ...

Persönlich würde ich jedoch sagen, dass es sinnvoller ist, NSLog() direkt zu verwenden.

+0

Damit wird der Ausdruck gedruckt, den Sie an das Makro übergeben. Wenn Sie '[foo objectAtIndex: idx]' übergeben, wird "[foo objectAtIndex: idx]" gedruckt. Unter der Annahme, dass der Fragesteller den String tatsächlich druckt, sollten sie den Operator # weglassen und "% @" anstelle von "% s" verwenden (je nachdem, um welche Art von String es sich handelt). –

7

Es scheint, als würde dies auch funktionieren.

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

Nur getestet, und es scheint gut zu funktionieren.

+0

Es kann auch dieses NSLog sein (@ # text "something anched"); – malhal

0

Ich glaube, es ist nur eine Frage der Vorsicht mit den Räumen. Dies sollte funktionieren:

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

Ein weiteres Beispiel:

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

0

ich den Eindruck, bin dieses ist, was Sie meinen, und wollen

Sie einen String möchten, nehmen ein Argument, das andere Strings enthält, ähnlich einer stringwithformat-Funktion.

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

dann das Makro verwenden Sie geben es nur um den Wert, den sie dem vollständigen Zeichenfolge fügt

NSLog(ThisMacro(@"Mthokozisi")) 

Das Endergebnis sein wird, @"Hello my name is Mthokozisi, and I'm a developer"

Verwandte Themen