【问题标题】:How to select one of the options?如何选择其中一个选项?
【发布时间】:2019-05-03 19:24:13
【问题描述】:

我正在尝试使用 POSIX getopt 函数并遇到了一些问题。我想通过命令行参数为应用程序提供一种模式(读取或写入)。所以我尝试做这样的事情:

enum mode{
    read,
    write
};
enum mode mode;

int opt;
while((opt = getopt("rw")) != -1){
    switch(opt){
        case 'w':
            mode = write;
            break;
        case 'r':
            mode = read;
            break;
        default:
            fprintf(stderr, "Usage: %s [-r-w]\n", argv[0]");
            exit(1);
    }
}

问题在于它的工作方式现在可以同时传递-r-w 选项,这是无意义的。我希望选择这两种模式中的唯一一种。

这样做的“惯用”方式是什么?

【问题讨论】:

  • 在您的情况下,1)验证:选择“无模式”是否有问题? 2) 第二次选择相同的模式有问题吗?
  • @chux 1) 是的,我希望用户只选择一种模式。

标签: c command-line-arguments unistd.h


【解决方案1】:

如果是我,我可能会使用这些方面的东西:

enum mode { DEFAULT, READ, WRITE };
enum mode mode = DEFAULT;

int opt;
while ((opt = getopt("rw")) != -1)
{
    switch (opt)
    {
    case 'w':
        if (mode == READ)
            err_exit("cannot use mutually exclusive options -r and -w");
        mode = WRITE;
        break;
    case 'r':
        if (mode == WRITE)
            err_exit("cannot use mutually exclusive options -r and -w");
        mode = READ;
        break;
    default:
        fprintf(stderr, "Usage: %s [-r|-w]\n", argv[0]);
        exit(1);
    }
}

if (mode == DEFAULT)
    mode = READ;    // Or write, whichever is your default

请注意,这样可以避免使用未初始化的变量mode

我假设有一个合适的函数err_exit() 报告错误并退出。我的实现也有一个err_usage(),将使用err_usage("[-r|-w]");(并使用函数调用err_setarg0(argv[0]) 来记录程序名称)。您可以在 GitHub 上的 SOQ(堆栈溢出问题)存储库中以文件 stderr.cstderr.h 的形式在 src/libsoq 子目录中找到我的实现。

我也避免使用像 readwrite 这样的名称,因为它们也用于函数,因此被小写枚举常量隐藏(它们在普通标识符命名空间中,与函数和变量相同)。事实上,我可能会使用诸如OPT_ 之类的前缀(因此OPT_DEFAULTOPT_READOPT_WRITE)以避免与名称的其他可能用途发生冲突。

【讨论】:

  • 如果代码是if (mode == READ) --> if (mode != DEFAULT),那么像-w -w这样的用法会被检测到。
  • 是的,@chux:当我开始打字时,我实际上有!= DEFAULT,但我决定需要重新处理错误消息——需要两个测试来报告两种不同的错误情况(两者都是一对相互排斥的选项,而不是重复一个选项;我讨厌草率的错误消息,上面写着“多个条件之一是错误的”)。总体而言,设置相同标志的重复选项不太严重。对此的最终决定取决于我们没有的上下文。 (我还假设实际上除了-r-w 之外还有更多选项——帮助、版本等)
【解决方案2】:

如何选择其中一个选项?
I want user to select exactly one mode.

创建一个支持一种且仅一种有效模式的辅助函数。

enum mode get_mode(void) {
  int opt = getopt("rw");
  if (opt != -1 && getopt("rw") == -1) {
    switch(opt){
      case 'w': return write;
      case 'r': return read;
    }
  }
  fprintf(stderr, "Usage: %s [-r-w]\n", argv[0]");
  exit(1);
}

【讨论】:

  • 我喜欢这个函数的简洁性,但是(与 OP 代码一样)此代码不调用符合 POSIX 的 getopt。缺少 argc 和 argv 参数。此外, argv 将超出函数内部的范围。另外,读写会与 头文件中的定义冲突。
【解决方案3】:

这太主观了,这不是一个好问题,但这里有一些想法:

(1) 一种方法是只有一种选择。默认行为为读取,如果指定了 -w 选项,则模式为写入。

(2) 一些 Unix 程序通过说“最后一个参数获胜”来解决问题

(3) 另一种方法是使用单独的变量,并检测设置两个标志的条件。

我已经看到了所有三种方法的使用。可能还有其他想法。

【讨论】:

    猜你喜欢
    • 2014-02-12
    • 1970-01-01
    • 2020-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-28
    • 1970-01-01
    相关资源
    最近更新 更多