biblioteca de processamento de linha de comando - getopt
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?
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.