getopt_long() – 正确使用它的方法?

好的,我搜索过并发现以下两个StackOverflow主题让我朝着正确的方向前进:

C / UNIX的参数解析助手

从命令行将参数传递给C程序

注意:所有代码都是PSEUDO-CODE。 将在其工作时发布可编译代码。

但是,我仍然对如何在C中使用getopt_long()感到困惑。我正在编写的程序被定义为具有以下可能的标记(但可以包含您绝对需要的数量,其余用空值填充) ):

id3tagEd filename -title "title" -artist "artist" -year 1991 -comment "comment" -album "album" -track 1 

现在,根据我的阅读,我需要利用一个结构来获取长期选项,对吗? 如果是这样,我写了一些类似的东西:

 struct fields field = { char *[] title; char *[] artist; char *[] album; int year; char *[] comment; int track; } static struct options long_options[] = { {"title", 0, &field.title, 't'}, {"artist", 0, &field.artist, 'a'}, {"album", 0, &field.album, 'b'}, {"year", 0, &field.year, 'y'}, {"comment", 0, &field.comment, 'c'}, {"track", 0, &field.track, 'u'}, {0, 0, 0, 0} } 

现在,根据我收集的内容,我将通过以下方式调用它:

 int option_index = 0; int values = getopt_long(argc, argv, "tabycu", long_options, &option_index); 

从这里开始,我可以严格使用字段结构并在程序中执行我需要的操作吗? 但是,如果是这种情况,有人可以解释整个long_options结构吗? 我阅读了这些手册页,我只是完全糊涂了。 通过重读手册页,我可以看到我可以将变量设置为null,并且应该将所有选项要求设置为“required_argument”? 然后通过while()循环设置结构? 但是,我看到正在使用optarg。 这是由getopt_long()设置的吗? 或者是否从示例中遗漏了?

最后一个问题,我将始终有一个未命名的必需选项:filename,我只是使用argv [0]来获取访问权限吗? (因为我可以假设它将是第一个)。

在旁注中,这与作业问题有关,但它与修复它无关,它更多的是基础,必须首先通过命令行理解参数传递和解析。

首先,你可能不希望has_arg字段为0 – 它必须是no_argumentrequired_arguemntoptional_argument 。 在您的情况下,所有这些都将是required_argument 。 除此之外,你没有正确使用flag字段 – 它必须是一个整数指针。 如果设置了相应的标志, getopt_long()将使用通过val字段传入的整数填充它。 我认为你根本不需要这个function。 这是一个更好(缩短)的例子:

 static struct option long_options[] = { {"title", required_argument, NULL, 't'}, {"artist", required_argument, NULL, 'a'}, {NULL, 0, NULL, 0} }; 

然后,您可以适当地使用它(直接从联机帮助页,我添加了一些注释):

 // loop over all of the options while ((ch = getopt_long(argc, argv, "t:a:", long_options, NULL)) != -1) { // check to see if a single character or long option came through switch (ch) { // short option 't' case 't': field.title = optarg; // or copy it if you want to break; // short option 'a' case 'a': field.artist = optarg; // or copy it if you want to break; } } 

您可以根据需要扩展其他字段(并添加一些error handling,请!)。 注意 – 如果你想在你的例子中使用-title-artist ,你需要使用getopt_long_only() ,它没有短选项。

至于你的filename选项,你会把它作为'?'getopt_long()调用,所以你可以在那时处理它。 您的其他选择是要求它是第一个或最后一个选项并单独处理它。

如果你使用popt库,你将能够像在伪代码中那样创建一些智能:

 #include  #include "popt.h" struct _field { char *title; char *artist; /* etc */ } field; field.title = NULL; field.artist = NULL; /* HERE IS WHAT YOU WANTED IN YOUR PSEUDO-CODE */ struct poptOption optionsTable[] = { {"title", 't', POPT_ARG_STRING, &field.title, 't' "set the 'title' of the album" }, {"artist", 'a', POPT_ARG_STRING, &field.artist, 'a' "set the 'artist' of the album" }, POPT_AUTOHELP POPT_TABLEEND }; poptContext optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); poptSetOtherOptionHelp(optCon, "[OPTIONS]"); char c; while ((c = poptGetNextOpt(optCon)) >= 0) { switch (c) { case 't': /* do extra stuff only if you need */ break; case 'a': /* do extra stuff only if you need */ break; default: poptPrintUsage(optCon, stderr, 0); exit(1); } } if (field.title) printf("\nTitle is [%s]", field.title); if (field.artist) printf("\nArtist is [%s]", field.artist) 

比getopt聪明;)