2009-04-27 35 views
1

我試圖想出一個聰明的方式(在C中)在一個構造中創建一個字符串數組以及數組索引的符號名稱(枚舉或#define)易於維護。類似:在同一時間定義數組和符號索引

爲const char *串[] = { M(STR_YES, 「是」), M(STR_NO, 「否」), M(STR_MAYBE, 「也許」) };

其中結果將相當於:

爲const char *串[] = { 「是」, 「否」, 「也許」}; 枚舉索引{STR_YES,STR_NO,STR_MAYBE}; (或#define STR_YES 0等)

但我在這種情況下如何構建M宏的空白。

任何聰明的想法?

回答

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_yesSTR_no,...作爲枚舉器名稱,您可以使用與上面相同的方法。否則,只需傳遞宏兩件事。一個小寫名字和一個大寫名字。然後你可以將上面想要的那個串起來。

+2

這種技術被稱爲X-宏 - http://en.wikipedia.org/wiki/C_preprocessor#X-Macros – qrdl 2009-04-27 18:56:24

+0

完美,這就是我一直在尋找我的慢週一昏昏沉沉的大腦掛鉤。將定義放在一個單獨的文件中,並將其讀入兩次。 謝謝! – 2009-04-27 19:04:15

+0

此技術的一個缺點是IDE和/或調試器可能不夠智能,無法正確解析這些問題。如果是這種情況 - 最好將生成列表作爲構建過程的一部分。 – Hexagon 2009-04-27 19:10:54

4

這是一個使用代碼生成的好地方。使用像perl,php之類的語言來生成你的.h文件。

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 
} 
相關問題