我之所以提出这个问题,是因为没有多少关于如何为每个循环分配这个optind的信息。
Man page说:
变量optind是要在argv中处理的下一个元素的索引。系统将此值初始化为1。
下面,我有一个从Head First C得到的简单代码,在代码中,我们从“argc”中减去“optind”,得到剩余参数的数量,然后我们将使用这些参数作为“成分”打印剩余参数。

#include <unistd.h>
#include <stdio.h>
int main(int argc, char* argv[]) {
char* delivery = "";
int thick = 0 ;
int count = 0;

char ch;,

for(int i = 0; i < argc;i++){
//This is , to show the whole array and their indexes.
    printf("Argv[%i] = %s\n", i, argv[i]);
}
while((ch = getopt(argc, argv, "d:t")) != -1 ){
    switch(ch) {
        case 'd':
            printf("Optind in case 'd' : %i\n",optind);
            delivery = optarg;
            break;
        case 't':
            printf("Optind in case 't' : %i\n",optind);
            thick = 1;
            break;
        default:
            fprintf(stderr,"Unknown option: '%s'\n", optarg); // optional argument.
            return 1;
    }
}
    argc -= optind;
    argv += optind;
    printf("Optind : %i and Argc after the subctraction : %i\n",optind,argc);
    if(thick)
        puts("Thick crust");
    if(delivery[0]){
        printf("To be delivered %s\n", delivery);
    }

    puts("Ingredients:");
    for(count = 0; count < argc ; count ++){
        puts(argv[count]);
    }
    return 0;
}

因此,在代码的开头,for循环将写入所有数组及其索引,以查看差异。
然后我运行代码:
./pizzaCode -d now Anchovies Pineapple -t //-t is intentionally at the end

有人告诉我,如果标志在末尾,它就不会出现在't'的情况下,但不知怎么的,它在我的ubuntu上工作。这是我想知道的另一件事,但不是主要问题。
因此输出如下:
Argv[0] = ./pizzaCode
Argv[1] = -d
Argv[2] = now
Argv[3] = Anchovies
Argv[4] = Pineapple
Argv[5] = -t
Optind in case 'd' : 3
Optind in case 't' : 6
Optind : 4 and Argc after the subctraction : 2
Thick crust
To be delivered now
Ingredients:
Anchovies
Pineapple

到目前为止一切都很好,问题是argv[0]和argv1怎么变成了凤尾鱼和菠萝?
2-还有一个问题是optind是如何变成3的?因为d的索引是1,下一个索引是2。
循环后optind怎么变成4?在“t”的情况下是6。
我希望我的问题对你们大家都是清楚的,我只是想理解逻辑,而不是去记住它。
提前谢谢你!

最佳答案

manpage for Gnu getopt记录了这一非标准实施:
默认情况下,getopt()在扫描时排列argv的内容,因此最终所有非选项都在末尾。
这实际上并不完全正确;正如您在示例中看到的那样,排列发生在扫描最后一个选项之后。但是效果是一样的;argv被排列,这样非选项就在最后,optind被修改为索引第一个非选项。
如果要避免排列,以便getopt按照Posix执行:
如果optstring的第一个字符是“+”或设置了环境变量POSIXLY_CORRECT,则一旦遇到非option参数,选项处理就会停止。
在这种情况下,不进行置换,并保留optind的值。
设置POSIXLY_CORRECT还有其他的后果,在手册页中有各种Gnu实用程序的记录。我的习惯是使用+作为选项字符串的第一个字符(除非我真的想要非Posix行为),但是可以说设置环境变量更容易移植。
对于您的具体问题:
为什么在argv[0]argv[1]处有非选项参数?
因为您修改了argv:argv += optind;
为什么optind3 in-the-loop processing选项-d
因为这个选项需要一个参数。所以下一个参数是now参数后面的参数,它已经被处理过了(通过将指向它的指针放入optarg中)。
optind是怎么变成4的?
如上所述,在对argv向量进行置换之后对其进行修改,以便optind成为第一个“未处理”非选项参数的索引。

10-08 00:00