【问题标题】:extract string messages from set of #define从#define 集合中提取字符串消息
【发布时间】:2010-07-29 15:54:41
【问题描述】:

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

#define ABC_INVALID_BUFFER_SIZE 101
#define ABC_INVALID_COMMAND 102

等等

在运行时,我在开发应用程序时收到各种错误代码。我想让应用程序在运行时打印出像“错误:ABC_INVALID_COMMAND”这样的消息,而不是打印“错误:102”。

我想要一个允许我使用 map[code] 将数字转换为文本的翻译地图。

所以我正在寻找一种机制,让我在编译时解析包含文件,并将其转换为 map[102] = string("ABC_INVALID_COMMAND")。 我可以使用 awk 脚本来做到这一点,但我想知道是否存在已经存在的机制。我肯定不能成为第一个想要/需要这样做的人吗?我还没有发现明显的东西?

【问题讨论】:

  • 我认为您最好(手动)编写一个将代码转换为人类可读错误消息的函数。这可以像返回字符串常量的 switch() 语句一样简单。许多库已经提供了这样的东西(例如,LDAP 的 ldap_err2string());但是,如果您的 3rd 方库没有为您提供它,可能仍然值得花一点时间手动编写代码。
  • 1000 条消息,其中大部分我不知道它们是什么意思?

标签: c


【解决方案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

【讨论】:

    【解决方案2】:

    绝对!这可以通过 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]);
    }
    

    【讨论】:

    • 非常有趣的优雅解决方案,如果你可以控制你定义的常量,但它是一个第三方库(用于特殊的专用硬件),它定义了 1000 条消息和错误代码......
    【解决方案3】:

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

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

    2、用结构数组替换值

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

    并用一对常量“描述”对其进行初始化。 根据您使用#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。

    【讨论】:

    • 部分有帮助。 Cpp 将显示最终执行的定义(取决于其他 ifdef)。仍然需要我的 awk 脚本。
    猜你喜欢
    • 2021-12-07
    • 1970-01-01
    • 2021-08-01
    • 1970-01-01
    • 2022-12-20
    • 1970-01-01
    • 2015-01-25
    • 1970-01-01
    相关资源
    最近更新 更多