www.samueldiasneto.com: Opções da linha de comando em C

Pesquisar em todo o site
Se esta página lhe ajudar, considere fazer uma doação

Processando opções da linha de comando na linguagem C

Para implementar o processamento da linha de comando em seus programas você pode usar as funções getopt() e getopt_long().

 

getopt ()

A função getopt() faz parte do arquivo de cabeçalho unistd.h e sua sintaxe é:

#include <unistd.h>

int getopt(int argc, char *argv[], char *opcoes)

extern *optarg;
extern optind;
extern opterrr;

onde argc e argv são os conhecidos argumentos de main e opcoes é uma string que armazena os caracteres de opção suportados pelo programa. A definição de opcoes deve ser algo como:

static char opcoes[] = "ab:c";

Observe que a letra b vem seguida de dois pontos. Isto indica que esta opção pode receber argumentos, o que não ocorre com as opções a e c.

A função getopt() ainda possui três variáveis externas que devem ser conhecidas pois serão utilizadas:

 

getopt funciona da seguinte maneira:

A linha de comando é analisada e a função retorna um valor inteiro. Cada chamada da função retorna um dos caracteres de opção passados. Ao retornar o caractere de opção, a variável optarg aponta para o argumento da opção, caso este exista. Ao final da análise, o valor -1 é retornado pela função. Neste ponto optind estará apontando para o primeiro argumento do programa. Por exemplo, digamos que a linha de comando a ser processada por getopt seja:

[nerd@aranha]$ gcc -Wall -g arquivo.c

a coisa funciona assim:

  1. getopt é chamada, analisa a linha de comando e retorna W. Como esta opção aceita argumentos e um argumento foi passado, optarg aponta para all.

  2. getopt é chamada novamente e agora retorna g.

  3. o processamento das opções termina e getopt retorna -1. optind estará com o valor 3 indicando que o primeiro argumento do programa é argv[3].

 

Para um melhor entendimento vamos a um exemplo usando getopt:

/* Processando opções da linha de comando com getopt() */

#include <stdio.h>
#include <unistd.h>

int main(int argc,char *argv[])
  {
    int opcao;
    static char opcoes[] = "ab:c";
    opterr = 0;

    while((opcao = getopt(argc,argv,opcoes)) != -1)
      switch(opcao)
        {
	  case 'a':
	    {	  
	      printf("opção -a escolhida.\n");
              break;
	    }   
          case 'b':
	    { 
              printf("opção -b escolhida.\n");
              printf("esta opção recebeu o argumento %s.\n",optarg);
              break;
            }
          case 'c':
	    {
	      printf("opção -c escolhida.\n");
              break;
	    }   
	  default:
	    printf("opção inválida!\n");
	}

      for(;optind < argc;optind++)
        printf("argv[%d] = %s\n",optind,argv[optind]);

      return(0);
  }

 

Executando nosso programa de exemplo:

nerd@aranha:~/C$ ./opcoes -a
opção -a escolhida.
nerd@aranha:~/C$ ./opcoes -b teste
opção -b escolhida.
esta opção recebeu o argumento teste.
nerd@aranha:~/C$ ./opcoes -c
opção -c escolhida.
nerd@aranha:~/C$ ./opcoes -d
opção inválida!

 

getopt_long()

Com getopt_long você pode processar opções longas tipo -- version. Esta função faz parte do arquivo de cabeçalho getopt.h e sua sintaxe é:

#include <getopt.h>

int getopt_long(int argc, char *argv[],
                char *opcoes,
		option *opcoes_longas,
		int *indice_opcoes_longas)

onde argc, argv e opcoes já são conhecidos. opcoes é uma string do tipo daquela mostrada no uso de getopt() acima.

O argumento opcoes_longas é um ponteiro para uma matriz de estruturas do tipo option. Esta estrutura é pré-definida em getopt.h e sua composição é:

struct option
  {
    const char *name;/* Nome da opção longa */
    int has_arg;     /* Diferente de zero se opção aceita argumento */
    int *flag;       /* NULL(zero) ou um ponteiro para um valor int */
    int val;         /* Valor de retorno */
  }

Abaixo segue um exemplo de como deve ser a declaração da matriz de estruturas do tipo option a ser usada com getopt_long:

static struct option opcoes_longas[]=
  {
    {"help",0,0,'h'},   /* name,has_arg,flag,val */
    {"version",0,0,'v'}, /* name,has_arg,flag,val */
    {0,0,0,0}
  };

O último elemento da matriz deve ter valor zero em todos os componentes da estrutura option.

flag e val trabalham em conjunto. Quando você quiser que getopt_long retorne uma letra que abrevia a opção longa, use como mostrado acima, ou seja, flag com o valor de zero e val com a letra a ser retornada.

Quando quiser usar flag você deve fazer assim:

static int chave = 0; /* iniciando a flag */
static struct option opcoes_longas[]=
  {
    {"help",0,0,'h'},
    {"version",0,&chave,1},
    {0,0,0,0}
  };

Neste caso, se a opção passada na linha de comando for "help" a função getopt_long retornará "h", simulando assim a passagem de uma opção curta, porém se a opção passada for "version", o valor 1 será armazenado na variável "chave"

O argumento indice_opcoes_longas é usado da seguinte maneira: um índice interno da função getopt_long inicia em zero e é usado para comparar a opção passada na linha de comando com o elemento opcoes_longas[índice].name. Se a opção passada for igual a opcoes_longas[índice].name, o índice é armazenado em indice_opcoes_longas para ser usado no processamento dos outros elementos da estrutura. Caso contrário o índice é incrementado e nova comparação é feita até o final da matriz de estruturas.

Vamos a um exemplo:

/* Processando opções da linha de comando com getopt_long() */

#include <stdio.h>
#include <getopt.h>

int main(int argc,char *argv[])
  {
    int opcao;
    static int chave = 0;
    int indice_opcoes_longas = 0;
    static char opcoes[] = "hg:c";
    static struct option opcoes_longas[]=
      {
        {"help",0,0,'h'},
	{"version",0,&chave,1},
	{0,0,0,0}
      };
    opterr = 0;

    while((opcao = getopt_long(argc,argv,
                               opcoes,
                               opcoes_longas,
			       &indice_opcoes_longas)) != -1)
      switch(opcao)
        {
	  case 0:
            break;
	  case 'h':
	    {
	      printf("Exibindo ajuda.\n");
              break;
	    }
          case 'g':
	    {
              printf("opção -g escolhida.\n");
              printf("esta opção recebeu o argumento %s.\n",optarg);
              break;
            }
          case 'c':
	    {
	      printf("opção -c escolhida.\n");
              break;
	    }
	  default:
	    printf("opção inválida!\n");
	}

      if(chave != 0)
        printf("Versão 1.0\n");
	return(0);

  }

 

Executando o programa:

nerd@aranha:~/C$ ./opcoes_longas -h
Exibindo ajuda.
nerd@aranha:~/C$ ./opcoes_longas -g teste
opção -g escolhida.
esta opção recebeu o argumento teste.
nerd@aranha:~/C$ ./opcoes_longas -c
opção -c escolhida.
nerd@aranha:~/C$ ./opcoes_longas --version
Versão 1.0
nerd@aranha:~/C$ ./opcoes_longas -b
opção inválida!
nerd@aranha:~/C$ ./opcoes_longas --debug
opção inválida!

Se esta página lhe ajudou, considere fazer uma doação