getopt_long () – ¿Una forma adecuada de usarlo?

OK, he buscado y encontrado los siguientes dos temas de StackOverflow que me iniciaron en la dirección correcta:

Argumentos de análisis de argumentos para C / UNIX

Pasa los argumentos al progtwig C desde la línea de comando

NOTA: TODO EL CÓDIGO ES PSEUDO-CÓDIGO. PUBLICARÁ CÓDIGO COMPILABLE CUANDO FUNCIONA.

Sin embargo, todavía estoy completamente confundido sobre cómo usar getopt_long () en C. El progtwig que estoy escribiendo se define como el que tiene las siguientes tags posibles (pero puede incluir tantas como sea necesario, completando el rest con valores vacíos) ):

id3tagEd filename -title "title" -artist "artist" -year 1991 -comment "comment" -album "album" -track 1 

Ahora, por lo que leo, necesito utilizar una estructura para las opciones largas, ¿correcto? Si es así, escribí algo como esto:

 struct fields field = { char *[] title; char *[] artist; char *[] album; int year; char *[] comment; int track; } static struct options long_options[] = { {"title", 0, &field.title, 't'}, {"artist", 0, &field.artist, 'a'}, {"album", 0, &field.album, 'b'}, {"year", 0, &field.year, 'y'}, {"comment", 0, &field.comment, 'c'}, {"track", 0, &field.track, 'u'}, {0, 0, 0, 0} } 

Ahora, de lo que recogí, lo llamaría a través de esto:

 int option_index = 0; int values = getopt_long(argc, argv, "tabycu", long_options, &option_index); 

Desde aquí, ¿podría usar estrictamente la estructura de campo y hacer lo que necesito dentro de mi progtwig? Sin embargo, si este es el caso, ¿puede alguien explicar la estructura long_options completa? Leí las páginas del manual y eso, y estoy completamente confundido. Al volver a leer las páginas del manual, puedo ver que puedo establecer variables en nulas y ¿debería establecer todos los requisitos de mis opciones en “required_argument”? ¿Y luego configurando las estructuras a través de un bucle while ()? Sin embargo, veo optarg siendo utilizado. ¿Está establecido por getopt_long ()? ¿O falta en el ejemplo?

Y un último problema, siempre tendré una opción obligatoria sin nombre: nombre de archivo, ¿solo usaría argv [0] para obtener acceso a eso? (Ya que puedo asumir que será el primero).

En una nota al margen, esto se relaciona con un problema de la tarea, pero no tiene nada que ver con solucionarlo, es más fundamental tener que entender el paso de los argumentos y el análisis en C a través de la línea de comandos primero.

En primer lugar, es probable que no desee un 0 para el campo has_arg ; debe ser uno de no_argument , required_arguemnt o optional_argument . En su caso, todos ellos serán required_argument . Además, no está utilizando el campo de marca correctamente, tiene que ser un puntero de entero. Si se establece el indicador correspondiente, getopt_long() lo completará con el número entero que getopt_long() a través del campo val . No creo que necesites esta característica en absoluto. Aquí hay un ejemplo mejor (acortado) para su caso:

 static struct option long_options[] = { {"title", required_argument, NULL, 't'}, {"artist", required_argument, NULL, 'a'}, {NULL, 0, NULL, 0} }; 

Luego, más adelante, puede usarlo adecuadamente (directamente desde la página del manual, agregué algunos comentarios):

 // loop over all of the options while ((ch = getopt_long(argc, argv, "t:a:", long_options, NULL)) != -1) { // check to see if a single character or long option came through switch (ch) { // short option 't' case 't': field.title = optarg; // or copy it if you want to break; // short option 'a' case 'a': field.artist = optarg; // or copy it if you want to break; } } 

Puede extenderse a sus otros campos según sea necesario (¡y agregar algún manejo de errores, por favor!). Nota: si desea usar -artist y -artist como lo ha hecho en su ejemplo, deberá usar getopt_long_only() , que no tiene opciones cortas.

En cuanto a su opción de filename , obtendrá eso como un '?' desde la llamada a getopt_long() , para que pueda manejarlo en ese momento. Sus otras opciones son requerir que sea la primera o la última opción y manejarlas por separado.

Si utiliza la biblioteca popt , podrá crear algo inteligente como lo hizo en su pseudo-código:

 #include  #include "popt.h" struct _field { char *title; char *artist; /* etc */ } field; field.title = NULL; field.artist = NULL; /* HERE IS WHAT YOU WANTED IN YOUR PSEUDO-CODE */ struct poptOption optionsTable[] = { {"title", 't', POPT_ARG_STRING, &field.title, 't' "set the 'title' of the album" }, {"artist", 'a', POPT_ARG_STRING, &field.artist, 'a' "set the 'artist' of the album" }, POPT_AUTOHELP POPT_TABLEEND }; poptContext optCon = poptGetContext(NULL, argc, argv, optionsTable, 0); poptSetOtherOptionHelp(optCon, "[OPTIONS]"); char c; while ((c = poptGetNextOpt(optCon)) >= 0) { switch (c) { case 't': /* do extra stuff only if you need */ break; case 'a': /* do extra stuff only if you need */ break; default: poptPrintUsage(optCon, stderr, 0); exit(1); } } if (field.title) printf("\nTitle is [%s]", field.title); if (field.artist) printf("\nArtist is [%s]", field.artist) 

Sé inteligente que getopt;)