2013-08-06 12 views
10

Sto realizzando un piccolo programma in C che gestisce molti argomenti della riga di comando, quindi ho deciso di utilizzare getopt per ordinarli per me.Utilizzo di getopt in C con argomenti non opzionali

Tuttavia, voglio che due argomenti non opzionali (file di origine e di destinazione) siano obbligatori, quindi devi averli come argomenti durante la chiamata al programma, anche se non ci sono flag o altri argomenti.

Ecco una versione semplificata di quello che devo gestire gli argomenti con le bandiere:

while ((c = getopt(argc, argv, "i:d:btw:h:s:")) != -1) { 
    switch (c) { 
     case 'i': { 
      i = (int)atol(optarg); 
     } 
     case 'd': { 
      d = (int)atol(optarg); 
     } 
     case 'b': 
      buf = 1; 
      break; 
     case 't': 
      time = 1; 
      break; 
     case 'w': 
      w = (int)atol(optarg); 
      break; 
     case 'h': 
      h = (int)atol(optarg); 
      break; 
     case 's': 
      s = (int)atol(optarg); 
      break; 
     default: 
      break; 
    } 
} 

Come posso modificare questo in modo che gli argomenti che non siano opzioni sono trattati anche?

Voglio anche essere in grado di avere le non-opzioni prima dello o dopo le opzioni, quindi come sarebbe gestito?

risposta

13

getopt imposta la variabile optind per indicare la posizione dell'argomento successivo.

Aggiungere il codice simile a questo dopo le opzioni di ciclo:

if (argv[optind] == NULL || argv[optind + 1] == NULL) { 
    printf("Mandatory argument(s) missing\n"); 
    exit(1); 
} 

Edit:

Se si desidera consentire opzioni dopo gli argomenti regolari si può fare qualcosa di simile a questo:

while (optind < argc) { 
    if ((c = getopt(argc, argv, "i:d:btw:h:s:")) != -1) { 
    // Option argument 
    switch (c) { 
     case 'i': { 
      i = (int)atol(optarg); 
     } 
     case 'd': { 
      d = (int)atol(optarg); 
     } 
     case 'b': 
      buf = 1; 
      break; 
     case 't': 
      time = 1; 
      break; 
     case 'w': 
      w = (int)atol(optarg); 
      break; 
     case 'h': 
      h = (int)atol(optarg); 
      break; 
     case 's': 
      s = (int)atol(optarg); 
      break; 
     default: 
      break; 
    } 
    else { 
     // Regular argument 
     <code to handle the argument> 
     optind++; // Skip to the next argument 
    } 
} 
+1

OK, ma il mio ciclo uscirà se gli argomenti obbligatori vengono prima di quelli opzionali, quindi verranno elaborati solo quelli obbligatori e non quelli facoltativi. Come posso risolvere questo? –

+1

È normale richiedere che le opzioni vengano prima degli argomenti. Basta specificarlo nella pagina 'man'. –

+2

Sì, lo so, ma ad esempio con il comando ssh, il flag -p può arrivare prima * o * dopo l'argomento obbligatorio nome utente @ server. Voglio solo sapere come fare questo –

4

Davvero un buon esempio si può trovare qui: GNU Libc Il codice:

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

int 
main (int argc, char **argv) 
{ 
int aflag = 0; 
int bflag = 0; 
char *cvalue = NULL; 
int index; 
int c; 

opterr = 0; 

while ((c = getopt (argc, argv, "abc:")) != -1) 
switch (c) 
{ 
case 'a': 
    aflag = 1; 
    break; 
case 'b': 
    bflag = 1; 
    break; 
case 'c': 
    cvalue = optarg; 
    break; 
case '?': 
    if (optopt == 'c') 
    fprintf (stderr, "Option -%c requires an argument.\n", optopt); 
    else if (isprint (optopt)) 
    fprintf (stderr, "Unknown option `-%c'.\n", optopt); 
    else 
    fprintf (stderr, 
     "Unknown option character `\\x%x'.\n", 
     optopt); 
    return 1; 
default: 
    abort(); 
} 

printf ("aflag = %d, bflag = %d, cvalue = %s\n", 
    aflag, bflag, cvalue); 

for (index = optind; index < argc; index++) 
printf ("Non-option argument %s\n", argv[index]); 
return 0; 
} 

Consente di avere opzioni prima e dopo argomenti. Ho compilato ed eseguito un esempio di prova:

$ ./a.out aa ff bb -a -ctestparam hello 
aflag = 1, bflag = 0, cvalue = testparam 
Non-option argument aa 
Non-option argument ff 
Non-option argument bb 
Non-option argument hello 
Problemi correlati