C(预处理器):如何 concatenate/append 替换字符串
C (Preprocessor): How to concatenate/append substitution string
我在命令行上定义我的异常:
-DEXCEPTION_1=\"first\" -DEXCEPTION_2=\"second\" -DEXCEPTION_3=\"third\"
我检查了一个字符串:
except = 0;
#ifdef EXCEPTION_1
if (! strcmp(EXCEPTION_1, mystring))
{ except = 1;
}
#endif
#ifdef EXCEPTION_2
if (! strcmp(EXCEPTION_2, mystring))
{ except = 1;
}
#endif
#ifdef EXCEPTION_3
if (! strcmp(EXCEPTION_3, mystring))
{ except = 1;
}
#endif
if (except == 1)
{ // do something
}
else
{ // do something else
}
不用说,虽然这可行,但它也非常丑陋、不灵活并且导致我的代码冗余。
有没有办法将字符串附加到预处理器宏变量?
我想得到这样的东西(问题当然是#append
不存在):
#ifdef EXCEPTION_1 #append EXCEPTIONS if (! strcmp(EXCEPTION_1, mystring)) { except = 1; }
#ifdef EXCEPTION_2 #append EXCEPTIONS if (! strcmp(EXCEPTION_2, mystring)) { except = 1; }
#ifdef EXCEPTION_3 #append EXCEPTIONS if (! strcmp(EXCEPTION_3, mystring)) { except = 1; }
然后我可以在代码中使用 EXCEPTIONS
,它可以处理所有可能的异常排列。
换句话说,我想将一个字符串附加到一个宏变量 - 这可能吗?
你可以有定义链,但它看起来不会好多少:
#ifdef EXCEPTION_1
#define EXCEPTIONS1 if (! strcmp(EXCEPTION_1, mystring)) { except = 1; }
#else
#define EXCEPTIONS1
#endif
#ifdef EXCEPTION_2
#define EXCEPTIONS2 EXCEPTIONS1 if (! strcmp(EXCEPTION_2, mystring)) { except = 1; }
#else
#define EXCEPTIONS2 EXCEPTIONS1
#endif
// etc
同样,也好不了多少。
而且您真的 不应该用开放的 if
定义宏。它允许像 if(cond) EXCEPTIONS1 else cout<<"error";
这样奇怪的交互——这不会像你期望的那样,因为 EXCEPTIONS1
是一个普通的 if
并且会吞噬 else
分支。
用代码块编写宏的典型方法是将整个内容包装在 do{...}while(0)
中(注意没有结尾 ;
)。
您可以将宏参数转换为字符串:
#define STR(x) #x
STR(hello) --> "hello"
您可以连接 字符串文字 ,只需将它们并排书写即可:
"123" "abc" --> "123abc"
或者创建一个宏:
#define CONCAT(a, b) a b
CONCAT("hello", " world!") --> "hello world!"
您可以使用 ##
将字符串连接到宏。使用索引并仅使用条件来设置索引。然后最后您可以将索引与您的宏 EXCEPTION
连接起来。像,
定义一个像#define append(name) name ## counter
这样的宏
如果 counter
是 1
,这将反过来给你 name
作为 name1
现在您可以定义不同的 append
宏来将结果放在一个变量中 name
查看标记字符串化和连接部分 here
它可能会帮助一些人。通常,使用命令行宏来填充 table 并拥有一个简单扩展为循环的宏似乎更容易,该循环检查 table 的连续条目以设置例外标志。
例如,将下面的内容保存为silly.c,然后用cc -DEX1=\"hello\"
编译
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct Except {
const char* key;
int flag;
};
struct Except table[] = {
#if defined(EX1)
{EX1,1},
#endif
{NULL,0}
};
#define CHECKEX(mys,rv) { rv = 0;for(int i=0;table[i].key!=0;i++) \
if (strcmp(table[i].key,(mys))==0) \
rv = 1; \
}
int main()
{
int rv;
CHECKEX("hello",rv);
if (rv)
printf("Got an hello\n");
else printf("Got nothing\n");
return 0;
}
只需根据需要向 table 添加更多 "blocks"。当然只是建议。
我在命令行上定义我的异常:
-DEXCEPTION_1=\"first\" -DEXCEPTION_2=\"second\" -DEXCEPTION_3=\"third\"
我检查了一个字符串:
except = 0;
#ifdef EXCEPTION_1
if (! strcmp(EXCEPTION_1, mystring))
{ except = 1;
}
#endif
#ifdef EXCEPTION_2
if (! strcmp(EXCEPTION_2, mystring))
{ except = 1;
}
#endif
#ifdef EXCEPTION_3
if (! strcmp(EXCEPTION_3, mystring))
{ except = 1;
}
#endif
if (except == 1)
{ // do something
}
else
{ // do something else
}
不用说,虽然这可行,但它也非常丑陋、不灵活并且导致我的代码冗余。
有没有办法将字符串附加到预处理器宏变量?
我想得到这样的东西(问题当然是#append
不存在):
#ifdef EXCEPTION_1 #append EXCEPTIONS if (! strcmp(EXCEPTION_1, mystring)) { except = 1; }
#ifdef EXCEPTION_2 #append EXCEPTIONS if (! strcmp(EXCEPTION_2, mystring)) { except = 1; }
#ifdef EXCEPTION_3 #append EXCEPTIONS if (! strcmp(EXCEPTION_3, mystring)) { except = 1; }
然后我可以在代码中使用 EXCEPTIONS
,它可以处理所有可能的异常排列。
换句话说,我想将一个字符串附加到一个宏变量 - 这可能吗?
你可以有定义链,但它看起来不会好多少:
#ifdef EXCEPTION_1
#define EXCEPTIONS1 if (! strcmp(EXCEPTION_1, mystring)) { except = 1; }
#else
#define EXCEPTIONS1
#endif
#ifdef EXCEPTION_2
#define EXCEPTIONS2 EXCEPTIONS1 if (! strcmp(EXCEPTION_2, mystring)) { except = 1; }
#else
#define EXCEPTIONS2 EXCEPTIONS1
#endif
// etc
同样,也好不了多少。
而且您真的 不应该用开放的 if
定义宏。它允许像 if(cond) EXCEPTIONS1 else cout<<"error";
这样奇怪的交互——这不会像你期望的那样,因为 EXCEPTIONS1
是一个普通的 if
并且会吞噬 else
分支。
用代码块编写宏的典型方法是将整个内容包装在 do{...}while(0)
中(注意没有结尾 ;
)。
您可以将宏参数转换为字符串:
#define STR(x) #x
STR(hello) --> "hello"
您可以连接 字符串文字 ,只需将它们并排书写即可:
"123" "abc" --> "123abc"
或者创建一个宏:
#define CONCAT(a, b) a b
CONCAT("hello", " world!") --> "hello world!"
您可以使用 ##
将字符串连接到宏。使用索引并仅使用条件来设置索引。然后最后您可以将索引与您的宏 EXCEPTION
连接起来。像,
定义一个像#define append(name) name ## counter
如果 counter
是 1
name
作为 name1
现在您可以定义不同的 append
宏来将结果放在一个变量中 name
查看标记字符串化和连接部分 here 它可能会帮助一些人。通常,使用命令行宏来填充 table 并拥有一个简单扩展为循环的宏似乎更容易,该循环检查 table 的连续条目以设置例外标志。
例如,将下面的内容保存为silly.c,然后用cc -DEX1=\"hello\"
编译#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct Except {
const char* key;
int flag;
};
struct Except table[] = {
#if defined(EX1)
{EX1,1},
#endif
{NULL,0}
};
#define CHECKEX(mys,rv) { rv = 0;for(int i=0;table[i].key!=0;i++) \
if (strcmp(table[i].key,(mys))==0) \
rv = 1; \
}
int main()
{
int rv;
CHECKEX("hello",rv);
if (rv)
printf("Got an hello\n");
else printf("Got nothing\n");
return 0;
}
只需根据需要向 table 添加更多 "blocks"。当然只是建议。