Lihuen
RSSRSS AtomAtom

Parsear argumentos en forma elegante con getopt()

Esta es una buena idea para deshacerse de los problemas de parsear los argumentos pasados al main, usando getopt_long(). Está un poco más claro que en el ejemplo de las páginas del manual y comentado parte por parte.

 #include <stdio.h> /* para printf */
 #include <stdlib.h> /* para exit */
 #define _GNU_SOURCE
 #include <getopt.h> /*para getopt_long*/ 
 
 int main(int argc, char * argv[]){
     int c;
     int digit_optind = 0;
 
     while (1) {
         /*Este while parsea todos los argumentos de argv con la función getopt_long()*/
         int this_option_optind = optind ? optind : 1;
         int option_index = 0;
         /*Esta estructura sirve para convertir los argumentos largos en cortos
         así, si el argumento es --compress en c se guardará 'c', como c tiene
         un argumento opcional, si éste existe se guarda en optarg.
         no_argument, optional_argument y required_argument son macros que se
         expanden a 0, 1 y 2 respectivamente*/
         static struct option long_options[] = {
             {"compress", optional_argument, 0, 'c'},
             {"decompress", no_argument, 0, 'd'},
             {"help", no_argument, 0, 'h'},
             {"verbose", no_argument, 0, 'v'},
             {"file", required_argument, 0, 'f'},
             {0, 0, 0, 0}
         };
        /*La cadena "dhvf:c::" indica que d, h y v no tienen argumentos, f tiene un
        argumento requerido (por eso los dos puntos 'f:') y c tiene un argumento opcional
        (de ahi los dobles dos puntos 'c::')*/
         c = getopt_long (argc, argv, "dhvf:c::",
         long_options, &option_index);
         if (c == -1)
         /*c es -1 cuando se terminan todos los argumentos, entonces sale del while*/
         break; 
 
         switch (c) { 
             case 'c':
                 /*Si uno de los argumentos de main es --compress=LZW o -cLZW entra en este case
                 c vale 'c' y optarg vale "LZW"*/
                 printf ("option c");
                 if (0 != optarg)
                 printf(" con argumento %s", optarg);
                 printf("\n");
                 break; 
 
             case 'd': 
                 /*Si uno de los argumentos de main es --decompress o -d entra en este case*/
                 printf ("option d\n");
                 break;
 
             case 'h':
                 /*y asi siguiendo..*/
                 printf ("option h\n");
                 break;
 
             case 'v':
                 printf ("option v\n");
                 break;
 
             case 'f':
                 printf ("option f con argumento %s\n", optarg);
                 break;
 
             default:
                 /*Si el argumento no machea con ninguna opción conocida, debería ser un error en los
                 parámetros...*/
                 printf ("La función getopt_long ha retornado un carácter desconocido. El carácter es = %c\n", c);
             }
         }
         /*Si siguen apareciendo cosas que no son argumentos, se imprimen hasta que se acaben...*/
         if (optind < argc) {
         printf ("No son opciones pero estan en ARGV: ");
         while (optind < argc)
             printf ("%s ", argv[optind++]);
         printf ("\n");
      }
    exit(0);
 }