1

在阅读了这个关于如何使用的链接getopt()之后,我试图举一个小例子。

我想要的是这样的:

./prog -v      # show me prog version
./prog -f filename  # just show me the filename I entered from the command line

这是我到目前为止写的:

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

int
main(int argc, *argv[]) {
     char VER[] = "0.1.1";
     int opt;
     opt = getopt(argc, argv, "vf:");
     char *filename;

      while (opt != -1) {
           switch(opt) {
            case 'v':
                printf("version is %s", VER);
                break;
            case 'f':
                filename = optarg;
                break;
            }
     }
    printf("The filename was %s", filename);
    return 0;
}

我编译代码:

$ gcc prog.c -o prog -Wall -Wextra

当我使用选项运行它时,我似乎无法理解-v它永远不会停止打印版本并且-f filename它会停在那里并且永远不会打印我输入的文件名。

4

3 回答 3

3

It doesn't stop because you only call getopt() once. A possible fix:

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

int
main(int argc, char **argv)
{
    char VER[] = "0.1.1";
    int opt;
    const char *filename = "unspecified";

    while ((opt = getopt(argc, argv, "vf:")) != -1)
    {
        switch (opt)
        {
            case 'v':
                printf("version is %s\n", VER);
                break;
            case 'f':
                filename = optarg;
                break;
            default:
                fprintf(stderr, "Usage: %s [-v][-f file]\n", argv[0]);
                return(1);
        }
    }
    printf("The filename was %s\n", filename);
    return 0;
}

Note that I've made sure that filename is initialized, that printf() outputs end with a newline, and that the error cases are reported.

Here's another, slightly more complex, example program:

/* Example 1 - using POSIX standard getopt() */

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

int
main(int argc, char **argv)
{
    int opt;
    int i;
    int bflag = 0;
    int aflag = 0;
    int errflag = 0;
    char *ifile = 0;
    char *ofile = 0;

    while ((opt = getopt(argc, argv, ":abf:o:")) != -1)
    {
        switch (opt)
        {
        case 'a':
            if (bflag)
                errflag++;
            else
                aflag++;
            break;
        case 'b':
            if (aflag)
                errflag++;
            else
                bflag++;
            break;
        case 'f':
            ifile = optarg;
            break;
        case 'o':
            ofile = optarg;
            break;
        case ':':   /* -f or -o without operand */
            fprintf(stderr, "Option -%c requires an operand\n", optopt);
            errflag++;
            break;
        case '?':
        default:
            fprintf(stderr, "Unrecognized option: -%c\n", optopt);
            errflag++;
            break;
        }
    }

    if (errflag)
    {
        fprintf(stderr, "Usage: %s [-a|-b][-f in][-o out] [file ...]\n", argv[0]);
        exit(2);
    }

    printf("Flags: a = %d, b = %d\n", aflag, bflag);
    if (ifile != 0)
        printf("Input: %s\n", ifile);
    if (ofile != 0)
        printf("Output: %s\n", ofile);
    printf("Argc = %d, OptInd = %d\n", argc, optind);
    for (i = optind; i < argc; i++)
        printf("File: %s\n", argv[i]);
    return(EXIT_SUCCESS);
}

It is based on an example from a Sun manual. The -a and -b options are mutually exclusive. It illustrates (the limitations of) POSIX getopt() with 'optional arguments' enabled (the leading : on the option string). It also prints out its inputs at the end.

于 2013-09-01T03:18:11.977 回答
1

Here:

case 'v':
    printf("version is %s", VER);
    break;

the break is breaking you out of the switch statement, not out of the while loop, so the while loop continues and you go on forever because opt never changes. You're missing some logic, here, you probably want to be calling getopt() again somewhere in the loop.

于 2013-09-01T03:12:47.937 回答
1
int main(int argc, *argv[], "vf")   


getopt.c:5:20: error: expected declaration specifiers or â...â before â*â token
getopt.c:5:28: error: expected declaration specifiers or â...â before string constant

this should be

int main(int argc, char *argv[] )     

modified code:

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

int main(int argc, char *argv[])
  {
     char VER[] = "0.1.1";
     int opt;
   opt = getopt(argc, argv, "vf:");
     char *filename;

      while (opt != -1) {
           switch(opt) {
            case 'v':
                printf("version is %s\n", VER);
                exit(0);
            case 'f':
             //   filename = optarg;
                 printf("The filename was %s\n", argv[2]);
                exit(0);


            }
     }
    return 0;
于 2013-09-01T03:13:36.957 回答