GETOPT

1. GETOPT

Fernando Oliveira
Ferdy1976

(usa Nenhuma)

Enviado em 20/10/2006 - 00:48h

Viva,

Quero fazer um programa que me permita mudar uma série de opções. E sim, sou um bocadito nabo nisto, mas vou aprendendo ;)

Descobri o getopt e achei fantástico as possibilidades, no entanto surgiram mais alguns problemas :(

O programa faz sempre alguma coisa pois algumas varíáveis são inicializadas no início do programa.


while (( param = getopt(argc, argv, "t:i:n:q:f:"))!=-1){
switch(param){
case 't':
n_sect=atoi(optarg);
break;
case 'i':
noi = atoi(optarg);
break;
case 'n':
var_nome=optarg;
break;
case 'q':
no_query = 1;
break;
case 'f':
clear_dt=1;
break;

O problema está nas 2 primeiras opções nas quais eu só queria aceitar inteiros, mas se alguém põe a opção 'hjkhk' ele aceita na mesma e transforma em inteiro. Estava a pensar nesta solução:

if (optarg == NULL){
perror("Valor inexistente: ");
uso();
}

i=1;
While (optarg[i]!=null){
if ((optarg[i]-'0'>=0) &&(optarg[i]-'0'<=9)){
i++;
else
perror("Argumento inválido: ");
uso();
}
}


já agora:
void uso(void)
{
perror("\nErro de formato.\n %s\n [-t n_sect] [-i noi] [-n name] [-q] [-f]\n", strerror( errno ) );
fprintf(" -t n_sect: number of sectors\n" );
fprintf(" -i noi: number of inodes\n" );
fprintf(" -n name: volume label (default \"(no name)\"\n");
fprintf(" -q: suppress output\n");
fprintf(" -f: clear data sectors (default: don\'t clear)\n");
exit(EXIT_FAILURE);
}

Para o caso do 'n' é fácil pois quaisquer chars ele aceita.

Para os 2 últimos outro problema pois estas 2 opções são apenas semáforos, isto é ON/OFF. Se alguém puser qualquer coisa à frente deveria sair imediatamente. Assim, estava a pensar por esta linha de comando no 'q' e 'f':

if (optarg!=NULL)
uso();

Gostaria de ler comentários sejam eles bons ou maus. Algumas ideias se possível. Agradeço desde já o facto de não terem adormecido até esta zona do tópico.

Obrigado


  


2. Reposta

Marcos Paulo Ferreira
daemonio

(usa Slackware)

Enviado em 16/11/2006 - 10:22h

Aí, já faz bem tempo que você postou esta dúvida, talvez você já a tenha a esclarecido;

Bom,eu recomendaria para você o uso da função getopt_long ao invés de getopt. A getopt_long oferece tudo que a getopt oferece e ainda mais, você pode criar opções do estilo "--help" "--delete",
pequenas "-h" -d" e flags (semáfaros como você disse) "--interactive" "--force" .. etc.

Bom, no 1º paragráfo, você colocou:
if ( optarg == NULL ) ...

Não precisa, getopt já testa isto para você. Quando você usa a letra da opção seguida de ':', getopt obriga o usuário a usar um argumento para esta opção, mostrando uma mensagem de erro e retornando '?' em optopt.

Em:
While (optarg[i]!=null){
if ((optarg[i]-'0'>=0) &&(optarg[i]-'0'<=9)) /*...*/

Você pode testar se optarg é um número, através de um if em cada case no switch.

case 'i': /* opcao flag i */
if ( optarg[0] == '0' ) // o número é zero?
noi = 0 ;
else if ( atoi(optarg) != 0 ) /* !=0 em caso de acerto */
noi = atoi(optarg) ;
/* pequeno exemplo, testa aí para ver
se dá certo. */
break ;


Agora no segundo caso, onde você queria que o programa saísse caso usasse uma opção flag (ou semáforo) com argumento, você poderia tirar
o ':' do parâmetro de getopt(). ficaria:

getopt(argc, argv, "t:i:n:qf") ...

O ':' representa "opção que recebe argumento", como elas duas (-q e -f) não recebem, então não precisa do ':'.

Testa aí e manda um reply se puder. Tenho tutoriais aqui sobre getopt e getopt_long se quiser mando para você.

[]'z
Daemonio






Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts