【问题标题】:getopt_long() doesn't see terminatorgetopt_long() 看不到终结符
【发布时间】:2014-04-30 16:53:34
【问题描述】:

我正在开发一个 C 程序,它使用 getopt 读取选项,然后遍历 argc 的其余部分以读取非可选参数。其中一些非可选参数是数字,其中一些是负数。常见问题,我知道,并且我理解修复只是在选项的结尾和非可选参数的开头之间放置一个“--”终止符。但是,这似乎不适用于我当前的设置。

这是读取可选和非可选参数的代码的 sn-p:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <math.h>

static const struct option longOpts[] = {
  {"inputconstheight", required_argument, 0, 'c'},
  {"inputheightfile", required_argument, 0, 'f'},
  {"alongtrackfile", required_argument, 0, 'g'},
  {"crosstrackfile", required_argument, 0, 'h'},
  {"lensconstant", required_argument, 0, 'm'},
  {"nonlinearoptics", required_argument, 0, 'n'},
  {"verbose", required_argument, 0, 'v'},
  {"rolloffset", required_argument, 0, 'x'},
  {"pitchoffset", required_argument, 0, 'y'},
  {"yawoffset", required_argument, 0, 'z'},
  {0, 0, 0, 0}
};

    int main(int argv, char **argc)
    {
    //skipping variable declaration for brevity
      while((opt = getopt_long(argv, argc, "cef:", longOpts, &longIndex))!=-1)
        {
          switch(opt)
        {
        case 'c': //constheight
          constantheightflag=1;
          constantheight=atof(optarg);
          break;
        case 'f': //inputheightfile
          constantheightflag=0;
          inputheightfilename=optarg;
          break;
        case 'g': //alongtrackfile
          inputalongtrackanglefilename=optarg;
          break;
        case 'h': //crosstrackfile
          inputcrosstrackanglefilename=optarg;
          break;
        case 'm': //lensconstant
          lensconstantflag=1;
          lensconstant=atof(optarg);
          break;
        case 'n': //nonlinearopticsflag
          nonlinearoptics=atoi(optarg);
          break;
        case 'v': //verbose
          verboseflag=1;
          break;
        case 'x': //rolloffset
          rolloffset=atof(optarg);
          break;
        case 'y': //pitchoffset
          pitchoffset=atof(optarg);
          break;
        case 'z': //yawoffset
          yawoffset=atof(optarg);
          break;
        case '?': 
          opterror=1;
          break;
        }
        }

      /*get non-optional arguments*/
      if((opterror==1)||((argv-optind)!=14)) {
        printf("Usage: geolocateplane -[cfghmnvxyz] -- outputlatfile outputlonfile imagexsize imageysize detectorxsize detectorysize fov_x fov_y lat lon alt roll pitch yaw\n");
        return 1;}
      else {
        outputlatfilename=argc[optind+0];
        outputlonfilename=argc[optind+1];
        imagexsize=atoi(argc[optind+2]);
        imageysize=atoi(argc[optind+3]);
        detectorxsize=atof(argc[optind+4]);
        detectorysize=atof(argc[optind+5]);
        fov_x=atof(argc[optind+6]);
        fov_y=atof(argc[optind+7]);
        cameralat=atof(argc[optind+8]);
        cameralon=atof(argc[optind+9]);
        cameraalt=atof(argc[optind+10]);
        cameraroll=atof(argc[optind+11]);
        camerapitch=atof(argc[optind+12]);
        camerayaw=atof(argc[optind+13]);
      }

这里是函数调用和输出:

XXXXXX:~/XXXX$ /XXX/geolocateplane --inputconstheight=0 --nonlinearoptics=0 --lensconstant=5.9982225412 --rolloffset=-1.0 --pitchoffset=-0.7 --yawoffset=0.0 --verbose -- /XXX/PACS.20130122.red.020756.lat.dat /XXX/PACS.20130122.red.020756.lon.dat 1024 1024 18.0 18.0 110 110 36.2927288472 -119.6177822504 19875.8 -0.3 0.7 -26.9
/XXX/geolocateplane: invalid option -- '1'
/XXX/geolocateplane: invalid option -- '1'
/XXX/geolocateplane: invalid option -- '9'
//etc...etc...

知道为什么会发生这种情况,或者解决方法是什么?

【问题讨论】:

  • GNU getopt() 不能以 POSIX-ly 正确的方式工作,除非您通过在环境中设置 POSIXLY_CORRECT=1(任何值)来告诉它。虽然因为-- 应该没问题,除非-- 前面的选项应该是一个参数,在这种情况下-- 可以被视为参数(到--verbose)。遗憾的是,您没有显示长选项数据结构。
  • 我添加了数据结构,你解决了我的问题。我不小心将 --verbose 保留为“required_argument”。我将其更改为“no_argument”,代码现在可以工作了!谢谢!关于 POSIXLY_CORRECT=1,我应该添加到我的 .bashrc 中吗?
  • "... 在这种情况下 -- 可以被视为参数(对 --verbose)。" 得到他...;) @JonathanLeffler跨度>
  • 由你决定......可能不会。一两年前,我不得不调试的一个更棘手的问题是,当我运行它时其他人的脚本失败了,因为我的环境中有 POSIXLY_CORRECT,而他们根本没想到会这样。从某种意义上说,当您使用getopt_long() 时,POSIX 正确性无关紧要;整个多头期权不是 POSIX。有时您需要意识到这一点。在这种情况下,问题在于所需的参数。
  • @JonathanLeffler 你会把这个放在答案中吗?

标签: c getopt-long


【解决方案1】:

尝试 1

GNU getopt() 不能以 POSIX 正确的方式工作,除非您通过在环境中设置 POSIXLY_CORRECT=1(任何值)来告诉它。话虽如此,您的示例应该没问题,因为-- 除非-- 之前的选项应该带一个参数,在这种情况下-- 将被视为参数(到--verbose)。

很遗憾,您没有展示长选项数据结构。

尝试 2

更新后,问题不言而喻:--verbose 需要一个参数,所以它确实咀嚼了 -- 作为其选项参数,留下该行的其余部分容易被误解。

设置或不设置 POSIXLY_CORRECT

我不喜欢 POSIX 错误的行为,但其他人喜欢它。这意味着当您希望将以下参数视为非选项参数时,您必须小心使用--

但是,设置 POSIXLY_CORRECT 也会使事情变得混乱。我有我设置的系统和其他我不设置的系统。两者都有效。

平均而言,最好不要设置它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-21
    • 2022-09-28
    • 2011-11-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多