C getopt多值

20

我的论点是这样的

./a.out -i file1 file2 file3

如何利用getopt()获取3个(或更多)输入文件?我正在这样做:

while ((opt = getopt(argc, argv, "i:xyz.."))!= -1){
  case 'i':
     input = optarg; 
     break;
  ...
}

我只获取了file1,如何获取file2file3


1
请注意,使用 getopt() 为命令行选项提供两个参数的问题提供了一些在这里未提及的可能性。 - Jonathan Leffler
3
修改程序代码中的optind的答案,是在冒险尝试。没有文件记录说明必须在调用代码中修改getopt()optindoptarg时应该如何运行。尽管当前和可能存在的大多数实现不会有问题,但是假设性实现可以将其内部状态记录在非全局变量中,并在返回时仅设置全局变量。这样的实现将符合getopt()的POSIX规范,但所示的改动将无法起作用。 - Jonathan Leffler
5个回答

31

我知道这已经很老了,但我在寻找解决方案时遇到了它。

while((command = getopt(argc, argv, "a:")) != -1){

    switch(command){
        case 'a':

        (...)

        optind--;
        for( ;optind < argc && *argv[optind] != '-'; optind++){
              DoSomething( argv[optind] );         
        }

        break;
    }

我发现getopt()使用的extern参数int optind指向'当前argv'选定后的下一个位置;这就是为什么我在开头将其减少的原因。

首先,for循环检查当前参数值是否在argv的边界内(argc是数组的长度,所以数组argv中的最后一个位置是argc-1)。 第二部分的&&比较下一个参数的第一个字符是否为'- '。如果第一个字符是'-',则我们已经没有当前参数的下一个值,否则argv[optind]就是我们的下一个值。依此类推,直到argv结束或参数用尽。

最后递增optind以检查下一个argv

请注意,因为我们首先检查'optind < argc',所以除非第一部分为真,否则不会执行条件的第二部分,因此不必担心超出数组边界问题。

PS 我是个相当新的C程序员,如果有人有改进或批评,请分享一下。


3
这段话虽然比较老,但我想提出一点批评。你不仅应该检查“-”的情况,还要确保 strlen(argv[optind]) 等于 2。这将确保它能正确处理以破折号开头的参数。不过,这段代码对我很有帮助!+1 - TheBat
你是在说像 -whatever 这样的参数对吧,@TheBat?我有点困惑,因为你所说的对 getopt_long 是行不通的。 - user129393192
你是在说像 -whatever 这样的参数对吧,@TheBat?我有点困惑,因为你所说的对 getopt_long 是行不通的。 - undefined

11
如果你必须这样做,那么你可以从argv[optind]开始并自己增加optind。但是,我建议不要这样做,因为我认为这种语法形式很差。(你怎么知道何时到达列表末尾?如果有人的文件以-作为第一个字符命名呢?)
我认为最好改变你的语法,可以选择以下两种形式之一:
/a.out -i file1 -i file2 -i file3

或者将文件列表视为位置参数:

/a.out file1 file2 file3

谢谢jamesdlin,我会看一下[optind],因为除了-i之外,我还有很多参数。 - w00d

6

我查看并尝试了上面的代码,但我发现我的解决方案更简单,而且对我来说效果更好:

我需要的处理方式是:

-m mux_i2c_group mux_i2c_out

需要2个参数。

以下是我的实际应用示例:

case 'm':
    mux_i2c_group = strtol(optarg, &ch_p, 0);

    if (optind < argc && *argv[optind] != '-'){
        mux_i2c_out = strtol(argv[optind], NULL, 0);
        optind++;
    } else {
        fprintf(stderr, "\n-m option require TWO arguments <mux_group> "
                        "<mux_out>\n\n");
        usage();
    }

    use_mux_flag = 1;
    break;

这个程序首先像平常一样获取了第一个值,然后寻找第二个必需的值。


好的决定!谢谢!:) - alexanderzhirov

6
请注意,glibc的非一致参数排列扩展将破坏使用多个参数以此方式的任何尝试。在非GNU系统上,“-i的第二个参数”将被解释为第一个非选项参数,停止任何进一步的选项解析。考虑到这些问题,如果您想使用此语法,则应放弃getopt并编写自己的命令行解析器,因为它不是getopt支持的语法。

0

GoTTimw的解决方案对我非常有用。但是,我想提出另一个想法,这里还没有提出。

以这种方式将参数作为一个字符串传递。

./a.out -i "file1 file2 file3"

然后您会得到一个字符串作为单个参数,您只需要按空格拆分它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接