【问题标题】:Playing around with getopt玩弄 getopt
【发布时间】:2018-04-10 17:39:08
【问题描述】:

您好,我对编码很陌生,并试图找出这个 getopt 不起作用的原因。我的编译器抱怨“i:o:”

错误 C2664 'int getopt(int,char **,char *)': 无法将参数 3 从 'const char [5]' 转换为 'char *'

int main(int argc, char *argv[])
{
    int opt;
    while ((opt = getopt(argc, argv, "i:o:")) != -1)
    {
        switch (opt)
        {
        case 'i':
            printf("Input file: \"%s\"\n", optarg);
            break;
        case 'o':
            printf("Output file: \"%s\"\n", optarg);
            break;
        }
    }
    return 0;
}    

这很奇怪,因为当我阅读 getopt 时,我看到了“选项参数是一个字符串,它指定了对该程序有效的选项字符。”

【问题讨论】:

  • 第三个参数必须是可写的,字符串字面量是不可写的。这可能是您正在使用的 getopt 库中的“代码异味”。
  • 您使用的是哪个运行时?我看到int getopt(int argc, char * const argv[], const char *optstring);
  • 我建议 Boost.Program_options 优于 getopt
  • @FredLarson 试过了。没有留下深刻印象。
  • 我不知道 Visual Studio 库中有任何 getopt 函数 - 您包含哪个标头来获取它?

标签: c++ getopt


【解决方案1】:

根据您的错误消息,getopt 函数需要 可写 选项字符串。您可以通过制作这样的非常量字符数组来做到这一点:

int main(int argc, char *argv[])
{
    // non-const char array
    char opts[] = "i:o:"; // copy a string literal in

    int opt;
    while ((opt = getopt(argc, argv, opts)) != -1)
    {
        switch (opt)
        {
        case 'i':
            printf("Input file: \"%s\"\n", optarg);
            break;
        case 'o':
            printf("Output file: \"%s\"\n", optarg);
            break;
        }
    }
    return 0;
}

您的原始代码在LinuxGCC v7 上对我来说很好。您使用的版本的函数签名似乎不同。

我的系统上是:

int getopt (int argc, char** argv, const char* options);

但在您的系统上,它似乎是:

int getopt(int,char **,char *);

最后一个参数缺少const 导致错误,这就是为什么你需要给它一个非常量字符串。

注意:我不建议为此使用const_cast,因为有些人可能会受到诱惑。你永远不知道函数是如何实现的,或者内部实现是否会在某个时候发生变化。

【讨论】:

  • 如果getopt() 的实现确实没有修改选项字符串,您可能会使用const_cast。但是这种 const 正确性错误表明该库已过时或编写不佳。
  • 由于getopt() 不会写入最后一个参数,您可以const_cast 字符串文字而不是分配一个单独的非常量缓冲区:getopt(argc, argv, const_cast<char*>("i:o:"))
  • @FredLarson 不知道该功能是如何实现的,因此我绝不会根据概率和假设推荐const_cast。谁知道?也许它使用strtok
  • @Galik:我不知道实现的来源,因为它不是标准功能,而且 OP 不在 POSIX 平台上。源代码可能可用。如果源不可用,您可能可以按照您的建议使用可修改的字符串,然后在调用后检查字符串以查看它是否被修改。不过还是有一些风险。
  • @FredLarson 但是当你升级你的库时,实现可能会改变。所以我在“只是说不”阵营。 :)
【解决方案2】:

只需使用字符串指针:

char* opts = "i:o:";
getopt(argc, argv, opts);

【讨论】:

  • 这也不是合法的 C++。 OP 正在混合 C 和 C++ 并找到一些差异。
猜你喜欢
  • 1970-01-01
  • 2013-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多