Argparse
O processamento dos argumentos de linha de comando é necessário em diferentes programas, e boa parte dele pode ser generalizada. De fato, existem bibliotecas que oferecem recursos para realizar o processamento dos argumentos:
- getopt: função da biblioteca C padrão
- Biblioteca Program_options: biblioteca composta por classes e funções (parte da suite C++ boost)
Ambas opções acima são bastante utilizadas e completas. No entanto, por se pretenderem genéricas, apresentam alguns detalhes a serem bem compreendidos para que possam ser utilizadas (veja os manuais). Uma alternativa é esta pequena classe cujos objetos processam os argumentos de forma simplificada:
A classe Argparse é capaz de processar argumentos com opções curtas e longas, com ou sem valores complementares. Algumas definições podem esclarecer isso:
- Opção curta: informada com uma única letra e precedida por um hífen. Ex: -f
- Opção longa: informada com duas ou mais letras e precedida por dois hífens. Ex: --tipo
- Opção com valor complementar: a opção pede um valor. Ex: -p /home, --tipo arquivo
- Opção sem valor complementar: nenhum valor deve ser acrescentado à opção. Ex: -b, --path.
Valores complementares de opções são sempre do tipo string. Opções sem valor complementar, chamadas de flag, possuem valor bool (true se opção aparece na linha de comando, false caso contrário).
A classe Argparse possui esta interface:
class Argparse {
public:
Argparse();
Argparse(const Argparse& orig);
virtual ~Argparse();
// Métodos para adicionar uma opção do tipo flag. Tal tipo de opção
// não requer um valor a ser informado na linha de comando.
// Ela é do tipo bool: se aparece na linha de comando seu valor é true,
// e, caso não apareça, seu valor é false.
void add_flag(char shortoption);
void add_flag(const string & longoption);
// Métodos para adicionar uma opção do tipo flag com um valor
// predefinido
void add_flag(char shortoption, bool defval);
void add_flag(const string & longoption, bool defval);
// Métodos para adicionar uma opção comum. Tal tipo de opção
// requer um valor a ser informado na linha de comando.
// Ela é do tipo string: se aparece na linha de comando, a string que a sucede
// se torna seu valor. Caso essa opção não apareça, seu valor é uma string vazia.
void add_option(char shortoption);
void add_option(const string & longoption);
// Métodos para adicionar uma opção comum com um valor
// predefinido
void add_option(char shortoption, const string & defval);
void add_option(const string & longoption, const string & defval);
// Métodos para obter o valor de uma opção comum
string get_option(char shortoption) const;
string get_option(const string & longoption) const;
string operator[](const string & longoption) const;
string operator[](char shortoption) const;
// Métodos para obter o valor de uma opção do tipo flag
bool get_flag(char shortoption) const ;
bool get_flag(const string & longoption) const;
// Método para obter os argumentos que não foram processados como
// opções.
string get_extra() const { return extra;}
// Método para analisar os argumentos de linha de comando e extrair
// as opções e seus valores contidos nesses argumentos. O vetor argv
// corresponde ao parâmetro argv da função main. A análise das opções
// é efetuada a partir da segunda posição do vetor (argv[1]).
int parse(char * argv[]);
// Métodos para verificar se determinada opção foi fornecida nos argumentos
// Vale para opções e para flags
bool has_option(char shortoption) const;
bool has_option(const string & longoption) const;
};
O programa a seguir ilustra o uso de Argparse, supondo um programa que tenha as opções sem valor complementar -L, -P, e as opções com valor complementar -e, -p, --type.
#include <cstdlib>
#include <iostream>
#include "Argparse.h"
using namespace std;
/*
*
*/
int main(int argc, char** argv) {
Argparse args;
/* Demonstração do analisador de argumentos de linha de comando
As opções contidas nessa demonstração são:
-e EXTENSÃO
--type TIPO
-p CAMINHO
-L
-P
*
* Assim, o programa pode ser executado com qualquer combinação dessas opções,
* as quais podem aparecer em qualquer ordem na linha de comando.
*/
args.add_option('e');
args.add_flag('L');
args.add_flag('P', true);
args.add_option('p');
args.add_option("type", "file");
int n = args.parse(argv);
cout << "Identificou " << n << " opções" << endl;
cout << "ext=" << args['e'] << endl;
cout << "alg: largura=" << args.get_flag('L');
cout << ", profundidade=" << args.get_flag('P') << endl;
cout << "path=" << args['p'] << endl;
cout << "tipo=" << args["type"] << endl;
cout << "extra=" << args.get_extra() << endl;
return 0;
}