9

我正在传递我的程序输入,我可以在 argv 中看到它们,但 getopt 似乎没有我期望的参数。

这就是我运行我的 prog 的方式:./my_prog -X -f 文件名

<snip>
while ((opt = getopt(argc, argv, "Xf:eE:dD")) != EOF) {
    switch (opt) {
       case 'X':
       case 'f':
                if (optarg == NULL)
                fput("no point of living", fp);         << for debugging

</snip>

我总是将 optarg 设为空。为什么?

4

4 回答 4

12

您的参数字符串在 X 之后没有 :(例如 X:f),因此 optarg 将始终为空。

我还要指出,通常在 switch 语句中,您需要在每个 case 之后中断(通常,并非总是如此,但通常在解析参数时),所以:

switch ( ... ) {
    case 'X': {
        // do something
    } break;

    case 'f': {
        // do something else
    } break;
}
于 2011-06-23T06:33:43.910 回答
2

我刚刚处理了这个问题,看来这个问题从未得到完全回答。

您必须确保opterr = 0在调用之前设置了外部 libc 变量getopt;如果您不重置它并且getopt之前在系统中使用它的任何地方的另一个应用程序中出现错误,则该参数将失败。我还要重申现有的观点,因为在那之后你没有中断声明,case 'X':这是一个问题的明确迹象,因为它会失败。

getopt一次只处理一个参数,因此从案例X到案例f是一件坏事。在 a 的每个 case 语句中,您应该始终有一个中断,switch除非您绝对确定它应该通过(这在我的经验中非常罕见)。作为另一种一般的良好做法,您应该始终将代码块包含在 { } 中(指您的条件),除非它是一个return语句或break导致程序流退出当前或父块范围或进入的东西通过函数或方法调用的新作用域。

我认为您的选项字符串 Xf:eE:dD 很好。这表明:

1) 以下将只是始终具有空参数的选项标志:XedD

2) 以下选项需要一个参数:fE

如果这是您正在寻找的功能,那么给定的选项字符串就可以了。如果您使用的是 GNU libc,则根据上述其他答案,您可以在选项字符串中的选项之后使用 :: 来指示该选项可能有一个参数,但不是必须的。

所以在你的文件顶部确保你至少有:

extern int opterr;

然后在您getopt第一次在代码中调用之前,将其设置opterr为 0。

例如

opterr = 0;

while ((opt = getopt(argc, argv, "Xf:eE:dD")) != EOF) {
    switch (opt) {
       case 'X':
       case 'f':
                if (optarg == NULL)
                fput("no point of living", fp);         << for debugging

这至少应该可以部分解决您的问题。这是一个示例的链接:

http://www.gnu.org/software/libc/manual/html_node/Example-of-Getopt.html

干杯,

乔恩

于 2014-06-20T16:07:09.267 回答
2

还有谁可以访问此页面:来自http://www.gnu.org/software/libc/manual/html_node/Using-Getopt.html#Using-Getopt An option character in this string can be followed by a colon (‘:’) to indicate that it takes a required argument. If an option character is followed by two colons (‘::’), its argument is optional; this is a GNU extension.

所以在你的论点中你可以使用:“X:f:e:E:d:D:”

有同样的问题。

于 2012-03-30T07:47:09.553 回答
0

我知道这很旧,但我最近注意到几年前我使用 getopt 的方式发生了变化。也许这是一个不同的环境,但我发现今天使用它需要 optarg 直接在标志之后(没有空格),否则 optarg 为空。

使用您的示例,替换./my_prog -X -f filename./my_prog -X -ffilename

我发现它工作正常,即使感觉不对。希望这对其他人有所帮助。确保尝试两种方式。

于 2021-07-09T16:05:05.103 回答