【问题标题】:command line processing library - getopt命令行处理库 - getopt
【发布时间】:2009-02-11 07:37:53
【问题描述】:

有人可以帮助我使用 getopt 功能吗?

当我在 main 中执行以下操作时:

char *argv1[] = {"testexec","-?"}; char *argv2[] = {"testexec","-m","arg1"}; int cOption; /* test for -? */ setvbuf(stdout,(char*)NULL,_IONBF,0); printf("\n argv1 "); while (( cOption = getopt (2, argv1, "m:t:n:fs?")) != -1) { switch(cOption){ case 'm': printf("\n -m Arg : %s \n",optarg); break; case '?': printf("\n -? Arg "); break; case 'n': printf("\n -n Arg : %s \n",optarg); break; } } printf("\n argv2 "); while (( cOption = getopt (3, argv2, "m:t:n:fs?")) != -1) { switch(cOption){ case 'm': printf("\n -m Arg : %s \n",optarg); break; case '?': printf("\n -? Arg : %s \n",optarg); break; case 'n': printf("\n -n Arg : %s \n",optarg); break; } }

我在使用旧 libc 版本的 rhel3 上运行此代码。不知道具体是哪一个。

现在的问题是 getopt 第二次无法使用 argv2。 但是如果我用 argv1 注释掉第一个 getopt 调用,它就可以工作。

谁能告诉我我在这里做错了什么?

【问题讨论】:

    标签: c getopt


    【解决方案1】:

    argv1 和 2 必须以 0 结尾:

    char* argv1[] = {"par1", "par2", 0};
    

    编辑:好的,我阅读了 getopt 手册页,发现了这个:

    变量 optind 是 argv 中要处理的下一个元素的索引。系统初始化这个值 为 1。调用者可以将其重置为 1 以重新开始扫描相同的 argv,或者在扫描新的参数向量时。

    因此,在 getopt 的两个调用之间设置 optind=1 可以使其按预期工作。

    【讨论】:

    • 很好的答案,虽然这肯定是真的,但我尝试在示例代码中更改它,但它并没有解决所询问的特定问题。
    • 大卫,你是对的。我刚刚发现了那个错误并忘记了其余的:) 我编辑了答案,因为我注意到如果你将 optind 值更新为 1,代码会按预期工作。问候
    • 当心:POSIX 标准并未声明将 optind 重置为 1 会将 getopt() 重置为初始状态,尤其是在您没有完全解析第一个参数的情况下。例如,如果第一个参数是 -xy 并且您在处理 x 后停止,则不能保证 optind 的重置有效。
    【解决方案2】:

    getopt() 函数使用一些全局变量,如optindoptarg,来存储调用之间的状态信息。处理完一组选项后,这些变量中会留下导致下一组选项出现问题的数据。您可能会尝试通过清除变量在调用之间重置getopt 的状态,但我不确定这是否会起作用,因为该函数可能会使用其他未记录的变量并且您永远不会知道您是否会得到他们所有;此外,它绝对是不可移植的(即,如果getopt() 的实现发生变化,你的代码就会中断)。有关详细信息,请参阅man page。如果您能提供帮助,最好不要在给定程序中将getopt() 用于一组以上的参数。

    我不确定是否有一个实际的函数来重置getopt 的状态(或者可能是该函数的可重入版本,它可以让您将状态存储在自己的变量中)...我似乎记得曾经看到过类似的东西,但现在我找不到了:-/

    【讨论】:

      【解决方案3】:

      如手册页所述:

      "扫描多个参数向量的程序,或多次重新扫描同一向量,并希望在 optstring 的开头使用 GNU 扩展,例如 '+' 和 '-',或更改 POSIXLY_CORRECT 的值在两次扫描之间,必须通过将 optind 重置为 0 而不是传统值 1 来重新初始化 getopt()。(重置为 0 会强制调用内部初始化例程,该例程重新检查 POSIXLY_CORRECT 并检查 optstring 中的 GNU 扩展。)"

      【讨论】:

        【解决方案4】:

        您有什么理由不使用 getopt_long() 代替吗?在大多数平台上,getopt() 只是调用 _getopt_long() 并带有一个开关来禁用长参数。我知道(仍在使用)的几乎所有平台都是这种情况,包括 Linux、BSD 甚至像 HelenOS 这样的新兴操作系统——我知道,我是将 getopt 移植到它的 libc 的人 :)

        对于使用您的程序的任何人来说,至少在他们习惯使用它之前拥有较长的选项会容易得多。

        getopt_long() 将允许您使用两个(或更多)选项索引,它们在处理完参数后可以保持“活动”状态,只有内部(全局、不可重入)一个必须重新设置没什么大不了的。

        这使您可以轻松地将参数计数与两次调用中实际传递的选项数量进行比较,并具有许多其他好处。请考虑不要使用过时的接口。

        看看getopt.h,你就会明白我的意思了。

        【讨论】:

        • 定义大多数平台? HP-UX、Solaris、AIX - getopt() 不调用 getopt_long()。这是 6 个 Unix 变体中的 3 个(BSD、Linux、MacOS X 是其他重要的变体)。
        猜你喜欢
        • 1970-01-01
        • 2018-05-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-05-01
        • 1970-01-01
        相关资源
        最近更新 更多