从#define集中提取字符串消息

时间:2010-07-29 15:54:41

标签: c

我正在使用具有许多不同错误代码的第三方库。包含文件包含一大堆行,如:

#define ABC_INVALID_BUFFER_SIZE 101
#define ABC_INVALID_COMMAND 102

在运行时,我正在开发各种错误代码,因为我正在开发我的应用程序。我想在运行时让应用程序打印出“error:ABC_INVALID_COMMAND”之类的消息,而不是打印“error:102”。

我希望有一个各种翻译地图,允许我使用地图[代码]将数字转换为文本。

所以我正在寻找的是一种机制,它允许我在编译时解析包含文件,并将其转换为map [102] = string(“ABC_INVALID_COMMAND”)。 我可以使用awk脚本执行此操作,但我想知道是否存在已存在的机制。当然,我不能成为第一个想要/需要这样做的人吗?我还没有发现一些明显的东西吗?

3 个答案:

答案 0 :(得分:1)

你肯定不是第一个想要这个功能的人,我也会喜欢它。

不幸的是,您需要继续使用脚本。我会有一个运行make的脚本,然后每次运行你的脚本。

即使c预处理器废弃了#define的标签,你仍然可以访问它们:

cpp -dM foo.h

返回:

 (some others)
 #define A 1
 #define B 2

你会发现你仍然需要使用返回值。

http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Preprocessor-Options.html#Preprocessor-Options

的更多信息

答案 1 :(得分:1)

绝对!这可以使用X-Macros使用编译器的预处理器来完成。我经常使用它来将错误代码与字符串相关联。

完整说明:What is a good reference documenting patterns of use of X-Macros in C (or possibly C++)?

针对您的具体问题:

/* 
 * X Macro() data list
 *  - Add all new values here (and only here!)
 * Format: Enum, Value
 */
#define X_ABC_ERROR \
  X(ABC_INVALID_BUFFER_SIZE,   101) \
  X(ABC_INVALID_COMMAND,       102) \
  X(ABC_SOME_OTHER_ERROR,      200)

/* 
 * Build an array of error return values
 *   e.g. {101,102}
 */
static int ErrorVal[] =
{
  #define X(Enum,Val)     Val,
   X_ABC_ERROR
  #undef X
};

/* 
 * Build an array of error enum names
 *   e.g. {"ABC_INVALID_BUFFER_SIZE","ABC_INVALID_COMMAND"}
 */
static char * ErrorName[] = {
  #define X(Enum,Val)     #Enum,
   X_ABC_ERROR
  #undef X
};

/* 
 * Create an enumerated list of error indexes
 *   e.g. IDX_ABC_INVALID_BUFFER_SIZE = 0, IDX_ABC_INVALID_COMMAND = 1, ...
 */
enum {
  #define X(Enum,Val)     IDX_##Enum,
   X_ABC_ERROR
  #undef X
  IDX_MAX   /* Array size */
};

/* 
 * Sample function to show error codes/names
 */
static void showErrorInfo(void)
{
    int i;

    /* 
     * Access the values
     */
    for (i=0; i<IDX_MAX; i++)
        printf(" %s == %d\n", ErrorName[i], ErrorVal[i]);
}

答案 2 :(得分:0)

语言无法完成,预处理器会在编译器看到之前将字符串重新映射到它们的值。

常见的解决方案是:
1,一个脚本,用于生成常量列表以及一组匹配的#defined字符串 或者生成一个带有大switch语句的函数来返回字符串值。

2,用结构数组替换值

struct {
  int value;
  char *name;
} values;

并用一对常量“description”初始化它。 根据您使用#defines的方式,这可能无法实现。

我会编写一个脚本(awk / python / etc)来读取文本文件:

AVALUE 12
BVALUE 23
CVALUE 45

并吐出.h文件

#define AVALUE_S "AVALUE"
#define AVALUE 12
#define BVALUE_S "BVALUE"
#define BVALUE 23

然后在您的代码中,只要您需要人类可读的字符串,就可以使用AVALUE_S。