Pergunta

Alguém pode me ajudar com a função getopt?

Quando eu fazer o seguinte na principal:

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;
    }
}

Estou executando este código no RHEL3 que usa versão antiga libc. Eu não sei qual deles para ser exato.

Agora o problema é getopt não funciona no segundo tempo com argv2. Mas se eu comente a primeira chamada getopt com argv1, ele funciona.

Alguém pode me dizer o que estou fazendo de errado aqui?

Foi útil?

Solução

argv1 e 2 deve terminar em 0:

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

Editar : OK, eu li a página man getopt e eu encontrei isto:

O OPTIND variável é o índice do próximo elemento a ser processado em argv. O sistema inicializa este valor a 1. O chamador pode redefini-la para 1 para reiniciar a digitalização do mesmo argv, ou quando a digitalização de um novo vetor de argumento.

Assim, fazendo OPTIND = 1 entre as duas chamadas em getopt faz com que funcione como esperado.

Outras dicas

A função getopt() usa algumas variáveis ??globais, como optind e optarg, a informação do estado loja entre as chamadas. Depois que você terminar o processamento de um conjunto de opções, não há dados deixados nessas variáveis ??que está causando problemas com o próximo conjunto de opções. Você poderia tentar redefinir o estado de getopt entre chamadas, limpando as variáveis, mas eu não tenho certeza de que iria trabalhar desde que a função pode usar outras variáveis ??que não são documentados e você nunca sabe se você tivesse todos eles obtido; além disso, seria absolutamente não portável (ou seja, se a implementação de mudanças getopt(), suas pausas de código). Veja a homem página para mais detalhes. Não melhor para uso getopt() por mais de um conjunto de argumentos em um determinado programa, se você pode ajudá-lo.

Eu não tenho certeza se existe uma função real para o estado de getopt reset (ou talvez uma versão de reentrada da função, que permite armazenar o estado em suas próprias variáveis) ... Eu me lembro de ter visto algo parecido uma vez, mas eu não posso encontrá-lo agora que eu olho: - /

Como afirmado na página man:

"Um programa que verifica vários vetores argumento, ou varrerá novamente o mesmo vector mais de uma vez, e quer fazer uso de extensões GNU como '+' e '-' no início do texto_opções, ou altera o valor do POSIXLY_CORRECT entre scans, deve reinicializar getopt (), redefinindo OPTIND a 0, em vez do valor tradicional de 1. (repor para 0 força a invocação de uma rotina de inicialização interna que verifica novamente POSIXLY_CORRECT e verifica se há extensões GNU em texto_opções). "

Existe alguma razão para que você não está usando getopt_long () em vez disso? Na maioria das plataformas, getopt () apenas chamadas _getopt_long () com um interruptor para argumentos longos com deficiência. Esse é o caso com quase todas as plataformas que eu saiba (ainda em uso), incluindo Linux, BSD e até mesmo emergente OS é como helenos -, eu sei, eu era o único que portado getopt à sua libc:)

É muito mais fácil em qualquer pessoa que use o seu programa para ter opções longas, pelo menos até que se acostumar a usá-lo.

getopt_long () irá permitir que você use dois (ou mais) índices de opção que pode ficar 'ao vivo' depois que eles são argumentos de processamento feito, apenas o interno (global, não reentrante) um teria que ser re-set que não é grande coisa.

Isso permite que você facilmente comparar a contagem de argumento para o número de opções realmente passaram em ambas as invocações com muitos outros benefícios .. por favor considere não usar a interface antiga.

Olhe para getopt.h, você verá o que quero dizer.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top