[Tutorial] Parseando argumentos em C
Temos várias maneiras de fazer isso, e aqui estarei abordando duas delas, somente com bibliotecas nativas de Unix/Linux.
Maneira rudimentar
Esse é o clássico:
main.c
#include <stdio.h>
int main(int argc, char *argv[]) {
/* O nome do programa conta como um argumento, e é o primeiro,
* sendo assim, precisamos pôr esse if para que não seja nulo.
*/
if(argc < 2) {
printf("Você precisa especificar um argumento!");
return -1;
}
printf("Olá, %s!\n", argv[1]); // argv[0] = nome do programa
return 0;
}
Podemos compilar e rodar: gcc main.c -o main
e ./main "Seu nome aqui"
⚠️ A partir daqui, estarei assumindo que você vai compilar os programas sozinho.
getopt
getopt é usado pra parsear opções na linha de comando, foi feito para parsear de forma simples e checar por opções válidas. Ele usa o GNU getopt.
Funções e argumentos
Todas as funções do getopt retornam inteiros.
int optionIndex = 0 // O getopt_long pede, pois vamos usar num while loop.
// Modo simples, não suportando argumentos longos.
getopt(argc, argv, "optstring, veremos a frente.");
// Modo longo, suportando tanto argumentos simples quanto longos.
getopt_long(argc, argv, "optstring", ArrayDeStructComArgumentosLongos, &optionIndex)
// Modo long, mas argumentos com apenas `-` não são tratados como argumentos.
getopt_long_only(argc, argv, "optstring", ArrayDeStructComArgumentosLongos, &optionIndex)
O que é esse tal optstring?
É uma string, todos os caracteres dessa string representam uma opção, e se essa opção precisar de um argumento, essa opção precisa estar seguida de um :
Por exemplo, "hvl:",
-he
-vnão tem argumentos, mas
-l` sim.
O struct do modo longo
Ele precisa ter 4 valores:
- nome
- se tem um argumento
(no_argument
ou0
caso não tenha,required_argument
ou1
caso seja um argumento obrigatório, eoptional_argument
ou2
, caso seja opcional) - flag
- val
(seu equivalente em modo simples)
E na verdade, é um array de structs.
#include <getopt.h>
static struct option longopts[] = {
// nome, argumento, flag, val
{ "help", no_argument, 0, 'h' },
// Obrigatoriamente, o ultimo "argumento" tem que ser apenas zeros.
{ 0, 0, 0, 0 }
};
Juntando tudo que você aprendeu
Nós já sabemos quais funções temos, sabemos usar o optstring, sabemos "configurar" o struct, só falta uma coisa: optarg
, mas é muito simples: ele é simplesmente o retorno da opção, se ela tiver um. então se eu rodar ./main -a arroz
, optarg
seria arroz.
#include <stdio.h>
#include <getopt.h>
void help(char *command_name){
printf("Usage: %s [arguments]\n", command_name);
}
int main(int argc, char *argv[]) {
// Retorno do getopt + index.
int opt, longIndex;
static struct option longopts[] = {
{"version", no_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{0,0,0,0}
};
/* Se a opção for encontrada, getopt retorna a opção
* Se todas as opções já foram parseadas, retorna -1
* Se encotrar uma opção invalida, retorna ?
* Que pode ser usado pelo "default:"
*/
while((opt = getopt_long(argc, argv, "hv", longopts, &longIndex)) != -1) {
switch(opt) {
case 'h': // Caso a opção seja h ou help.
help("testando");
break;
case 'v': // Caso a opção seja v ou version.
printf("Claramente 0.0.0.0.0\n");
break;
default: // Caso a opção seja invalida
help("testando");
break;
}
}
}
❤️ você chegou até aqui! Se tiver alguma dúvida, por favor deixe-me saber, tentarei respondê-la.