Getopt - 为缺少选项和缺少非选项参数添加案例

时间:2016-04-27 20:37:51

标签: c getopt

我正在制作一个更大的程序的一部分,这部分从文本文件或标准输入的提要中获取信息,这些信息的性质取决于添加到程序的选项。如果没有将文本文件添加为非选项参数,则程序应从stdin中读取。

例如:

fizzle.exe -a textfile.txt 以-a

选项的方式读取textfile.exe

fizzle.exe -a 以选项a规定的方式读取标准输入

我还没有开始工作的是:

fizzle.exe textfile.txt 以规定的方式读取textfile.txt(或stdin,如果没有正确的文本文件),不提供选项

这是我的代码:

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

    FILE *pointerFile = filereader(optarg);

    switch(option) {
        case 'a' :
            optionchosen = 0;
            counter(optionchosen,pointerFile,argv);
            break;

        case 'b' :
            optionchosen = 1;
            counter(optionchosen,pointerFile,argv);
            break;


        case ':' :
            counter(optionchosen,pointerFile,argv);
            break;          

    }
}

我无法弄清楚如何通过不提供选项来激活此开关的情况,但仍然可以使用或不使用非选项参数(文件名)。

3 个答案:

答案 0 :(得分:2)

嗯,您可以使用getopt完成您想要做的事情,等等,您只需稍微调整一下逻辑。具体来说,您可以设置getopt以便:

fizzle.exe                        /* reads from stdin   */
fizzle.exe -a                     /* reads from stdin   */
fizzle.exe -a textfile.txt        /* reads textfile.txt */
fizzle.exe textfile.txt           /* reads textfile.txt */

以下是围绕-a选项实现上述逻辑的简短示例。最后一种情况还指出,如果给出,在给出所有选项之后,第一个未处理的选项也将被视为要读取的文件名。

#include <stdio.h>
#include <unistd.h> /* for getopt */

int main (int argc, char **argv) {

    int opt;
    char *fn = NULL;
    FILE *pointerFile = stdin;  /* set 'stdin' by default */

    while ((opt = getopt (argc, argv, "a::b:")) != -1) {
        switch (opt) {
            case 'a' :  /* open file if given following -a on command line */
                if (!optarg) break;     /* if nothing after -a, keep stdin */
                fn = argv[optind - 1];
                pointerFile = fopen (fn, "r");
                break;
            case 'b' :; /* do whatever */
                break;
            default :   /* ? */
                fprintf (stderr, "\nerror: invalid or missing option.\n");
        }
    }
    /* handle any arguments that remain from optind -> argc
     * for example if 'fizzle.exe textfile.txt' given, read from
     * textfile.txt instead of stdin.
     */
    if (pointerFile == stdin && argc > optind) {
        fn = argv[optind++];
        pointerFile = fopen (fn, "r");
    }

    printf ("\n fizzle.txt reads : %s\n\n", pointerFile == stdin ? "stdin" : fn);

    return 0;
}

示例使用/输出

$ ./bin/optfizzle

 fizzle.exe reads : stdin

$ ./bin/optfizzle -a

 fizzle.exe reads : stdin

$ ./bin/optfizzle -a somefile.txt

 fizzle.exe reads : somefile.txt

$ ./bin/optfizzle someotherfile.txt

 fizzle.exe reads : someotherfile.txt

仔细看看,如果您有任何问题,请告诉我。

答案 1 :(得分:1)

忘记 getopt 字符串中的前导:;只需使用getopt选项。完成它们后,命令行中的其余元素(如果有)将在argv[optind]argv[argc]之间找到。

如果来电者未提供文件名,请使用/dev/stdin作为默认值,或使用 stdlib.h 中的stdin。无需要求用户提供-代表标准输入。

答案 2 :(得分:0)

如果你给它一个getopt作为输入参数,按照惯例,使用-的程序应该从stdin中读取。

作为旁注,您应始终拥有?(或default案例)的案例。

以下是读取其余参数的示例,将其放在处理所有while标志的大getopt循环下面:

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