Если вы используете BSD / OS X, вы можете использовать jot вместо seq:
for i in $(jot $END); do echo $i; done
В C строковые литералы объединяются автоматически. Например,
const char * s1 = "foo" "bar";
const char * s2 = "foobar";
s1
и s2
- это одна и та же строка.
Итак, для вашей задачи ответ (без вставки токена):
#ifdef __TESTING
#define IV_DOMAIN "domain.org"
#elif __LIVE_TESTING
#define IV_DOMAIN "test.domain.com"
#else
#define IV_DOMAIN "domain.com"
#endif
#define IV_SECURE "secure." IV_DOMAIN
#define IV_MOBILE "m." IV_DOMAIN
Есть несколько способов сделать это:
если вы имеете дело только со строковыми литералами, вы можете просто использовать просто строки - размещение одного строкового литерала за другим вызывает компилятор для их объединения.
если могут быть задействованы другие вещи, кроме строковых литералов (т. Е. Вы создаете новые идентификаторы из макросов), используйте оператор вставки токена препроцессора '##
. Возможно, вам также понадобится использовать Строковый оператор '#
', чтобы превратить ваши макросы в буквальные строки.
Пример # 1:
#ifdef __TESTING
#define IV_DOMAIN "domain.org" //in house testing
#elif __LIVE_TESTING
#define IV_DOMAIN "test.domain.com" //live testing servers
#else
#define IV_DOMAIN "domain.com" //production
#endif
// Sub-Domain
#define IV_SECURE "secure." IV_DOMAIN //secure.domain.org etc
#define IV_MOBILE "m." IV_DOMAIN
И до вставки токена оператор идет, я не думаю, что большинство ответов, в которых предлагалось использовать оператор препроцессора вставки токена, действительно пытались это сделать - это может быть сложно использовать.
Использование часто предлагаемого ответа приведет к ошибка компилятора при попытке использовать макрос IV_SECURE
, потому что:
#define IV_SECURE "secure."##IV_DOMAIN
расширяется до:
"secure"domain.org
Возможно, вы захотите попробовать использовать '
# `' оператор 'stringizing':
#define IV_SECURE "secure." #IV_DOMAIN
Но это не сработает, потому что он работает только с аргументами макроса, а не только с любым старым макросом.
Об этом нужно знать, когда вы с использованием Token-Paste ('##') или stringizing ('#') операторы обработки - это то, что вы должны использовать дополнительный уровень косвенности, чтобы они работали должным образом во всех случаях.
Если вы этого не сделаете, а элементы, переданные оператору вставки токена, сами являются макросами, вы Вы получите результаты, которые, вероятно, не соответствуют вашим ожиданиям:
#include <stdio.h>
#define STRINGIFY2( x) #x
#define STRINGIFY(x) STRINGIFY2(x)
#define PASTE2( a, b) a##b
#define PASTE( a, b) PASTE2( a, b)
#define BAD_PASTE(x,y) x##y
#define BAD_STRINGIFY(x) #x
#define SOME_MACRO function_name
int main()
{
printf( "buggy results:\n");
printf( "%s\n", STRINGIFY( BAD_PASTE( SOME_MACRO, __LINE__)));
printf( "%s\n", BAD_STRINGIFY( BAD_PASTE( SOME_MACRO, __LINE__)));
printf( "%s\n", BAD_STRINGIFY( PASTE( SOME_MACRO, __LINE__)));
printf( "\n" "desired result:\n");
printf( "%s\n", STRINGIFY( PASTE( SOME_MACRO, __LINE__)));
}
Вывод:
buggy results:
SOME_MACRO__LINE__
BAD_PASTE( SOME_MACRO, __LINE__)
PASTE( SOME_MACRO, __LINE__)
desired result:
function_name21
Таким образом, используя ваши исходные IV_DOMAIN
определения и макросы утилит сверху, вы можете сделайте это, чтобы получить то, что вы хотите:
// Sub-Domain
#define IV_SECURE "secure." STRINGIFY( IV_DOMAIN) //secure.domain.org etc
#define IV_MOBILE "m." STRINGIFY( IV_DOMAIN)
Вам нужны операторы # и ## и автоматическая конкатенация строк.
Оператор предварительной обработки # превращает параметр макроса в строку. Оператор ## вставляет два токена (например, макропараметры) вместе.
Мне приходит в голову возможность
#define IV_DOMAIN domain.org
#define IV_SECURE(DOMAIN) "secure." #DOMAIN
, которая должна изменить значение IV_SECURE на
#define IV_SECURE "secure." "domain.org"
, которое автоматически объединится в «secure.domain.org» (при условии, что фазы перевода в Си такие же, как и в С ++).
ДРУГОЕ РЕДАКТИРОВАНИЕ: Пожалуйста, прочитайте комментарии, которые показывают, как мне удалось запутаться. Имейте в виду, что я полностью опытен в Си, хотя, возможно, немного ржавый. Я бы удалил этот ответ, но я решил оставить его как пример того, как легко быть запутанным препроцессором Си.
Я вижу много хороших и правильных ответов на ваш первый вопрос, но нет ответов на ваш второй, поэтому вот что: я думаю, что это ужасная идея. Почему вы должны пересобрать свое программное обеспечение (особенно выпускную версию), чтобы просто изменить имя сервера? Кроме того, как вы узнаете, какая версия вашего программного обеспечения указывает на какой сервер? Вам придется встроить механизм для проверки во время выполнения. Если это вообще практично для вашей платформы, я рекомендую вам загрузить домены / URL-адреса из файла конфигурации. Только самые маленькие встраиваемые платформы не могут быть «практичными» для этой цели:)
Как уже отмечалось, используйте вставку токенов. Вы также должны знать, что имена макросов, такие как
__TESTING
, зарезервированы в C (не знаю об Objective C) для реализации - вам не разрешено использовать их в своем собственном коде. Зарезервированные имена - это все, что содержит двойное подчеркивание и что-либо, начинающееся с подчеркивания и заглавной буквы.
Следующие вместе строки объединяются компилятором C.
#define DOMAIN "example.com"
#define SUBDOMAIN "test." DOMAIN
const char *asCString = SUBDOMAIN;
NSString *asNSString = @SUBDOMAIN;
Попробуйте использовать оператор ##
#define IV_SECURE secure.##IV_DOMAIN