在getsubopt中正确使用const char *数组

时间:2013-12-04 21:54:51

标签: arrays pointers enums char const

我正在尝试使用getsubopt来解析c ++中的一些子选项。我有以下代码。

enum LOG_LEVELS {LOG_QUIET, LOG_NORMAL, LOG_VERBOSE, LOG_DEBUG};

int parse_log_level(char *log_level){
    /* Define valid log options. */
    char *const log_opts[] =
    {
        "quiet",
        "normal",
        "verbose",
        "debug",
        NULL
    }; /* <- First set of warnings */

    char* value;
    /* Loop through each option and check for valid log options. */
    while (log_level != '\0'){
        switch (getsubopt (&log_level, log_opts, &value))
        {
            case LOG_QUIET:
                return LOG_QUIET;
                break;

            case LOG_NORMAL:
                return LOG_NORMAL;
                break;

            case LOG_VERBOSE:
                return LOG_VERBOSE;
                break;

            case LOG_DEBUG:
                return LOG_DEBUG;
                break;

            default:
                std::cout << "Only the following log options are valid"
                          << std::endl << std::endl << "\tquiet"
                          << std::endl << "\tnormal"
                          << std::endl << "\tverbose"
                          << std::endl << "\tdebug" << std::endl;
                return -1;
                break;
        }
    }
}

当我尝试编译时,我收到以下错误。

option_parser.cpp: In function 'int parse_log_level(char*)':
option_parser.cpp:35: warning: deprecated conversion from string const to 'char*'
option_parser.cpp:35: warning: deprecated conversion from string const to 'char*'
option_parser.cpp:35: warning: deprecated conversion from string const to 'char*'
option_parser.cpp:35: warning: deprecated conversion from string const to 'char*'

正如您可能注意到的,我在某种程度上偏离了以下提供的示例: getsubopt example

即,我使用过:

char *const log_opts[] =
{
     "quiet",
     "normal",
     "verbose",
     "debug",
     NULL
}; /* <- First set of warnings */

取代我想象的将是他们的代码版本:

char *const log_opts[] = 
{
     [LOG_QUIET] = "quiet", /* <- New error */
     [LOG_NORMAL] = "normal", /* <- New error */
     [LOG_VERBOSE] = "verbose", /* <- New error */
     [LOG_DEBUG] = "debug", /* <- New error */
     NULL
};

当我尝试上面的代码时,我收到以下错误

option_parser.cpp: In function 'int parse_log_level(char*)':
option_parser.cpp:30: error: expected primary-expression before '[' token
option_parser.cpp:31: error: expected primary-expression before '[' token
option_parser.cpp:32: error: expected primary-expression before '[' token
option_parser.cpp:33: error: expected primary-expression before '[' token

我在教程中选择了我的格式,因为它避免了错误,我不理解语法,即我不理解char * const数组声明中的[FOO] = "bar"语法。我也注意到在示例中他们的枚举没有命名,而我的等价LOG_LEVELS是。我的枚举在我的程序的其他地方工作。最后,我注意到他们的枚举对第一个项目有类似的语法,即RO_OPT = 0,的上下文中的enum {RO_OPT = 0, RW_OPT, NAME_OPT};

我曾尝试在网上其他地方寻找类似的结构,但没有找到任何帮助我解决这个问题的东西。我希望在尝试尽可能清楚地提出这个问题时,我并不太啰嗦。

1 个答案:

答案 0 :(得分:0)

您的代码是正确的。在我看来,getsubopt的原型是不正确的。 tokens应该是const char * const *。据推测,这是一个历史错误,无法轻易纠正。

有几种丑陋的方法可以解决这个问题。

您可以为每个选项创建本地非const char数组:

char tok_quiet[] = "quiet";
char tok_normal[] = "normal";
char tok_verbose[] = "verbose";
char tok_debug[] = "debug";
char *const log_opts[] =
{
    tok_quiet,
    tok_normal,
    tok_verbose,
    tok_debug,
    NULL
};

或者您可以使用文字数组作为标记:

char *const log_opts[] =
{
    (char[]){'q','u','i','e','t',0},
    (char[]){'n','o','r','m','a','l',0},
    (char[]){'v','e','r','b','o','s','e',0},
    (char[]){'d','e','b','u','g',0},
    NULL
};

我认为你会同意这两件事都很令人反感。

鉴于这些选择,我可能只是使用编译指示禁用该部分代码的-Wwrite-strings警告。

(您引用的其他代码,例如[LOG_QUIET] = "quiet",使用C99当前不支持的C99语法。[]=语法允许您通过索引初始化数组成员。)