Как сделать макрос, который может взять строку?
Я пытаюсь сделать что-то действительно тривиальное: макрос, который берет строку и печатает ее в NSLog.
Вот так:
#define PRINTTHIS(text) \
NSLog(@"text");
Однако, когда я пытаюсь передать строку этому парню, я получаю "текст", напечатанный на консоли. Не все переменные заменены на уровне строк внутри макроса? Как это сделать?
Ответы
Ответ 1
Вы хотите использовать оператор "stringising" препроцессора, #
и, вероятно, оператор "склейка маркера", "##":
#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)));
Я не уверен, что если Objective-C требует, чтобы '@' не имел пробелов между ним и исходной цитатой - если разрешены пробелы, отпустите операцию PASTE().
Обратите внимание, что для правильной работы с параметрами макроса вам понадобятся дуплексные 2 уровня косвенности для STRINGIFY()
и PASTE()
. И это почти никогда не повредит, если вы не делаете что-то очень необычное (там, где вы не хотите, чтобы макро параметры были расширены), поэтому довольно стандартно использовать эти операторы таким образом.
Ответ 2
Здесь один из способов написать макрос, который текстурирует свой аргумент в строковый объект, хотя он выглядит мне немного грубо:
#define PRINTTHIS(text) NSLog((NSString *)CFSTR(#text))
Он использует оператор стробирования, чтобы превратить аргумент в строку C, которую он затем использует для создания CFString, который без сбоев соединяется с NSString.
Ответ 3
Кажется, что это тоже сработает.
#define PRINTTHIS(text) NSLog(@#text);
Просто протестировал его, и, похоже, он работает нормально.
Ответ 4
Использование
#define PRINTTHIS(text) \
do { NSLog(@"%s", #text); } while(0)
Таким образом, текст может содержать% символов, его "if-proof", полуколоны находятся в нужном месте и т.д.
Лично, однако, я бы сказал, что имеет смысл просто использовать NSLog() напрямую.
Ответ 5
Я думаю, что проблема, с которой вы сталкиваетесь, заключается в том, что "текст" находится внутри того, что представляется препроцессору как строковый литерал (кавычки и, возможно, символ @), поэтому он не заменяет. Просто догадаться, но будет ли это работать?
#define PRINTTHIS(text) \
NSLog(@"%@", text);
PRINTTHIS(@"string");
Вы также можете определить версию, которая берет строки C вместо строк ObjC:
#define PRINTTHIS_C(text) \
NSLog(@"%s", text);
PRINTTHIS_C("string");
Ответ 6
Возьмите это с солью... Я не разработчик Objective-C. Но в макрофайлах, подобных функции C, параметры макроса, входящие в строковые литералы, не заменяются соответствующими фактическими аргументами, поэтому подстановка, которую вы пытаетесь сделать, не будет работать.
Это может сработать:
#define PRINTTHIS(text) \
NSLog(@text);
PRINTTHIS("your message here");
(поэтому кавычки перемещаются из определения макроса.)
Чак указывает в комментарии, что в Objective-C, @считается частью токена
в этой конструкции. Поэтому может потребоваться использовать оператор склейки маркера ##:
#define PRINTTHIS(text) \
NSLog(@##text);
Ответ 7
Я считаю, что это всего лишь вопрос осторожности с пространствами. Это должно работать нормально:
#define PRINTTEXT( msg ) NSLog( (msg) )
Другой пример:
#define TFCheckPoint( msg ) [TestFlight passCheckpoint: (msg) ];
Ответ 8
У меня такое впечатление, что это то, что вы имеете в виду, и хотите
Вам нужна строка, которая может принимать аргумент, содержащий другие строки, что-то похожее на функцию stringwithformat.
#define ThisMacro(value) @"Hello my name is %@, and I'm a developer", value
Затем, чтобы использовать макрос, вы просто передаете ему значение, которое оно добавляет к полной строке
NSLog(ThisMacro(@"Mthokozisi"))
Конечным результатом будет @"Hello my name is Mthokozisi, and I'm a developer"