我正在尝试一种聪明的方法(在C中)创建一个字符串数组,以及数组索引的符号名称(枚举或#define),在一个结构中便于维护。类似的东西:
const char * strings [] = { M(STR_YES,“是”), M(STR_NO,“不”), M(STR_MAYBE,“也许”) };
其中结果相当于:
const char * strings [] = {“yes”,“no”,“maybe”}; 枚举索引{STR_YES,STR_NO,STR_MAYBE}; (或#define STR_YES 0等)
但是我在这种情况下为如何构造M宏绘制了一个空白。
任何聪明的想法?
答案 0 :(得分:6)
clang编译器源中使用的一种技术是创建包含这样的列表的.def
文件,该文件的设计类似于C文件,可以轻松维护而无需触及使用它的其他代码文件。例如:
#ifndef KEYWORD
#define KEYWORD(X)
#endif
#ifndef LAST_KEYWORD
#define LAST_KEYWORD(X) KEYWORD(X)
#endif
KEYWORD(return)
KEYWORD(switch)
KEYWORD(while)
....
LAST_KEYWORD(if)
#undef KEYWORD
#undef LAST_KEYWORD
现在,它做的是包括这样的文件:
/* some code */
#define KEYWORD(X) #X,
#define LAST_KEYWORD(X) #X
const char *strings[] = {
#include "keywords.def"
};
#define KEYWORD(X) kw_##X,
#define LAST_KEYWORD(X) kw_##X
enum {
#include "keywords.def"
};
在你的情况下,你可以做类似的事情。如果您可以使用STR_yes
,STR_no
,...作为枚举器名称,则可以使用与上述相同的方法。否则,只需传递宏两件事。一个小写名称和一个大写名称。然后你可以将上面想要的那个字符串化。
答案 1 :(得分:4)
这是使用代码生成的好地方。使用perl,php等语言生成.h文件。
答案 2 :(得分:0)
不需要将其放入特定的.def文件中;仅使用预处理器是完全可能的。我通常会定义一个名为...LIST
的列表,其中每个元素都包含在...LIST_ELEMENT
中。根据我将使用的列表,我将使用逗号分隔除最后一个条目(最简单),或者在一般情况下,可以在每次使用时单独选择分隔符。例如:
#include <string.h>
#define DIRECTION_LIST \
DIRECTION_LIST_ELEMENT( up, DIRECTION_LIST_SEPARATOR ) \
DIRECTION_LIST_ELEMENT( down, DIRECTION_LIST_SEPARATOR ) \
DIRECTION_LIST_ELEMENT( right, DIRECTION_LIST_SEPARATOR ) \
DIRECTION_LIST_ELEMENT( left, NO_COMMA )
#define COMMA ,
#define NO_COMMA /**/
#define DIRECTION_LIST_ELEMENT(elem, sep) elem sep
#define DIRECTION_LIST_SEPARATOR COMMA
typedef enum {
DIRECTION_LIST
} direction_t;
#undef DIRECTION_LIST_ELEMENT
#undef DIRECTION_LIST_SEPARATOR
#define DIRECTION_LIST_ELEMENT(elem, sep) void (*move_ ## elem)(struct object_s * object);
#define DIRECTION_LIST_SEPARATOR NO_COMMA
typedef struct object_s {
char *name;
// ...
DIRECTION_LIST
} object_t;
#undef DIRECTION_LIST_ELEMENT
#undef DIRECTION_LIST_SEPARATOR
static void move(object_t *object_p, const char * direction_string)
{
if (0) {
}
#define DIRECTION_LIST_SEPARATOR NO_COMMA
#define DIRECTION_LIST_ELEMENT(elem, sep) \
else if (strcmp(direction_string, #elem) == 0) { \
object_p->move_ ## elem(object_p); \
}
DIRECTION_LIST
#undef DIRECTION_LIST_ELEMENT
#undef DIRECTION_LIST_SEPARATOR
}