对于某些选项顺序,Getopt返回-1

时间:2013-11-03 22:37:09

标签: c linux unix getopt

当我在其他选项之前有非选项时,基本上getopt返回-1。

    n = atoi(argv[1]);

    while ((opt = getopt(argc, argv, "hi:o:")) != -1) {
        switch (opt) {
        case 'i':
            ifile = optarg; 
            break;
        case 'o':
            ofile = optarg; 
            break;
        case 'h':
            printf("...");
            break;
        default:
            printf("Invalid Option\n");
            exit(0);
        }
    }

示例:

./a.out 22 -i infile -o outfile

这使得getopt返回-1并且switch语句永远不会被执行。

./a.out -i infile -o outfile

然而这是有效的,但我真的希望第一个选项只是一个数字,而不必包含另一个选项。

我认为getopt应该处理这个案子,但我可能是错的。任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:1)

通用解决方案

解决问题的最简单方法是:

n = atoi(argv[1]);

argv[1] = argv[0];
++argv;
--argc;

while ((opt = getopt(argc, argv, "hi:o:")) != -1)
{
    ...as before...
}

这有效地消耗了第一个选项,然后将事物重新设置为正统格式。这适用于远程符合标准的任何版本getopt()(事实上和法律上)。请注意,如果您不重新分配argv[1] = argv[0];getopt()将使用原始argv[1]中的值(此示例中的数字)作为“程序名称”。

使用GNU getopt()

使用GNU getopt(),有两种方法可以解决这个问题。一个使用'按顺序返回'功能,以便将非选项('文件名')参数视为前缀为选项字符代码1(ASCII SOH控制字符;又名 Control-A )。另一个使用默认模式,getopt()在处理选项时置换选项。请注意,默认情况下,这在Mac OS X和其他平台上不可用。

这段代码几乎完成了两项工作;您只需使用"-hi:o:"更改“置换”模式(显示)和“按顺序返回”模式之间的选项字符串。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>

int main(int argc, char **argv)
{
    int n;
    int opt;
    char *ifile = 0;
    char *ofile = 0;

    n = atoi(argv[1]);

    while ((opt = getopt(argc, argv, "hi:o:")) != -1)
    {
        printf("Option: %c\n", opt);
        switch (opt)
        {
        case 'i':
            ifile = optarg;
            break;
        case 'o':
            ofile = optarg;
            break;
        case 'h':
            printf("...");
            break;
        case 1:
            n = atoi(optarg);
            break;
        default:
            printf("Invalid Option %d\n", opt);
            exit(1);
        }
    }

    printf("argc = %d; optind = %d\n", argc, optind);
    for (int i = optind; i < argc; i++)
        printf("argv[%d] = %s\n", i, argv[i]);

    if (ifile != 0)
        printf("i-file: %s\n", ifile);
    if (ofile != 0)
        printf("o-file: %s\n", ofile);
    printf("%d\n", n);

    return 0;
}

使用'permute'运行示例:

$ go9 9 -i in -o out
Option: i
Option: o
argc = 6; optind = 5
argv[5] = 9
i-file: in
o-file: out
9
$

使用'按顺序返回'运行示例:

$ go9 9 -i in -o out
Option: 
Option: i
Option: o
argc = 6; optind = 6
i-file: in
o-file: out
9
$

如果您希望这样做,请确保没有设置环境变量POSIXLY_CORRECT。您可以在选项字符串前加+作为强制类似POSIX的行为。