Подтвердить что ты не робот

Как сделать макрос, который может взять строку?

Я пытаюсь сделать что-то действительно тривиальное: макрос, который берет строку и печатает ее в NSLog.

Вот так:

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

Однако, когда я пытаюсь передать строку этому парню, я получаю "текст", напечатанный на консоли. Не все переменные заменены на уровне строк внутри макроса? Как это сделать?

4b9b3361

Ответ 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"